带有继承的 Web API 版本控制
Posted
技术标签:
【中文标题】带有继承的 Web API 版本控制【英文标题】:Web API Versioning With Inheritance 【发布时间】:2018-11-22 02:06:30 【问题描述】:我正在尝试让 Web API 版本控制与继承的类一起使用。我正在使用 stock Values
控制器的两个非常简单的变体。
[ApiVersion("1.0")]
[RoutePrefix("api/vversion:apiVersion/Values")]
[ControllerName("Values")]
public class ValuesController : ApiController
// GET api/values
[Route("")]
public IEnumerable<string> Get()
return new string[] "value1", "value2" ;
// GET api/values/5
[Route("id:int")]
public virtual string Get(int id)
return "value from 1";
[ApiVersion("2.0")]
[RoutePrefix("api/vversion:apiVersion/Values")]
[ControllerName("Values")]
public class Values2Controller : ValuesController
//Want to use the method in the base class
//public IEnumerable<string> Get()
//
// return new string[] "value2-1", "value2-2" ;
//
[Route("id:int")]
// GET api/values/5
public new string Get(int id)
return "value from 2";
我的启动配置也很简单。
public static void Register(HttpConfiguration config)
var constraintResolver = new DefaultInlineConstraintResolver()
ConstraintMap = ["apiVersion"] = typeof(ApiVersionRouteConstraint)
;
config.MapHttpAttributeRoutes(constraintResolver);
config.AddApiVersioning(o => o.AssumeDefaultVersionWhenUnspecified = true; );
未覆盖的路线完全按照我的预期工作
http://localhost:32623/api/v1.0/Values/12
-> “从 1 开始的值”
http://localhost:32623/api/v2.0/Values/12
-> “来自 2 的值”
调用v1的默认Get
路由
http://localhost:32623/api/v1.0/Values -> 值1,值2
但是在子控制器上尝试相同的路由会导致错误。
http://localhost:32623/api/v2.0/Values
<Message>
The HTTP resource that matches the request URI 'http://localhost:32623/api/v2.0/Values' does not support the API version '2.0'.
</Message>
<InnerError>
<Message>
No route providing a controller name with API version '2.0' was found to match request URI 'http://localhost:32623/api/v2.0/Values'.
</Message>
</InnerError>
错误消息表明被覆盖的成员需要“1.0”路由,我可以在子类中使用类似的方法解决此问题。
[Route("")]
public override IEnumerable<string> Get()
return base.Get();
但这在更大的应用程序中似乎不太理想。有没有办法让这项工作按照我想要的方式进行,而不需要这些“空”覆盖?
【问题讨论】:
【参考方案1】:您需要做的是覆盖DefaultDirectRoutePrivider
以允许路由继承:
public class WebApiCustomDirectRouteProvider : DefaultDirectRouteProvider
protected override IReadOnlyList<IDirectRouteFactory>
GetActionRouteFactories(HttpActionDescriptor actionDescriptor)
// inherit route attributes decorated on base class controller's actions
return actionDescriptor.GetCustomAttributes<IDirectRouteFactory>(inherit: true);
完成后,您需要在 Web api 配置中配置它以及自定义路由约束
public static void Register(HttpConfiguration config)
var constraintResolver = new DefaultInlineConstraintResolver()
ConstraintMap = ["apiVersion"] = typeof(ApiVersionRouteConstraint)
;
var directRouteProvider = new WebApiCustomDirectRouteProvider();
// Attribute routing. (with inheritance)
config.MapHttpAttributeRoutes(constraintResolver, directRouteProvider);
config.AddApiVersioning(_ => _.AssumeDefaultVersionWhenUnspecified = true; );
所以现在继承值控制器现在将拥有派生控制器中可用的基本路由
出于演示目的
[ApiVersion("1.0")]
[RoutePrefix("api/vversion:apiVersion/Values")]
[ControllerName("Values")]
public class ValuesController : ApiController
[HttpGet]
[Route("")] // GET api/v1.0/values
public virtual IHttpActionResult Get()
return Ok(new string[] "value1", "value2" );
[HttpGet]
[Route("id:int")] // GET api/v1.0/values/5
public virtual IHttpActionResult Get(int id)
return Ok("value from 1");
[ApiVersion("2.0")]
[RoutePrefix("api/vversion:apiVersion/Values")]
[ControllerName("Values")]
public class Values2Controller : ValuesController
//Will have inherited GET "api/v2.0/Values" route
// GET api/v2.0/values/5 (Route also inherited from base controller)
public override IHttpActionResult Get(int id)
return Ok("value from 2");
您会注意到子节点中的路由并未用于被覆盖的操作,因为它也将从基本控制器继承。
【讨论】:
以上是关于带有继承的 Web API 版本控制的主要内容,如果未能解决你的问题,请参考以下文章
带有 IHttpControllerSelector 的 AttributeRouting - Api 版本控制
Java Web学习总结(43)—— Restful API 版本控制