Маршрутизация и наследование атрибутов .NET WebAPI
Я играю с идеей иметь базовый контроллер, который использует общий репозиторий для предоставления основных методов CRUD для моих контроллеров API, чтобы мне не приходилось дублировать один и тот же базовый код в каждом новом контроллере. Но у меня возникают проблемы с распознаванием атрибута маршрутизации, когда он находится в базовом контроллере. Чтобы показать, какая именно проблема у меня возникла, я создал очень простой контроллер WebAPI.
когда у меня есть метод Get в основном Контроллер и он наследует от ApiController напрямую у меня нет никаких проблем и это работает, как ожидалось.
[RoutePrefix("admin/test")]
public class TestController : ApiController
{
[Route("{id:int:min(1)}")]
public string Get(int id)
{
return "Success";
}
}
когда я перемещаю метод Get в базовый контроллер, он возвращает содержимое страницы 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 it возвращает следующий JSON
{ "Сообщение": "не найден HTTP-ресурс, соответствующий URI запроса'http://test.com/admin/test'.", "MessageDetail": "не найден тип, который соответствует контроллеру с именем 'admin'." }
кто-нибудь знает способ заставить маршрутизацию работать с атрибутами от базового контроллера?
3 ответа:
маршруты атрибутов не могут быть унаследованы. Это было обдуманное дизайнерское решение. Мы не чувствовали себя правильно и не видели действительных сценариев, где было бы целесообразно их унаследовать.
не могли бы вы дать более реалистичный сценарий, где вы хотите использовать это?
[обновление(24.03.2014)]
В предстоящем выпуске 5.2 веб-API MVC будет точка расширения под названиемSystem.Web.Http.Routing.IDirectRouteProvider
С помощью которого можно включить наследование сценарий, который вы ищете здесь. Вы можете попробовать это самостоятельно, используя последние ночные сборки(документация о том, как использовать ночные сборки здесь)[обновление(31.07.2014)]
Пример того, как это можно сделать в Web API2.2
версия:config.MapHttpAttributeRoutes(new CustomDirectRouteProvider()); //--------- public class CustomDirectRouteProvider : 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 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<IDirectRouteFactory> GetActionRouteFactories(HttpActionDescriptor actionDescriptor) { return actionDescriptor.GetCustomAttributes<IDirectRouteFactory> (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)