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属性路由.是这样的,还是有人能指出我类似的,支持的技术?
谢谢
在对 ASP.NET 团队的成果进行更多研究之后,看起来System.Web.Http.Routing.IDirectRouteProvider可扩展性有望满足我们的需求。在撰写本文时,这仅适用于 ASP.NET 夜间构建,但有望在我们准备推出时达到 RTM 或至少 CTP。
以下代码显示了如何为我上面的示例实现这一点(原始来源:https : //aspnetwebstack.codeplex.com/workitem/1464)
在方法中Application_Start或WebApiConfig.Register()传递一个新IDirectRouteProvider的MapHttpAttributeRoutes()方法。
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)
您不能使用属性来装饰界面Route。这是因为 Web API 在其自己的框架内工作...它检查所有类型的对象ApiController以确定要路由的内容。它基本上询问您的自定义控制器的方法的属性以创建路由。它不会寻找您的自定义IContract接口,因此它不会关心执行此类路由。
即使您更改 Web API 的代码库以Route从接口读取和处理属性,这将如何工作?接口是契约,不包含功能。那么,如果它看到 的路由"Version",它将把它映射到哪个控制器实现/实例?它任意找到的第一个可以分配给IContract? 最后一个?他们全部?如果全部执行,如何一次执行 N 个控制器方法?
我相信您需要评估一下您对属性路由的理解。它告诉 Web API 框架在该控制器上使用该方法来实现该路由。您无法将其抽象为接口,因为它将无法确定要执行的派生类。