Tag Archive: routing

Custom Method Names via Attribute Routing in ASP.NET Web API 2

Microsoft .NET

I am using Web API 2 in my ASP.NET MVC 5 project, and I found myself needing custom routes very quickly. In my scenario I’m building a single-page application using AngularJS, so all the data is received and sent to and from web api’s from ajax calls.

In my scenario I have a collection projects, and each project has a collection of releases; ultimately my web api routing and controller looked like the following.

config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new { id = RouteParameter.Optional });
config.Routes.MapHttpRoute("ActionApi", "api/{controller}/{action}/{id}", new { id = RouteParameter.Optional });
[RoutePrefix("api/Projects")]
public class ProjectsController : ApiController
{
    public ProjectDTO[] Get()
    {
        ...
    }

    public ProjectDTO Get(int id)
    {
        ...
    }

    public HttpResponseMessage Post(Project project)
    {
        ...
    }

    public void Put(Project project)
    {
        ...
    }

    public void Delete(int id)
    {
        ...
    }
}

This is the default, or at least, most common method of using web api based on the HTTP verbs used when calling the service. While this is great for the most basic CRUD operations, I needed to facilitate relational data and have custom named methods. There are many ways to accomplish custom method names gracefully, each has their own pros and cons, but ultimately I’m just going to cut to the chase and demonstrate attribute routing, which I found to be the easiest, and most useful. I spent several days researching ways to do this, and no matter what I did I ran into some limitation, funky issue, or an approach that required custom routes or additional code, or even uninstalling WebDAV or re-configuring your web.config file – sigh. To say the least, I felt they were all terrible solutions.

Finally, I came across this article.
http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2

In short, it saved my sanity. I was able to add a web api as simple as this.

[HttpGet]
[Route("{id}/Releases")]
public ReleaseDTO[] Releases(int id)
{
    ...
}

No changes to my routing. No changes to my web.config file. No uninstalling WebDAV. No weird limitations. What this also gave me was the control over the routes that I wanted so I could have a consistent url scheme that made sense, since the data is relational. The url scheme would be ‘/api/projects/{projectId}/releases’, which makes complete hierarchical sense.

After all the research I did, this would be the approach I would recommend when you need to expand your web api past the basic HTTP verb support. I tossed the idea of using a lot of separate controllers, but felt it would be a maintenance nightmare, and a bit silly to have too many, albeit small controllers when I could logically group things a bit better.