Custom Routing in ASP.NET Core MVC

Custom Routing in ASP.NET Core MVC Application

In this article, I will discuss Custom Routing in the ASP.NET Core MVC Web Application. Please read our previous article discussing the basic Concepts of Routing and the fundamentals of Conventional Routing in ASP.NET Core MVC Applications. We will work with the same example we created in our previous article. As part of this article, we will discuss the following pointers in detail.

  1. Custom Routing in ASP.NET Core MVC Application.
  2. Custom Routing Without Default Values in ASP.NET Core MVC.
  3. Route Constraints in ASP.NET Core MVC Web Application.
  4. Types of Route Constraints
  5. How do you make Route Parameters Optional in the ASP.NET Core MVC?
  6. How do you Provide Default Route Values in the ASP.NET Core MVC?
Custom Routing in ASP.NET Core MVC Application

Custom Routing in ASP.NET Core MVC allows us to define our own routing patterns for our web application, giving us more control over how URLs are mapped to controller actions. This can be useful when creating SEO-friendly URLs, handling specific routing scenarios, or creating a more organized and structured URL hierarchy. 

Custom Routing Without Default Values in ASP.NET Core MVC Application:

ASP.NET Core MVC allows configuring routing without default values for route parameters (controller, action, and route data). This allows us to create routes that depend only on the URL values without predetermined or default values. If a route parameter is absent from the URL, it will be treated as missing.

Suppose you want to define your own custom route without default values. In that case, you need to modify the MapControllerRoute middleware component within the Main method of the Program class, as shown in the below image. As you can see, we have removed the default values as well as the Optional Parameter from the Pattern (pattern: “{controller}/{action}”)). You can give any name to your route, and here I am providing the Route name as CustomRoute (name: “CustomRoute”).

Custom Routing in ASP.NET Core 6 MVC Web Application

With the above Custom Routing in Place, when we run the application, it will not access the Home Controller Index Action method by default. That means it will not access any controller action method by default. The above MapControllerRoute is the simplest possible convention-based route for an ASP.NET Core MVC Web Application. Now run the application and navigate to the following URLs, and you will see the output as expected. You need to change the port number.
https://localhost:44359/Student/Details
https://localhost:44359/Student/Index

This is working fine. However, what if we wanted to have more specific routes? Say something like the following URLs:
https://localhost:44359/Student/Details/20
https://localhost:44359/Student/Index/10

If you want your controller action methods to match the above URLs, you need to use a Route Constraints feature in the ASP.NET Core MVC Application.

Route Constraints in ASP.NET Core MVC Web Application:

Route constraints in ASP.NET Core MVC are important in controlling the flow of HTTP requests to route handlers based on specific conditions. Constraints allow you to restrict the values that are accepted by route parameters, ensuring that the route is only matched for valid inputs. These constraints ensure that a route will only match and subsequently invoke an action method if the incoming request meets all specified criteria. 

Route constraints are defined within the route template, either inline within the route definition or as part of the route configuration. Constraints can check for various conditions, including data types, value ranges, pattern matching, and custom validation logic.

Implementing Route Constraints in ASP.NET Core MVC:

Route constraints are used in both attribute-based and conventional-based routing to ensure that the values provided in the URL match the expected data types or formats. Let’s say we want to create a route matching the following URLs.
https://localhost:44359/Student/Details/20
https://localhost:44359/Student/Index/10

We can achieve this in two ways: Attribute Routing and Conventional Routing. In our upcoming articles, we will discuss how to achieve the same using Attribute Routing. In this article, let us see how we can achieve the same using Conventional Routing in ASP.NET Core MVC Web Applications.

To achieve the above URL Patterns, we need to modify the MapControllerRoute Middleware Component as follows. As you can see, as part of the pattern, we specify the id parameter (pattern: “{controller}/{action}/{id}”). Here, the id parameter is not optional; it is mandatory, and while accessing any action method, it is mandatory to pass the Id parameter value.

Route Constraints in ASP.NET Core MVC Web Application

As we make the action method mandatory for taking the ID parameter value, we need to change the action methods of our controller with the ID parameter. So, modify the StudentController class as shown below.

using Microsoft.AspNetCore.Mvc;
namespace RoutingInASPDotNetCoreMVC.Controllers
{
    public class StudentController : Controller
    {
        public string Index(string id)
        {
            return $"Index({id}) Action Method of StudentController";
        }
        public string Details(string id)
        {
            return $"Details({id}) Action Method of StudentController";
        }
    }
}

With the above changes in place, now run the application and navigate to the following URLs, and you will see that methods are executed as expected.
https://localhost:44359/Student/Details/20
https://localhost:44359/Student/Index/10

This is working fine. But, the problem with the above route is that it can accept any value. Instead of an integer, if you pass a string value, it also accepts and executes the action methods, as shown below.
https://localhost:44359/Student/Details/ABC
https://localhost:44359/Student/Index/ABC

If you want to restrict the id parameter value to be an integer only, then you need to use a concept called Route Constraint in ASP.NET Core. So, what we need to do is, while defining the Route, we can explicitly tell that this parameter is going to accept only integer, boolean, or any particular data type value.

In our example, we want to restrict the id parameter to accept only integer values. So, we need to modify the MapControllerRoute Middleware Component as follows. As you can see, as part of the pattern, we specify the id parameter to accept int values only (pattern: “{controller}/{action}/{id:int}”). This is called inline Route Constraint. Inline constraints are specified directly within the route template by appending a colon (:) followed by the constraint name to a route parameter.

