Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Attribute routing and inheritance

I am playing around with the idea of having a base controller that uses a generic repository to provide the basic CRUD methods for my API controllers so that I don't have to duplicate the same basic code in each new controller. But am running into problems with the routing attribute being recognized when it's in the base controller. To show exactly what the problem I'm having I've created a really simple WebAPI controller.

When I have a Get method in the main Controller and it inherits from the ApiController directly I don't have any problems and this works as expected.

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

When I move the Get method into a base controller it is returning the contents of the 404 page.

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

Some more interesting notes:

  • I can access the action at GET /Test/1. So it is finding it based on the default route still.

  • When I try to access POST /admin/test, it returns the following JSON

    { "Message":"No HTTP resource was found that matches the request URI 'http://test.com/admin/test'.", "MessageDetail":"No type was found that matches the controller named 'admin'." }

Does anyone know of a way to get the routing to work with attributes from a base controller?

like image 490
Jeff Treuting Avatar asked Nov 14 '13 21:11

Jeff Treuting


People also ask

What is attribute routing?

As the name implies, attribute routing uses attributes to define routes. Attribute routing gives you more control over the URIs in your web API. For example, you can easily create URIs that describe hierarchies of resources. The earlier style of routing, called convention-based routing, is still fully supported.

What is the difference between routing and attribute routing in MVC?

ASP.NET MVC also supports new type of routing that is called Attribute Routing. In this, attribute participate to route url to particular action. Note: Attribute Routing is configuring before the Convention Routing or simple Routing. We can use Convention based Routing and Attribute Routing in the same project.

What is difference between conventional and attribute routing?

In short, Convention Routing approaches Routing from the general case; you generally add some routes that will match all or most of your URLs, then add more specific routes for more specialized cases. The other way to approach this problem is via Attribute Routing.

What is the advantage of attribute routing?

Attribute routing gives you more control over the URIs in your web application. The earlier style of routing, called convention-based routing, is still fully supported. In fact, you can combine both techniques in the same project.


Video Answer


2 Answers

Attribute routes cannot be inherited. This was a deliberate design decision. We didn't feel right and didn't see valid scenarios where it would make sense to inherit them.

Could you give a more realistic scenario as to where you would want to use this?

[Update(3/24/2014)]
In the upcoming 5.2 release of MVC Web API, there is going to be an extensibility point called System.Web.Http.Routing.IDirectRouteProvider through which you can enable the inheritance scenario that you are looking for here. You could try this yourself using the latest night builds(documentation on how to use night builds is here)

[Update(7/31/2014)]
Example of how this can be done in Web API 2.2 release:

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);     } } 
like image 108
Kiran Avatar answered Sep 30 '22 21:09

Kiran


Using Web API 2.2, you can:

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

as outlined here: http://www.asp.net/web-api/overview/releases/whats-new-in-aspnet-web-api-22

like image 34
Dejan Avatar answered Sep 30 '22 19:09

Dejan