API Web Api 2 не распознает несколько атрибутов для маршрутизации (версии)

Я пытаюсь реализовать Маршрутизация атрибутов и ************** из RoutingConstaints Sample, но когда я использую оба на контроллере, атрибут с версией больше не работает.

Что мне нужно изменить в атрибуте, чтобы заставить его играть красиво с помощью маршрутизации атрибутов?

В примере кода загрузите образец проекта (или просто просмотрите несколько файлов из приведенной выше ссылки), а затем измените маршруты как таковые:

// When I use the RoutePrefix, ************** no longer works (Sending "Api-Version" through http header doesn't route correctly
// If I remove the RoutePrefix I can use ************** again
// What do I need to change in its code to be able to use both?
[**************("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 */
 [**************("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);
 }
}

Код **************

Код VersionConstraint

Изменить: Пожалуйста, дайте мне знать, если вам нужна дополнительная информация или даже отправьте идеи или вещи, чтобы попробовать:)

Edit2: Вот пример того, что я пытаюсь сделать из блога Troy Hunt: http://www.troyhunt.com/2014/02/your-api-versioning-is-wrong-which-is.html

Edit3: Вот что я хотел бы кодировать, чтобы быть как можно ближе, поскольку это уменьшит количество накладных и магических строк.

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

Изменить: последний удар, пытаясь только написать информацию о версии маршрута один раз за маршрут, на уровне атрибута контроллера, а не за действие.

1 ответ

Атрибуты Route и ************** работают отлично вместе, но ваш атрибут RoutePrefix также применяется к вашему ************** (попробуйте обратиться /api/v 1/Customers/api/Customer - вы получите ответ, когда заголовок api-версии установлен)

Следующий код приведет к желаемому поведению в отношении двух URL-адресов в вашем примере, возвращающих правильные ответы, но, очевидно, это не решит вашу проблему с желанием ************** и one RoutePrefix в верхней части класса, Для этого потребуется другой подход. Однако вы можете иметь отдельные контроллеры для разных версий api.

[RoutePrefix("api")]
public class CustomersV1Controller : ApiController
{
 /* Other stuff removed */
 [**************("Customers", 1)]
 [Route("v1/Customers")]
 public IHttpActionResult Get()
 {
 return Json(_customers);
 }
}

Улучшение будет заключаться в создании вашего собственного атрибута вместо Route, поэтому вам не нужно будет префикс версии каждый раз:

public class Custom************** : Attribute, IHttpRouteInfoProvider
{
 private readonly string _template;
 public Custom**************(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 */
 [**************("Customers", 2)]
 [Custom**************("Customers", 2)]
 public IHttpActionResult Get()
 {
 return Json(_customers);
 }
}

licensed under cc by-sa 3.0 with attribution.