Custom Route Constraints in ASP.NET Core MVC Web Application

Note: The {id:int} in the pattern of MapControllerRoute Middleware Component specifies that whatever is in this part of the URL must be an integer. Otherwise, the URL does not map to this route.

With the above changes in place, now run the application and navigate to the following URLs, and you will see a 404 error. This is because we are passing the Id parameter value as ABC here.
https://localhost:44359/Student/Details/ABC
https://localhost:44359/Student/Index/ABC

Now, pass the id parameter value as an integer, and you should get the output as expected.

Types of Route Constraints

You can use many route constraints. Some of them are as follows.

  • int: Matches any integer.
  • bool: Matches a Boolean value.
  • datetime: Matches a valid DateTime value.
  • decimal: Matches a decimal number.
  • double: Matches a double number.
  • guid: Matches a Guid value.
  • long: Matches a long number.
  • min(value): Matches an integer greater than or equal to the specified minimum value.
  • max(value): Matches an integer less than or equal to the specified maximum value.
  • range(min, max): Matches an integer within a specified range.
  • alpha: Matches one or more alphabetical characters.
  • regex(expression): Matches input based on the specified regular expression.
  • length(min,max): Restricts the length of the parameter value.
How Do We Make Route Parameters Optional in the ASP.NET Core MVC Application?

In ASP.NET Core MVC, you can make route parameters optional by specifying default values for those parameters. This approach allows you to define routes matching URLs with or without specific route parameter values. Before understanding How to Make the Route Parameter an Optional Parameter, let us first change the StudentController class as shown below. 

using Microsoft.AspNetCore.Mvc;
namespace RoutingInASPDotNetCoreMVC.Controllers
{
    public class StudentController : Controller
    {
        public string Index()
        {
            return $"Index() Action Method of StudentController";
        }
        public string Details(string id)
        {
            return $"Details({id}) Action Method of StudentController";
        }
    }
}

As you can see in the above code, the Index action method does not take any parameter, while the Details action method takes one parameter. We need to invoke the Index action method without a parameter as follows.
https://localhost:44359/Student/Index

On the other hand, we need to make the id parameter of the Details action method optional. It means the Details action method should be invoked using the following two URLs.
https://localhost:44359/Student/Details
https://localhost:44359/Student/Details/10

In order to achieve this, we need to use optional parameters in our convention-based routing by adding a question mark “?” to the optional route parameter constraint. In our example, we want to mark the id parameter as an optional parameter and accept only integer values. So, in the URL pattern, we need to specify the id parameter as “id:int?“. We need to modify the MapControllerRoute Middleware Component as follows.

How to Make Route Parameters Optional in ASP.NET Core MVC Application

Here, “id:int?” says that id is an optional parameter, but if you pass any value, it should be of type integer. You can define only one optional parameter per route, which must be the last parameter. With the above changes in place, now run the application and navigate to the following URLs, and you will get the data as expected.
https://localhost:44359/Student/Index
https://localhost:44359/Student/Details
https://localhost:44359/Student/Details/10

How Do We Provide Default Route Values in the ASP.NET Core MVC application?

Default Route values are useful when you have optional route parameters. As of now, you can observe that whenever we run the application, by default, it loads the base URL (https://localhost:44359/) of the application and gives us a 404 error. This is because we have not set any default values for our Route parameter. If we have not specified the name of the controller or action method in the URL, what should the controller and action method execute?

Let us proceed and understand how we can specify the default values for our Route Parameter so that if we do not specify the Controller or Action method name in the URL or when the application launches, it should take the default values from the Route and execute the action method.

So, using Default values, we can specify what happens if parts of the route are not provided in the URL. For example, when we navigate to the following two URLs
https://localhost:44359/
https://localhost:44359/Home

We want to map the above two URLs to the Home Controller and Index action method of the Application. To do so, we need to specify the default controller and action method name in the MapControllerRoute Middleware Component URL Pattern. So, modify the MapControllerRoute Middleware Component within the Main method of the Program class as follows. Here, we have specified the default controller name as Home, the default action method name as Index, and Id as the Route parameter, which is optional as well as that parameter can accept only integer values (pattern: “{controller=Home}/{action=Index}/{id:int?}“).

How to Provide Default Route Values in ASP.NET Core MVC Application

With the above changes in place, now run the application and visit the following two URLs, and you should get the output as expected.
https://localhost:44359/
https://localhost:44359/Home

You can also map the default values for the route parameter by using the defaults parameter of the MapControllerRoute Extension method, as shown in the image below. 

Custom Routing in ASP.NET Core MVC Application

The following is the complete Program.cs class file code.

namespace RoutingInASPDotNetCoreMVC
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            // Add services to the container.
            builder.Services.AddControllersWithViews();

            var app = builder.Build();

            // Configure the HTTP request pipeline.
            if (!app.Environment.IsDevelopment())
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            app.MapControllerRoute(
                name: "CustomRoute",
                pattern: "{controller}/{action}/{id:int?}",
                defaults: new { controller = "Home", action = "Index" }
            );

            app.Run();
        }
    }
}

With the above changes in place, run the application, and it should work as expected.

In the next article, I will discuss Custom Route Constraint in ASP.NET Core MVC Applications. In this article, I explain custom routing in ASP.NET Core MVC Web Application with examples. I hope you enjoy this Custom Routing in ASP.NET Core MVC Web Application article.

Leave a Reply

Your email address will not be published. Required fields are marked *