Conventional vs Attribute based routing in .NET Core web applications
Conventional vs Attribute based routing in .NET Core web applications

Conventional vs Attribute Routing In ASP .NET Core Apps

In previous post, we have seen different ways to apply routing in an ASP .NET Core web application. In this post, let’s talk more about how routing can be configured in an application.

Note this article provides information for MVC and Web API type of .NET Core web applications. This can be considered as extension to previous blog post providing more examples and more information about how to setup routing.

Reserved Routing Parameters

Before looking at how to configure routing, let’s look at some common routing parameters which are provided by default in .NET.

These route parameter names should not be used for custom parameter names in routing as it would cause errors in routing the requests. Note that patterns, constraints and default value can be specified for these parameters too.

culture

if culture (e.g. en-us or en-gb) is required in URL, this parameter can be used. This parameter allows only valid culture names in place of this parameter.

controller

This route parameter matches with any controller name.

e.g. if URL pattern specified like /{controller}, then an actual incoming URL /home would redirect the request to HomeController.

action

If this parameter is specified, then it would try to find an action matching with actual value from the URL. If the matching action is found, then request is handed over to it for execution only if HTTP verbs from incoming requests match with allowed HTTP verbs for the action.

e.g. if the URL pattern is /{controller}/{action}, then an incoming URL GET /products/update would be redirected to Update action in ProductsController, if the action allows HTTPGET requests.

area

Controllers can be logically grouped into different areas. For example, a big application might have area for order related functionality, another area for inventory management, etc.

This route parameter can be used to accept area names in place of this parameter.

e.g. if a URL pattern is /{area}/{controller}/{action} and the incoming URL is /Orders/Return/Request, then routing would try to find area with name Orders. If area is found, then controller with name ReturnController and Request action is invoked if controller and action is found and HTTP verbs matched.

Conventional Routing

This type of routing can be setup via UseEndpoints middleware. Below example shows a call to MapControllerRoute, which takes a route name and route parameters.

Route parameters have some defaults, if controller name is not found in incoming URL, home controller would be the default controller and if action name is not found in incoming URL, Index action would be used. The last parameter id is optional.

Route name specified in below example has nothing to do with URL matching with endpoint. It is just logical name for configurations.

Note that these two parameters are not optional. Matching URL to endpoint happens from right to left, so:

  • /” would go to “/home/index
  • /home” would go to “/home/index
  • /index” would be handled by IndexController if it exists. Otherwise this might result in error.

Having a common routing scheme for whole application might be useful and might save a lot of time for developer activities. This type of routing is generally used in MVC web applications.

There are some other methods which can also be used instead of MapControllerRoute:

  • MapDefaultControllerRoute – this is same as MapControllerRoute, except the default values specified already so no parameters are needed.
  • MapAreaControllerRoute – If the application wants to use area routing parameter, then this method can be used to create the route.

Also, these methods can be used to setup multiple routes using conventional routing.

Attribute Routing

As per recommendation from documentation, REST APIs should use attribute routing to model the app’s functionality as a set of resources where operations are represented by HTTP verbs.

It uses MapControllers method inside UseEndpoints middleware as shown in below code.

Route

A RouteAttribute can accept a string. This parameter specifies the route for the resources on which this attribute is placed.

Below example shows a controller which has used Route attribute on controller as well as actions to specify route templates. As the example shows multiple routes can be specified on the same action.

Http Method Attributes

The Http method attributes are generally used to define which verbs can be processed by an action. Those attributes also take a string parameter which can be used to specify the route template or part of route template.

Below is example from previous post. It shows how the API controller uses HttpGetAttribute, HttpPutAttribute and HttpDeleteAttribute for adding a parameter id in the route template.

Combining Routes

To avoid repetitions, the route attributes placed on controller are combined with routes specified in the attributes on individual actions. Below is code example explaining it.

Note that route templates applied to an action that begin with / or ~/ don’t get combined with route templates applied to the controller.

Important Note

Please note that the methods, MapControllerRoute or MapAreaControllerRoute, can be used to map both conventionally routed controllers and attribute routed controllers.

On the other hand, the method MapControllers can only map attribute routed controllers.

I hope this article and previous article provided enough information to you so that you can create your own application to setup routing. Do you have any questions? Let me know your thoughts.

Leave a ReplyCancel reply

This Post Has 2 Comments

  1. mirucki
    mirucki

    If I have a mostly attribute based Web API, but also some pages that are routed conventionally, should I call both MapControllers and MapControllerRoute? Some sites say that is incorrect and that MapControllerRoute already does what MapControllers does.
    Ex:
    endpoints.MapControllers();
    endpoints.MapControllerRoute(“default”, “{controller=App}/{action=Index}/{id?}”);

    1. Manoj Choudhari
      Manoj Choudhari

      IMO, technically it should be possible. Ideally, if a controller is service HTML resource, it typically should use conventional routing. If a controller is serving REST API, then it typically should use attribute routing. (Reference: https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-6.0#mixed-routing-attribute-routing-vs-conventional-routing)

      Although it is possible technically, I would suggest to create two different web apps, one serving HTML page and other only serving API requests. Hope this helps.