Rants and Raves

Thanks for visiting my blog!

Web API 2's Attribute Routing: Looking Deeper
Web API 2's Attribute Routing: Looking Deeper
November 12, 2013

I recently recorded a new module for ASP.NET  Web API course (on Pluralsight) to cover the new features of Web API 2 (it’s not out yet, soon…I promise).

It was fun plumbing the depths of how it works. I generally like the feature but the implementation may change some of your code if you’re dealing with routes under the covers (i.e. for auth or versioning).

If you want a quick overview, I really like Dan Wahlin’s walkthrough of the feature here:

http://weblogs.asp.net/dwahlin/archive/2013/11/11/new-features-in-asp-net-web-api-2-part-i.aspx

While most of us are used to creating routes using the Web API configuration, attributed routes are different. Before attributed routing, when you would look at the route data (e.g. request.GetRouteData()) you would get a route with a name that tied to the configured name. This was really useful for the way to use **UrlHelper **to build your URLs.

In fact, you can get this behavior by supplying names to the individual routes in your attributed routing:

public FooController : ApiController
{
  [Route("api/foos", Name = "Foo")]
  public object Get()
  {
    // ...
  }
}

...

var helper = new UrlHelper(Request);
var url = helper.Link("Foo");

But if you’re traversing the route collection in any way (e.g. in a** ControllerSelector**) it is important to understand where these routes actually are. When you use attribute routing, all the route attributes get added to a common route without a name. This is a special route that is an instance of an internal class called **RouteCollectionRoute **(Source Link). This route has a collection of sub-routes that you can query for that includes *all* the attribute routes. But if you just want the selected route for your call, you can simple ask for it using the RouteData.Values:

var routeData = request.GetRouteData();
var subroutes = (IEnumerable<IHttpRouteData>)routeData.Values["MS_SubRoutes"];
var route = subroutes.First().Route;

The real problem for some is that there is no longer controller name in the route data. This makes sense of course because there is no specific controller that a route points to as attributed routes are related to methods, not controllers. Being aware of these internals may help you solve issues when you use or move to using attributed routes.

Hope this helps!