在接口上定义的WebApi属性路由

本文关键字:WebApi 属性 路由 定义 接口 | 更新日期: 2023-09-27 17:52:37

我正在尝试将WCF/REST服务项目转换为MVC/WebAPI。服务层作为不同终端系统的包装器被多次实现,所有实现都遵循接口(IContract)中定义的公共契约。使用WCF,我们在每个公开为web服务方法的方法上定义了[WebInvoke][OperationContract]属性。在WebAPI中,这可以通过在控制器上定义属性路由来简化。然而,我希望在接口上保持路由属性的定义,这样所有的实现都有相似的行为。

下面是旧界面的示例:

[ServiceContract]
public interface IContract
{
    [WebInvoke(UriTemplate = "Version", Method = "GET", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
    [OperationContract]
    string GetVersion();
}

这是我希望得到的工作:

public interface IContract
{
    [Route("Version")]
    [HttpGet]
    string GetVersion();
}

我也会考虑创建一个抽象基类,但这个其他StackOverflow问题让我认为没有合适的替代[WebInvoke(UriTemplate)]使用WebAPI属性路由。是这样吗,或者有人能给我指出一个类似的,支持的技术吗?

谢谢

在接口上定义的WebApi属性路由

在对ASP进行了更多的研究之后。. NET团队,看起来System.Web.Http.Routing.IDirectRouteProvider的可扩展性有望满足我们的需求。在撰写本文时,只能使用ASP。. NET的夜间构建,但希望在我们准备好推出它时达到RTM或至少CTP。

下面的代码显示了如何实现我上面的例子(原始来源:https://aspnetwebstack.codeplex.com/workitem/1464)

Application_StartWebApiConfig.Register()中传递一个新的IDirectRouteProviderMapHttpAttributeRoutes()方法

config.MapHttpAttributeRoutes(new CustomDirectRouteProvider());

按如下方式定义路由提供程序。这基本上只是打开属性继承,所以它会从基类(而不是接口)读取路由。

public class CustomDirectRouteProvider : DefaultDirectRouteProvider
{
    protected override IReadOnlyCollection<IDirectRouteFactory> GetActionRouteFactories(HttpActionDescriptor actionDescriptor)
    {
        return actionDescriptor.GetCustomAttributes<IDirectRouteFactory>(inherit: true);
    }
}

在我的例子中,我们创建了一个抽象的BaseApiController,它为WebAPI方法提供[Route]属性。

public abstract class BaseApiController : ApiController, IContract
{
    [Route("Version")]
    [HttpGet]
    public abstract string GetVersion();
}

我们的终端系统以前是WCF REST服务端点,它实现了一个contract接口。对于WebAPI,控制器现在派生自BaseApiController。(我们还必须将名称从ContractService更改为ContractServiceController。)我们保留IContract是为了向后兼容,但它现在是在BaseApiController上实现的。[RoutePrefix]属性是在控制器上定义的,在本例中是我们的根URL。

[RoutePrefix("")]
public class TestController : BaseApiController
{
    public override string GetVersion();
    {
        return "Version 1.0.0.0";
    }
}

不能用Route属性装饰接口。这是因为Web API在自己的框架内工作……它检查所有类型为ApiController的对象,以确定要路由的对象。它基本上询问你的自定义控制器的方法的属性以便创建路由。它不会寻找您的自定义IContract接口,所以它不会关心做这样的路由。

即使你改变了Web API的代码库,从接口读取和处理Route属性,这将如何工作?接口是一个契约,不包含功能。所以,如果它看到"Version"的路由,它将映射到哪个控制器实现/实例?第一个它任意发现哪一个可以分配给IContract ?最后一个?所有人?如果所有这些,如何同时执行N个控制器方法?

我相信你需要评估一下你对属性路由的理解。它告诉Web API框架对这个路由在这个控制器上使用这个方法。您不能将其抽象为接口,因为它将无法确定要执行的派生类。