Custom Route Constraint in ASP.NET Core MVC 

How to Create Custom Route Constraints in ASP.NET Core MVC

In this article, I am going to discuss How to Create Custom Route Constraints in ASP.NET Core MVC Web Applications with Examples. Please read our previous article, where we discussed Custom Routing in the ASP.NET Core MVC Web Application. We will work with the same example we created in our previous article.

This tutorial aims to demonstrate how you can create a custom route constraint. A custom route constraint enables you to prevent a route from being matched unless some custom condition is matched.

Custom Route Constraints in ASP.NET Core MVC Web Application:

Route Constraints in ASP.NET Core MVC Routing specify conditions that the values of route parameters must meet for a route to match a given URL. They allow us to add validation or filtering logic to our route parameters, ensuring that only specific values are considered valid and eligible for routing.

Custom Route Constraints in ASP.NET Core MVC allow us to define specialized logic to determine whether a route should match a particular request based on certain criteria. This is useful when we need to restrict routes based on specific conditions, such as checking the format of route parameters or applying more complex validation.

How to Create a Custom Route Constraint in ASP.NET Core?

In order to create a Custom Route Constraint in ASP.NET Core MVC, we need to create a class by implementing the IRouteConstraint interface. This interface has a single method called Match, and you need to implement this Match method to define your custom constraint logic. As part of this Match method, we need to check if a particular URL parameter is valid for a constraint. If you go to the definition of the IRouteConstraint interface, then you will see the following.

How to Custom Route Constraints in ASP.NET Core MVC Web Applications with Examples

As you can see, it has one method called Match, and this Match Method determines whether the URL parameter contains a valid value for this constraint. It returns true if the URL parameter contains a valid value; otherwise, false. This method takes the following five parameters.

  • httpContext: An object that encapsulates information about the HTTP request. It encapsulates all HTTP-specific information about an HTTP request, like request, response, sessions, and more. You can also check the HttpContext to see if the request is authenticated and take the appropriate action accordingly.
  • route: The router that this constraint belongs to, i.e., the URL.
  • routeKey: The name of the parameter that is being checked.
  • values: A dictionary that contains the parameters for the URL.
  • routeDirection: An object that indicates whether the constraint check is being performed when an incoming request is being handled or when a URL is being generated. This is an enum class that has two directions. IncomingRequest: A URL from a client is being processed. UrlGeneration: A URL is created based on the route definition.

So, we are going to create a Custom Route Constraint for validating the Alpha Numeric String. That means if the incoming Route Data Contains both Alphabet and Numeric, it will be considered a valid value; if it contains only alphabet or only numeric, it will be considered an invalid value. For this, we don’t have any built-in constraint in ASP.NET Core, and to achieve this in ASP.NET Core MVC Application, we need to create a Custom Route Constraint.

So, create a class file with the name AlphaNumericConstraint.cs within the Models folder and then copy and paste the following code into it. As you can see, the following AlphaNumericConstraint class implements the IRouteConstraint interface and provides an implementation for the Match method. As part of the Match method, we have implemented one alphanumeric regex to check the incoming request parameter to check whether the route parameter contains both Alphabets (A-Z, a-z) and numeric (0-9). If it contains both alphabet and numeric, then it is returning true else, it is returning false.

using System.Text.RegularExpressions;
namespace RoutingInASPDotNetCoreMVC.Models
{
    public class AlphaNumericConstraint : IRouteConstraint
    {
        public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
        {
            //validate input params  
            if (httpContext == null)
                throw new ArgumentNullException(nameof(httpContext));

            if (route == null)
                throw new ArgumentNullException(nameof(route));

            if (routeKey == null)
                throw new ArgumentNullException(nameof(routeKey));

            if (values == null)
                throw new ArgumentNullException(nameof(values));

            if (values.TryGetValue(routeKey, out object? routeValue))
            {
                var parameterValueString = Convert.ToString(routeValue);
                if (Regex.IsMatch(parameterValueString ?? string.Empty, "^(?=.*[a-zA-Z])(?=.*[0-9])[A-Za-z0-9]+$"))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }

            return false;
        }
    }
}
Register the Custom Route Constraint:

We need to register the Custom Route Constraint within the ConstraintMap dictionary in ASP.NET Core. The ConstraintMap is a dictionary that contains the list of route constraints. So, we have to add our custom route constraint to this dictionary with the help of route options. There are two ways using which we can register the Custom Route Constraint service to the dependency Injection contains. We need to register the Custom Route Constraint within the Main method. They are as follows:

Method1: Configuring the Custom Route Constraint Service using AddRouting Method
builder.Services.AddRouting(options =>
{
      options.ConstraintMap.Add(“alphanumeric”, typeof(AlphaNumericConstraint));
});

Method2: Configuring the Custom Route Constraint Service using Configure Method
builder.Services.Configure<RouteOptions>(routeOptions =>
{
routeOptions.ConstraintMap.Add(“alphanumeric”, typeof(AlphaNumericConstraint));
});

Use the Custom Route Constraint in Route Configuration:

Once we register the Custom Route Constraint Service, then we can use the Custom Route Constraint in the Route Template. You have to use the “:” separator between the route parameter and constraints. For example, you can use the alphanumeric (whatever name you provided while registering the service) route constraint as follows:

app.MapControllerRoute(
      name: “CustomRoute”,
      pattern: “{controller}/{action}/{id:alphanumeric?}”,
      defaults: new { controller = “Home”, action = “Index” }
);
In the above code, we have specified the id parameter with Custom Route Constraint alphanumeric and made this parameter optional.

using RoutingInASPDotNetCoreMVC.Models;

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

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

            //Configuring the Custom Route Constraint Service using AddRouting Method
            builder.Services.AddRouting(options =>
            {
                options.ConstraintMap.Add("alphanumeric", typeof(AlphaNumericConstraint));
            });

            //Configuring the Custom Route Constraint Service using Configure Method
            //builder.Services.Configure<RouteOptions>(routeOptions =>
            //{
            //    routeOptions.ConstraintMap.Add("alphanumeric", typeof(AlphaNumericConstraint));
            //});

            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:alphanumeric?}",
                defaults: new { controller = "Home", action = "Index"}
            );

            app.Run();
        }
    }
}

Note: You can use the Custom Route Constraint in both Convention-Based and Attribute-Based Routing in ASP.NET Core Application.

Next, modify the Student Controller as follows. Now, you can access the Index and Details action method without passing any route values. But if you want to pass route values for the Details action method, then the value should be alphanumeric else; it will give a 404 Resource Not Found Error.

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";
        }
    }
}

In the next article, I am going to discuss Attribute Routing in ASP.NET Core MVC Applications. In this article, I explain How to Create Custom Route Constraints in ASP.NET Core MVC Web Application with Examples. I hope you enjoy this Custom Route Constraint in ASP.NET Core MVC Web Application article.

Leave a Reply

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