Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebApi2 attribute routing inherited controllers

I'm trying to create basic REST api with a base controller like so:

Base class:

public abstract class WebApiEntityController<TEntity> : ApiController
    where TEntity : EntityBase<TEntity, int>
{
    private readonly IRepository<TEntity> _repository; 
    protected WebApiEntityController(IRepository<TEntity> repository)
    {
        _repository = repository;
    }

    [Route("")]
    [WebApiUnitOfWork]
    public HttpResponseMessage Get()
    {
        return Request.CreateResponse(HttpStatusCode.OK, _repository.ToList());
    }
    [..........]

Derived class:

[RoutePrefix("api/TimesheetTask")]
public class TimesheetTaskController : WebApiEntityController<TimesheetTask>
{
    private readonly IRepository<TimesheetTask> _timeSheetTaskRepository;

    public TimesheetTaskController(IRepository<TimesheetTask> timeSheetTaskRepository) : base(timeSheetTaskRepository)
    {
        _timeSheetTaskRepository = timeSheetTaskRepository;
    }
}

but calling GET on the route ~/api/TimesheetTask/ results in a 404 not found.

According to this answer, attribute routes cannot be inherited. So my question is, how can I write a consistent API for all my domain models without having to copy and paste code?

I know I can do convention routing with this configuration:

config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

but then I'll have to specify the action, and my endpoints will be

/api/{controller]/Get
/api/{controller]/Post

and I don't want that. I can also remove the {action} part of the routeTemplate, but then how will I route to custom actions?

If anyone can help, that would be appreciated. Also, the next step for my domain model API would involve supporting querying, and that can easily get complicated. Is there a library that generates these routes for you? If anyone can help me find such a library it would be much appreciated.

like image 294
Desmond Lee Avatar asked Jul 25 '14 14:07

Desmond Lee


People also ask

What is the base controller for all Web API controller to inherit from?

In ASP.NET MVC 5 and Web API 2, there were two different Controller base types. MVC controllers inherited from Controller ; Web API controllers inherited from ApiController .

What is difference between attribute and conventional routing?

As per our opinion, Attribute Routing provides us more flexibilities as compared to Convention Based Routing. In Attribute Routing, we can manage route as controller level, action level and also area level. Also, it can override the child route, if required.

Which is the attribute used to specify the routing pattern with the Web API?

Web API 2 supports a new type of routing, called 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.

How do I enable attribute based routing?

Enabling Attribute Routing in ASP.NET MVC Enabling attribute routing in your ASP.NET MVC5 application is simple, just add a call to routes. MapMvcAttributeRoutes() method with in RegisterRoutes() method of RouteConfig. cs file. You can also combine attribute routing with convention-based routing.


1 Answers

The answer you quoted has since been updated. As of WebApi 2.2 they created an extensibility point to allow the feature you wanted. Attribute rout can be inherited, but you need to configure it. I had the same requirement for a base API controller and after searching came across the same answer you quoted.

.NET WebAPI Attribute Routing and inheritance

You need to overwrite the DefaultDirectRoutePrivider:

public class WebApiCustomDirectRouteProvider : DefaultDirectRouteProvider {
    protected override System.Collections.Generic.IReadOnlyList<IDirectRouteFactory>
        GetActionRouteFactories(System.Web.Http.Controllers.HttpActionDescriptor actionDescriptor) {
        // inherit route attributes decorated on base class controller's actions
        return actionDescriptor.GetCustomAttributes<IDirectRouteFactory>(inherit: true);
    }
}

With that done you then need to configure it in your web api configuration

public static class WebApiConfig {
    public static void Register(HttpConfiguration config) {
        .....
        // Attribute routing. (with inheritance)
        config.MapHttpAttributeRoutes(new WebApiCustomDirectRouteProvider());
        ....
    }
}
like image 150
Nkosi Avatar answered Sep 21 '22 14:09

Nkosi