我正试图从RoutingConstaintsSample中同时实现Attribute Routing和VersionedRoute
,但当我在控制器上同时使用这两种方法时,版本化的属性将不再有效。
我需要在属性上修改什么才能让它在属性路由中发挥作用?
对于代码示例,下载示例项目(或者只查看上面链接中的几个文件),然后修改路线如下:
// When I use the RoutePrefix, VersionedRoute no longer works (Sending "Api-Version" through http header doesn't route correctly
// If I remove the RoutePrefix I can use VersionedRoute again
// What do I need to change in its code to be able to use both?
[VersionedRoute("api/Customers", 1)] // This route would be used as http://url/api/customers with a header of "api-version: 1"
[RoutePrefix("api/v1/Customers")] // This route would be used purely through url versioning of http://url/api/v1/Customers
public class CustomersV1Controller : ApiController {
/* Other stuff removed */
[VersionedRoute("api/Customer", 1)] // I'd rather not have to use this here at all and just use a single one on the class, but having both nor just one on either works right now.
[Route("")]
public IHttpActionResult Get()
{
return Json(_customers);
}
}
版本化路线代码
版本约束代码
编辑:如果你需要更多信息,甚至发布想法或东西来尝试,请告诉我:)
第二版:下面是我在Troy Hunt的博客中尝试做的一个例子:http://www.troyhunt.com/2014/02/your-api-versioning-is-wrong-which-is.html
第三版:这是我想编写的代码,因为它可以减少很多开销和魔术串。
[VersionedRoute("api/Customers", 1)] // This route would be used as http://url/api/customers with a header of "api-version: 1"
[RoutePrefix("api/v1/Customers")] // This route would be used purely through url versioning of http://url/api/v1/Customers
public class CustomersV1Controller : ApiController {
/* Other stuff removed */
[Route("")]
public IHttpActionResult Get()
{
// Removed
return Ok(customers);
}
[Route("{id:int}")]
public IHttpActionResult GetById(int id)
{
// Removed
return Ok(customer);
}
}
[VersionedRoute("api/Customers", 2)] // This route would be used as http://url/api/customers with a header of "api-version: 2"
[RoutePrefix("api/v2/Customers")] // This route would be used purely through url versioning of http://url/api/v2/Customers
public class CustomersV2Controller : ApiController {
/* Other stuff removed */
[Route("")]
public IHttpActionResult Get()
{
// Removed
return Ok(customersThatAreDifferentThanV1);
}
[Route("{id:int}")]
public IHttpActionResult GetById(int id)
{
// Removed
return Ok(customerThatIsDifferent);
}
}
编辑:最后一次碰撞,尝试在控制器属性级别,而不是每次操作,每条路线只需写入一次路线版本信息。
Route
和VersionedRoute
属性可以很好地协同工作,但RoutePrefix
属性也应用于VersionedRoute
(尝试访问/api/v1/Customers/api/Customer-设置api版本头时会得到响应)
下面的代码将针对您的示例中返回正确响应的两个URL产生所需的行为,但显然这并不能解决您想要一个VersionedRoute
和一个RoutePrefix
位于类顶部的问题。为此需要另一种方法。但是,您可以为不同的api版本提供单独的控制器。
[RoutePrefix("api")]
public class CustomersV1Controller : ApiController
{
/* Other stuff removed */
[VersionedRoute("Customers", 1)]
[Route("v1/Customers")]
public IHttpActionResult Get()
{
return Json(_customers);
}
}
一个改进是创建自己的属性,而不是Route
,这样你就不需要每次都在版本前加前缀:
public class CustomVersionedRoute : Attribute, IHttpRouteInfoProvider
{
private readonly string _template;
public CustomVersionedRoute(string route, int version)
{
_template = string.Format("v{0}/{1}", version, route);
}
public string Name { get { return _template; } }
public string Template { get { return _template ; } }
public int Order { get; set; }
}
[RoutePrefix("api")]
public class CustomersV2Controller : ApiController
{
/* Other stuff removed */
[VersionedRoute("Customers", 2)]
[CustomVersionedRoute("Customers", 2)]
public IHttpActionResult Get()
{
return Json(_customers);
}
}