.NET WebAPI Attribute Enrutamiento y herencia

Estoy jugando con la idea de tener un controlador base que use un repository genérico para proporcionar los métodos CRUD básicos para mis controladores API para que no tenga que duplicar el mismo código básico en cada nuevo controlador. Pero estoy teniendo problemas con el atributo de enrutamiento que se reconoce cuando está en el controlador base. Para mostrar exactamente cuál es el problema que tengo, he creado un controlador WebAPI realmente simple.

Cuando tengo el método Get en el controlador principal y hereda del ApiController directamente, no tengo ningún problema y esto funciona como se esperaba.

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

Cuando muevo el método Get a un controlador base, devuelve el contenido de la página 404.

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

Algunas notas más interesantes:

  • Puedo acceder a la acción en GET / Test / 1. Por lo tanto, sigue encontrándolo basado en la ruta predeterminada.

  • Cuando bash acceder a POST / admin / test, devuelve el siguiente JSON

    {“Mensaje”: “No se encontró ningún recurso HTTP que coincida con el URI de solicitud ‘ http://test.com/admin/test ‘.”, “MessageDetail”: “No se encontró ningún tipo que coincida con el controlador llamado ‘admin’. ” }

¿Alguien sabe de una manera de hacer que la ruta funcione con los atributos de un controlador base?

Las rutas de atributo no se pueden heredar. Esta fue una decisión de diseño deliberada. No nos sentimos bien y no vimos escenarios válidos en los que tendría sentido heredarlos.

¿Podría darnos un escenario más realista sobre dónde querría usar esto?

[ Actualización (24/3/2014)]
En la próxima versión 5.2 de MVC Web API, habrá un punto de extensibilidad llamado System.Web.Http.Routing.IDirectRouteProvider través del cual puede habilitar el escenario heredado que está buscando aquí. Puede intentarlo usted mismo usando las últimas comstackciones nocturnas (la documentación sobre cómo usar comstackciones nocturnas está aquí )

[ Actualización (31/07/2014)]
Ejemplo de cómo esto se puede hacer en la versión 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); } } 

Usando Web API 2.2, puedes:

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

como se describe aquí: http://www.asp.net/web-api/overview/releases/whats-new-in-aspnet-web-api-22

Lo tengo.

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

Una advertencia aquí es que el parámetro de acción de ruta debe ser el mismo que el nombre de la acción. No pude encontrar una manera de evitar eso. (No puede cambiar el nombre de la ruta con un RouteAttribute)