简体   繁体   English

Web Api 2 API无法识别路由的多个属性(版本控制)

[英]Web Api 2 API not recognizing Multiple Attributes for Routing (Versioning)

I'm trying to implement both Attribute Routing and the VersionedRoute from RoutingConstaints Sample but when I use both on a controller, the versioned attribute no longer works. 我正在尝试从RoutingConstaints Sample实现属性路由VersionedRoute ,但是当我在控制器上使用两者时,版本化属性不再起作用。

What would I need to modify on the attribute to get it to play nice with Attribute Routing? 我需要在属性上修改什么才能让它与属性路由一起使用?

For code example download the sample project (or just look at the few files from the above link) and then modify the routes as such: 对于代码示例,请下载示例项目(或者只查看上面链接中的几个文件),然后修改路由:

// 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);
    }
}

VersionedRoute Code VersionedRoute代码

VersionConstraint Code VersionConstraint代码

Edit: Please let me know if you need more information or even post ideas or things to try :) 编辑:如果您需要更多信息,甚至发布想法或事情,请告诉我:)

Edit2: Here is an example of what I'm trying to do from Troy Hunt's Blog: http://www.troyhunt.com/2014/02/your-api-versioning-is-wrong-which-is.html 编辑2:以下是我试图从特洛伊亨特的博客做的一个例子: http//www.troyhunt.com/2014/02/your-api-versioning-is-wrong-which-is.html

Edit3: Here is what I'd like to code to be as close to since it would reduce a lot of the overhead and magic strings. Edit3:这是我想要编写的代码,因为它会减少很多开销和魔术字符串。

[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);
    }
}

Edit: Last bump, trying to only have to write the route version information once per route, at the controller attribute level and not per-action. 编辑:最后一次尝试,只需要在每个路由上编写一次路由版本信息,在控制器属性级别而不是每次操作。

The Route and VersionedRoute attributes are working fine together, but your RoutePrefix attribute is also applied to your VersionedRoute (try accessing /api/v1/Customers/api/Customer - you'll get a response when the api-version header is set) RouteVersionedRoute属性一起正常工作,但您的RoutePrefix属性也适用于您的VersionedRoute (尝试访问/ api / v1 / Customers / api / Customer - 当设置api-version标头时,您将收到响应)

The following code would produce the desired behaviour with regards to the two URLs in your example returning the correct responses, but obviously this does not solve your problem of wanting one VersionedRoute and one RoutePrefix at the top of the class. 以下代码将针对示例中返回正确响应的两个URL产生所需的行为,但显然这并不能解决您想要在类顶部使用一个VersionedRoute和一个RoutePrefix问题。 Another approach would be needed for this. 为此需要另一种方法。 You can, however, have separate controllers for different api versions. 但是,您可以为不同的api版本提供单独的控制器。

[RoutePrefix("api")]
public class CustomersV1Controller : ApiController
{
    /* Other stuff removed */

    [VersionedRoute("Customers", 1)]
    [Route("v1/Customers")]
    public IHttpActionResult Get()
    {
        return Json(_customers);
    }
}

An improvement would be to create your own attribute instead of Route so you wouldn't need to prefix the version every time: 改进是创建自己的属性而不是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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM