接口上定义的WebApi属性路由

tbe*_*s42 6 c# asp.net-mvc wcf asp.net-web-api

我正在尝试将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();
}
Run Code Online (Sandbox Code Playgroud)

这是我希望得到的工作:

public interface IContract
{
    [Route("Version")]
    [HttpGet]
    string GetVersion();
}
Run Code Online (Sandbox Code Playgroud)

我还会考虑创建一个抽象基类,但是这个其他StackOverflow问题让我觉得没有合适的替代方法来[WebInvoke(UriTemplate)]使用WebAPI属性路由.是这样的,还是有人能指出我类似的,支持的技术?

谢谢

tbe*_*s42 5

在对 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());
Run Code Online (Sandbox Code Playgroud)

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

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

就我而言,我们创建了一个抽象 BaseApiController,它[Route]为 WebAPI 方法提供属性。

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

}
Run Code Online (Sandbox Code Playgroud)

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

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


Han*_*ney 1

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

即使您更改 Web API 的代码库以Route从接口读取和处理属性,这将如何工作?接口是契约,不包含功能。那么,如果它看到 的路由"Version",它将把它映射到哪个控制器实现/实例?它任意找到的第一个可以分配给IContract? 最后一个?他们全部?如果全部执行,如何一次执行 N 个控制器方法?

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