ASP.NET MVC 5 Attribute Routing

ASP.NET MVC 5 Attribute Routing

ASP.NET MVC 5 has a new feature called Attribute Routing that allows a developer to specify the route of controller actions by adding Route Attributes to them. Developers can also add a RoutePrefix Attribute on the controller if each of the controller actions within that controller share a particular route prefix. I'll show a very basic example of this using a ProductsController that will specify both a RoutePrefix on the controller as well as Route Attributes on each controller action.

RouteConfig and MapMvcAttributeRoutes

First, you need to turn on attribute based routing in ASP.NET MVC 5 when you register your routes in RouteConfig. It is a simple one line statement.

public static void RegisterRoutes(RouteCollection routes) {
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapMvcAttributeRoutes();

    // ...
}

Attribute Routing in ASP.NET MVC 5

Next, you need to create a controller and various controller actions and decorate them with various RoutePrefix and Route Attributes. In this case I added a RoutePrefix to the ProductsController telling ASP.NET MVC 5 that all controller action routes will be prefixed with "products".

Now for the Index Controller Action I just specify it as a Route, which means it will respond to the route "~/products", which is the route prefix.

The ViewById Controller Action will respond to the route "~/products/{id}", but there is a constraint on the id that it must be an integer. If {id} isn't an integer, this controller action will not be invoked.

The ViewByCode Controller Action will respond to the route "~/products/{code}", but only when the code consists of letters in the alphabet (a-z or A-Z) and exactly 6 characters in length. If the constraints are not satisfied, the controller action will not be invoked.

[RoutePrefix("products")]
public class ProductsController : Controller {
    private readonly IProductCatalog _productCatalog;

    public ProductsController(IProductCatalog productCatalog) {
        _productCatalog = productCatalog;
    }

    [Route]
    public ActionResult Index() {
        var products = _productCatalog.FetchAll();
        return View(products);
    }

    [Route("{id:int}")]
    public ActionResult ViewById(int id) {
        var product = _productCatalog.FetchProduct(id);
        return View("View", product);
    }

    [Route("{code:alpha:length(6)}")]
    public ActionResult ViewByCode(string code) {
        var product = _productCatalog.FetchProduct(code);
        return View("View", product);
    }
}

The joy here is that it is easy to see the route to a controller action by looking at the RoutePrefix and Route Attributes on the controller and action in ASP.NET MVC 5. You don't have to find it somewhere else. This makes it really convenient for troubleshooting routes. Although I didn't show any examples, this works with ASP.NET Web API 2.

Conclusion

Attribute Routing in ASP.NET MVC 5 and ASP.NET Web API 2 is a welcome new feature. Since Orchard will also be using ASP.NET MVC 5 and ASP.NET Web API 2 in the near future, I am looking forward to the release of it, too!