Take advantage of attribute-based routing in ASP.NET Core to decouple the controller and action names from the route template and allow more flexibility in your routing. Credit: Thinkstock The routing middleware in ASP.NET Core is adept at mapping incoming requests to the respective route handlers. You can set up routing in ASP.NET Core in two different ways: attribute-based routing and convention-based routing. Unlike convention-based routing, in which the routing information is specified at a single location, attribute routing enables you to implement routing by decorating your action methods with attributes. This article presents a discussion of how we can work with attribute-based routing in ASP.NET Core MVC. To work with the code examples provided in this article, you should have Visual Studio 2019 installed in your system. If you don’t already have a copy, you can download Visual Studio 2019 here. Create an ASP.NET Core 3.1 MVC project in Visual Studio 2019 First off, let’s create an ASP.NET Core project in Visual Studio 2019. Assuming Visual Studio 2019 is installed in your system, follow the steps outlined below to create a new ASP.NET Core project in Visual Studio. Launch the Visual Studio IDE. Click on “Create new project.” In the “Create new project” window, select “ASP.NET Core Web Application” from the list of templates displayed. Click Next. In the “Configure your new project” window, specify the name and location for the new project. Optionally check the “Place solution and project in the same directory” check box, depending on your preferences. Click Create. In the “Create a New ASP.NET Core Web Application” window shown next, select .NET Core as the runtime and ASP.NET Core 3.1 (or later) from the drop-down list at the top. Select “Web Application (Model-View-Controller)” as the project template to create a new ASP.NET Core MVC application. Ensure that the check boxes “Enable Docker Support” and “Configure for HTTPS” are unchecked as we won’t be using those features here. Ensure that Authentication is set to “No Authentication” as we won’t be using authentication either. Click Create. Following these steps will create a new ASP.NET Core MVC project in Visual Studio 2019. We’ll use this project in the sections below to illustrate how we can work with attribute routing in ASP.NET Core 3.1. Create a controller class in ASP.NET Core MVC Create a new controller named DefaultController and replace the default source code of the DefaultController with the following code: public class DefaultController : Controller { [Route("")] [Route("Default")] [Route("Default/Index")] public ActionResult Index() { return new EmptyResult(); } [Route("Default/GetRecordsById/{id}")] public ActionResult GetRecordsById(int id) { string str = string.Format ("The id passed as parameter is: {0}", id); return Ok(str); } } Use attribute routing at the controller level in ASP.NET Core Attribute routing can be used both at the controller and action method levels. If we apply the route attribute at the controller level, then the route is applicable to all action methods of that controller. If you examine our DefaultController class, you’ll observe that the Default route is used multiple times when specifying the route template for the action methods. The following code snippet shows how you can specify different route attributes at the controller level to make more flexible use of attribute routing. [Route("Default")] public class DefaultController : Controller { [Route("")] [Route("Index")] public ActionResult Index() { return new EmptyResult(); } [HttpGet] Route("Default/GetRecordsById/{id}")] public ActionResult GetRecordsById(int id) { string str = string.Format("The id passed as parameter is: {0}", id); return Ok(str); } } When using route attributes both at the controller and the action method levels, the route template applied at the controller level is prepended to the route template specified at the action method level. You might often need a common prefix for your controller. When you do, you should use the [RoutePrefix] attribute as shown in the code snippet given below. [RoutePrefix("services")] public class HomeController : Controller { //Action methods } Use attribute routing at the action method level in ASP.NET Core Refer to the DefaultController class shown above. As you can see, we’ve specified three routes in the Index method of the DefaultController class. This implies that each of the following URLs will invoke the Index() action method of the DefaultController. http://localhost:11277 http://localhost:11277/home http://localhost:11277/home/index As in convention-based routing, you can specify parameters in attribute-based routing as well. In other words, attribute-based routing allows you to specify route attributes with parameters. The GetRecordsById action method of the DefaultController class shown earlier is an example. Note that “{id}” in the specified route represents a parameter or a place holder. The id parameter in this example can be anything, such as a string or an integer. What if you would like to restrict the parameter to only integers? You can achieve this by using constraints. Use attribute route constraints in an action method Route constraints are used to thwart invalid requests to controller actions. For example, you might want to ensure that the parameter passed to an action method is always an integer. The syntax of using route constraints is {parameter:constraint}. The following code snippet illustrates this. Note that the id parameter here is always an integer. [Route("Default/GetRecordsById/{id:int}")] public ActionResult GetRecordsById(int id) { string str = string.Format("The id passed as parameter is: {0}", id); return Ok(str); } Use optional parameters in attribute route specifications You can use optional parameters in your route specification too. The following code snippet shows how this can be achieved. Note that the action method in this case would be executed even if the id parameter is not passed. [Route("Sales/GetSalesByRegionId/{id?}")] It’s important to understand that when using attribute routing neither the controller name nor the action method name plays any role in selecting which action method will be executed. Let’s see this with an example. The following code snippet illustrates how the URL has been changed in the route specification for the GetRecordsById action method. [Route("Home/GetRecordsById/{id:int}")] public ActionResult GetRecordsById(int id) { string str = string.Format("The id passed as parameter is: {0}", id); return Ok(str); } You can now invoke the GetRecordsById action method using the following URL: http://localhost:11277/home/GetRecordsById/1 Use multiple attribute route constraints in an action method It is also possible to apply multiple constraints to a parameter. The following code snippet illustrates how this can be achieved. Note the minimum value of the id parameter should be 1, else a 404 error will be returned. [Route("Default/GetRecordsById/{id:int:min(1)}")] public ActionResult GetRecordsById(int id) { string str = string.Format("The id passed as parameter is: {0}", id); return Ok(str); } Use HTTP verbs in attribute routes in an action method You can even use HTTP verbs in attribute routing. The following code snippet shows how this can be achieved. [HttpGet] [Route("Default/GetRecordsById/{id:int:min(1)}")] public ActionResult GetRecordsById(int id) { string str = string.Format("The id passed as parameter is: {0}", id); return Ok(str); } Commonly used attribute route constraints Here is a list of the most commonly used route constraints in ASP.NET Core. bool – used to match a Boolean value datetime – used to match a DateTime value decimal – used to match a decimal value double – used to match a 64-bit floating-point value float – used to match a 32-bit floating-point value guid – used to match a GUID value int – used to match a 32-bit integer value long – used to match a 64-bit integer value max – used to match an integer with a maximum value min – used to match an integer with a minimum value minlength – used to match a string with a minimum length regex – used to match a regular expression Create custom attribute route constraints You can also create your own custom route constraints by creating a class that extends the IRouteConstraint interface and implements the Match method as shown in the code snippet given below. public class CustomRouteConstraint : IRouteConstraint { public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection) { throw new NotImplementedException(); } } Use token replacement in attribute routes at the controller level Attribute routing in ASP.NET Core MVC provides support for another interesting feature named token replacement. You can use the tokens [action], [area], and [controller] in your controller, and these tokens will be replaced by the action, area, and controller names respectively. The following code snippet illustrates how this can be achieved. [Route("[controller]/[action]")] public class HomeController : Controller { private readonly ILogger<HomeController> _logger; public HomeController(ILogger<HomeController> logger) { _logger = logger; } public IActionResult Index() { return View(); } //Other action methods } Attribute routing in ASP.NET Core gives you more control and flexibility over the URIs in your web application. Although convention-based routing can be configured at a single location, which can in turn be applied to all controllers in your application, it is difficult to support certain URI patterns (such as API versioning) with convention-based routing. By using attribute routing, you can decouple the controller and action names from the route template. You can even use a combination of convention-based routing and attribute-based routing in your ASP.NET Core applications. How to do more in ASP.NET Core: How to pass parameters to action methods in ASP.NET Core MVC How to use API Analyzers in ASP.NET Core How to use route data tokens in ASP.NET Core How to use API versioning in ASP.NET Core How to use Data Transfer Objects in ASP.NET Core 3.1 How to handle 404 errors in ASP.NET Core MVC How to use dependency injection in action filters in ASP.NET Core 3.1 How to use the options pattern in ASP.NET Core How to use endpoint routing in ASP.NET Core 3.0 MVC How to export data to Excel in ASP.NET Core 3.0 How to use LoggerMessage in ASP.NET Core 3.0 How to send emails in ASP.NET Core How to log data to SQL Server in ASP.NET Core How to schedule jobs using Quartz.NET in ASP.NET Core How to return data from ASP.NET Core Web API How to format response data in ASP.NET Core How to consume an ASP.NET Core Web API using RestSharp How to perform async operations using Dapper How to use feature flags in ASP.NET Core How to use the FromServices attribute in ASP.NET Core How to work with cookies in ASP.NET Core How to work with static files in ASP.NET Core How to use URL Rewriting Middleware in ASP.NET Core How to implement rate limiting in ASP.NET Core How to use Azure Application Insights in ASP.NET Core Using advanced NLog features in ASP.NET Core How to handle errors in ASP.NET Web API How to implement global exception handling in ASP.NET Core MVC How to handle null values in ASP.NET Core MVC Advanced versioning in ASP.NET Core Web API How to work with worker services in ASP.NET Core How to use the Data Protection API in ASP.NET Core How to use conditional middleware in ASP.NET Core How to work with session state in ASP.NET Core How to write efficient controllers in ASP.NET Core Related content news Spin 3.0 supports polyglot development using Wasm components Fermyon’s open source framework for building server-side WebAssembly apps allows developers to compose apps from components created with different languages. By Paul Krill Nov 18, 2024 2 mins Microservices Serverless Computing Development Libraries and Frameworks how-to How to use DispatchProxy for AOP in .NET Core Take advantage of the DispatchProxy class in C# to implement aspect-oriented programming by creating proxies that dynamically intercept method calls. By Joydip Kanjilal Nov 14, 2024 7 mins Microsoft .NET C# Development Libraries and Frameworks news Microsoft’s .NET 9 arrives, with performance, cloud, and AI boosts Cloud-native apps, AI-enabled apps, ASP.NET Core, Aspire, Blazor, MAUI, C#, and F# all get boosts with the latest major rev of the .NET platform. By Paul Krill Nov 12, 2024 4 mins C# Generative AI Microsoft .NET feature Can Wasm replace containers? WebAssembly revolutionized browser apps, and promises to upend the server stack. How will it impact containers and Kubernetes? Six experts weigh in. By Bill Doerrfeld Nov 11, 2024 12 mins Containers Kubernetes Cloud Native Resources Videos