ASP.NET CORE Attribute Routing

In this tutorial will discuss attribute routing and will understand when choose between attribute routing and conventional based routing

Attribute routing allows us developers to define routes right next to the actions they map to. This allows for us to get very fine-grained control over what routes map to which actions.

As with convention-based routing, the routes are still evaluated against URLs, but unlike in convention-based routing, all routes are evaluated at the same time, in order to find the best match. Because of this, attribute routing wants us to be very specific when defining routes and route patterns.

Setup Attribute Routing.

In order to use attribute routing in ASP.NET Core 3.1, we need to do two things in our Startup.cs file.

First, just like with convention-based routing, we need to include the MVC controllers and views in the service layer:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
}

Next, we need to call the new MapControllers() method inside of the UseEndpoints() method:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{    
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

The MapControllers() method enables attribute routing, and can be used in conjunction with other methods like MapControllerRoute()MapAreaControllerRoute(), etc.

Where Are Attribute Routes Defined?

Unlike in convention-based routing, where the routes are defined in the Startup.cs file, attribute routes are defined in the controller classes as attributes on actions. For example:

[Route("Home")]
public class HomeController: Controller
{
    [Route("Index")]
    public IActionResult Index(int id = 0)
    {
        return View();
    }
}

You may notice that the [Route] attribute has been applied to both the action and the controller; this is different from .NET Framework MVC applications, where we needed to use the now-deprecated [RoutePrefix] attribute on the controller class.

The defined routes will now match the following URL:

/home/index

Route Evaluation Order

Convention-based routing evaluates matching routes in the order they are defined. By contrast, attribute routing creates a tree of all routes and evaluates them simultaneously. What this means is that more-specific routes will always be evaluated earlier than less-specific ones.

Let’s say we have the following attributes:

[Route("/post/{category}/{id}")]

and

[Route("/post/{**article}")]

In attribute routing, the first route will always be evaluated before the second, because it is more specific (and, really, that’s the only logical way to do this). Therefore, most of the time you do not need to worry about the order of evaluation for your attribute routes.

However, if for some reason you want to force routes to evaluate in a specific order, you can do so by setting the order:

[Route("/post/{**article}", Order = 1)]

[Route("/post/{category}/{id}", Order = 2)]

In general, you should avoid relying on Order, and instead define appropriately-specific routes for every action you need routed.

You can watch our video version of this tutorial with step by step explanation.