ASP.NET MVC 5 brings attribute based routing

Gain convenience and finer grain control over your URLs with MVC 5

Microsoft has been busy the past couple weeks. Hot off the heels of the .NET framework 4.5.1 release comes the launch of Visual Studio 2013, Entity Framework 6, MVC 5, WebApi 2, and more. One of the most subtle new features in MVC 5, attribute routing, is also one of the best improvements.

Since Microsoft first brought the MVC pattern into the .NET framework with MVC 1, developers have been constructing their web application URL routes using convention-based routing via Route Collections. A typical route registration for a simple site might look like the following:

This has worked well for years and was a major improvement over Web Forms, but has always been a pain point for more complex sites, specifically those with aggressive internet marketing goals involved. As a site becomes larger, it becomes harder to understand just how the routes are being processed since the routing is established in one shot at the application level. This can cause major troubleshooting issues which result in the fear of modifying anything at all lest you break another route down the line.

Enabling attribute based routing

With MVC 5 and attribute based routing, you gain finer control of your routes at both the controller and action level. Enabling attribute routing in your project is simple, just add a call to routes.MapMvcAttributeRoutes(); in your RegisterRoutes function.

Controller level routing

For starters, the routing attributes [RoutePrefix] and [Route] can be added at the controller level which apply to all actions within the controller unless a specific route is added to an action.

For example, if every action in a controller should be under the path /stats/ and the default route should be to the Index action you could define your controller as:

That saves you from having to define a route prefix for every action in the controller.

Routing constraints

You also gain the ability to do constraint based routing on your actions. Similar to function overrides, a route will only be matched if the data type matches, otherwise the request will fall through to the next route matching the pattern, looking for a supported data type.

Supported constraints are:

alpha Matches uppercase or lowercase Latin alphabet characters (a-z, A-Z) {x:alpha}
bool Matches a Boolean value. {x:bool}
datetime Matches a DateTime value. {x:datetime}
decimal Matches a decimal value. {x:decimal}
double Matches a 64-bit floating-point value. {x:double}
float Matches a 32-bit floating-point value. {x:float}
guid Matches a GUID value. {x:guid}
int Matches a 32-bit integer value. {x:int}
length Matches a string with the specified length or within a specified range of lengths.


long Matches a 64-bit integer value. {x:long}
max Matches an integer with a maximum value. {x:max(10)}
maxlength Matches a string with a maximum length. {x:maxlength(10)}
min Matches an integer with a minimum value. {x:min(10)}
minlength Matches a string with a minimum length. {x:minlength(10)}
range Matches an integer within a range of values. {x:range(10,50)}
regex Matches a regular expression. {x:(^\d{3}-\d{3}-\d{4}$)}

You can even apply multiple constraints to a single route to gain precise control over what URLs with route to what action.

Legacy Support

Finally, not only will the convention-based routing still work, but you can use attribute based routing simultaneously! As long as you activate the attribute based routing in your RegisterRoutes function, you can continue to use your convention-based routing as you have always done in the past and simply add attribute based routing where appropriate / convenient.

ITWorld DealPost: The best in tech deals and discounts.