Attribute Routing in ASP.NET MVC 5
Routing is how ASP.NET MVC matches a URI to an action. MVC 5 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 application.
The earlier style of routing, called convention-based routing
Why Attribute Routing?
For example, a socially enhanced e-commerce website could have the following routes:
{productId:int}/{productTitle}
Mapped toProductsController.Show(int id)
{username}
Mapped toProfilesController.Show(string username)
{username}/catalogs/{catalogId:int}/{catalogTitle}
Mapped toCatalogsController.Show(string username, int catalogId)
In previous version of ASP.NET MVC, the rules would be set in the RouteConfig.cs
file, and point to the actual controller actions
routes.MapRoute(
name: “ProductPage”,
url: “{productId}/{productTitle}”,
defaults: new { controller = “Products”, action = “Show” },
constraints: new { productId = “\\d+” }
);
When the route definitions are co-located with the actions, within the same source file rather than being declared on an external configuration class, it can make it easier to reason about the mapping between URIs and actions.
[Route(“{productId:int}/{productTitle}”)]
public ActionResult Show(int productId)
{
}
Enabling Attribute Routing
To enable attribute routing, call MapMvcAttributeRoutes during configuration.
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute(“{resource}.axd/{*pathInfo}”);
routes.MapMvcAttributeRoutes();
}
}
You can also combine attribute routing with convention-based routing.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute(“{resource}.axd/{*pathInfo}”);
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: “Default”,
url: “{controller}/{action}/{id}”,
defaults: new { controller = “Home”, action = “Index”, id = UrlParameter.Optional }
);
}
Optional URI Parameters and Default Values
You can make a URI parameter optional by adding a question mark to the route parameter. You can also specify a default value by using the form parameter=value.
public class BooksController : Controller
{
// eg: /books
// eg: /books/1430210079
[Route(“books/{isbn?}”)]
public ActionResult View(string isbn)
{
if (!String.IsNullOrEmpty(isbn))
{
return View(“OneBook”, GetBook(isbn));
}
return View(“AllBooks”, GetBooks());
}
// eg: /books/lang
// eg: /books/lang/en
// eg: /books/lang/he
[Route(“books/lang/{lang=en}”)]
public ActionResult ViewByLanguage(string lang)
{
return View(“OneBook”, GetBooksByLanguage(lang));
}
}
In this example, both /books and /books/1430210079 will route to the “View” action, the former will result with listing all books, and the latter will list the specific book. Both /books/lang and /books/lang/en will be treated the same.
Route Prefixes
Often, the routes in a controller all start with the same prefix.
public class ReviewsController : Controller
{
// eg: /reviews
[Route(“reviews”)]
public ActionResult Index() { … }
// eg: /reviews/5
[Route(“reviews/{reviewId}”)]
public ActionResult Show(int reviewId) { … }
// eg: /reviews/5/edit
[Route(“reviews/{reviewId}/edit”)]
public ActionResult Edit(int reviewId) { … }
}