Атрибут .NET WebAPI Маршрутизация и наследование

Я играю с идеей создания базового controllerа, который использует общий repository для предоставления основных методов CRUD для моих controllerов API, поэтому мне не нужно дублировать один и тот же базовый код в каждом новом controllerе. Но у меня проблемы с атрибутом маршрутизации, который распознается, когда он находится в базовом controllerе. Чтобы точно показать, в чем проблема, с которой я столкнулся, я создал действительно простой controller WebAPI.

Когда у меня есть метод Get в основном controllerе и он наследуется от ApiController, у меня нет проблем, и это работает так, как ожидалось.

[RoutePrefix("admin/test")] public class TestController : ApiController { [Route("{id:int:min(1)}")] public string Get(int id) { return "Success"; } } 

Когда я перемещаю метод Get в базовый controller, он возвращает содержимое страницы 404.

 [RoutePrefix("admin/test")] public class TestController : TestBaseController { } public class TestBaseController : ApiController { [Route("{id:int:min(1)}")] public string Get(int id) { return "Success"; } } 

Еще несколько интересных замечаний:

  • Я могу получить доступ к действию в GET / Test / 1. Таким образом, он находит это на основе маршрута по умолчанию.

  • Когда я пытаюсь получить доступ к POST / admin / test, он возвращает следующий JSON

    {«Сообщение»: «HTTP-ресурс не найден, который соответствует запросу URI« http://test.com/admin/test ».», «MessageDetail»: «Тип не найден, который соответствует controllerу с именем« admin ». ” }

Кто-нибудь знает, как заставить маршрутизацию работать с атрибутами с базового controllerа?

Маршруты атрибутов не могут быть унаследованы. Это было преднамеренное дизайнерское решение. Мы не чувствовали себя правильно и не видели реальных сценариев, где было бы разумно наследовать их.

Не могли бы вы дать более реалистичный сценарий относительно того, где вы хотели бы использовать это?

[ Обновление (3/24/2014)]
В предстоящем выпуске Web-API MVC 5.2 будет существовать точка расширения, называемая System.Web.Http.Routing.IDirectRouteProvider через которую вы можете включить сценарий наследования, который вы ищете здесь. Вы можете попробовать это самостоятельно, используя новейшие ночные сборки (документация о том, как использовать ночные сборки здесь )

[ Обновление (7/31/2014)]
Пример того, как это можно сделать в версии Web API 2.2 :

 config.MapHttpAttributeRoutes(new CustomDirectRouteProvider()); //--------- public class CustomDirectRouteProvider : DefaultDirectRouteProvider { protected override IReadOnlyList GetActionRouteFactories(HttpActionDescriptor actionDescriptor) { // inherit route attributes decorated on base class controller's actions return actionDescriptor.GetCustomAttributes (inherit: true); } } 

Используя Web API 2.2, вы можете:

 public class BaseController : ApiController { [Route("{id:int}")] public string Get(int id) { return "Success:" + id; } } [RoutePrefix("api/values")] public class ValuesController : BaseController { } config.MapHttpAttributeRoutes(new CustomDirectRouteProvider()); public class CustomDirectRouteProvider : DefaultDirectRouteProvider { protected override IReadOnlyList GetActionRouteFactories(HttpActionDescriptor actionDescriptor) { return actionDescriptor.GetCustomAttributes (inherit: true); } } 

как описано здесь: http://www.asp.net/web-api/overview/releases/whats-new-in-aspnet-web-api-22

Понял.

 [Route("api/baseuploader/{action}")] public abstract class BaseUploaderController : ApiController { [HttpGet] public string UploadFile() { return "UploadFile"; } } [Route("api/values/{action}")] public class ValuesController : BaseUploaderController { [HttpGet] public string Get(int id) { return "value"; } } 

Одно из предостережений здесь состоит в том, что параметр действия маршрута должен быть таким же, как имя действия. Я не мог найти способ обойти это. (Вы не можете переименовать маршрут с помощью атрибута RouteAttribute)

Interesting Posts
Давайте будем гением компьютера.