Custom Route Constraint in ASP.NET Core MVC 

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

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

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 developers to enforce specific rules for the URLs that an application can respond to. These constraints can be used to ensure that a route parameter meets certain conditions, such as being an integer, having a specific range of values, or matching a regular expression. Custom constraints provide a way to implement complex routing logic that cannot be achieved with built-in constraints.

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

Creating custom route constraints in ASP.NET Core MVC allows you to specify more control over routing requests to your controllers and actions based on the URL. This can be useful for validating route data before it reaches your controller, ensuring that your application responds only to URLs that match a certain pattern or criteria.

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 we need to implement this Match method to define our custom constraint logic. This method contains the logic for our constraint and returns a boolean indicating whether the constraint is met. 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 the given constraint. It returns true if the URL parameter contains a valid value; otherwise, it is false. This method takes the following five parameters.

  • HttpContext httpContext: Represents the HTTP context of the current request, providing access to the HTTP request and response objects, among other things.
  • IRouter route: The router that this constraint belongs to, i.e., the URL.
  • string routeKey: The name of the parameter that is being checked.
  • RouteValueDictionary values: A dictionary containing the route parameter names and values for the current request. This includes both the parameters extracted from the URL and any values provided by default or through static routes.
  • RouteDirection routeDirection: An enumeration that indicates whether the constraint check is being performed when an incoming request is being handled or when a URL is being generated. 
Creating Custom Route Constraint in ASP.NET Core MVC

We will 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 implemented one alphanumeric regex to check the incoming request parameter and determine whether the route parameter contains Alphabets (A-Z, a-z) and numeric (0-9). If it contains both alphabet and numeric, then it returns true; otherwise, it returns 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:

Before using our custom route constraint, we must register it with the routing system. This is typically done in the Program.cs file within the Main method. 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 built-in route constraints. So, we have to add our custom route constraint to this ConstraintMap dictionary with the help of route options. We can register the Custom Route Constraint service to the built-in dependency Injection container in two ways. They are as follows:

Method 1: Configuring the Custom Route Constraint Service using the AddRouting Method

This approach allows for the configuration of route options directly as part of the services collection setup. When configuring custom route constraints using AddRouting, you typically work with the RouteOptions.ConstraintMap property. In this example, AlphaNumericConstraint is a class that implements IRouteConstraint, and “alphanumeric” is the name we will use in our route templates to apply this constraint.

builder.Services.AddRouting(options =>
{
      options.ConstraintMap.Add("alphanumeric", typeof(AlphaNumericConstraint));
});
Method 2: Configuring the Custom Route Constraint Service using the Configure Method
builder.Services.Configure<RouteOptions>(routeOptions =>
{
      routeOptions.ConstraintMap.Add("alphanumeric", typeof(AlphaNumericConstraint));
});
Use the Custom Route Constraint in Route Configuration:

Once you register the Custom Route Constraint, then you 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; otherwise, 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";
        }
    }
}
Real-Time Example: Restricting Routes to Specific Days of the Week

Suppose your application should only respond to certain requests on specific days of the week, like processing reports only on weekdays. You could implement a custom route constraint that only matches routes on weekdays.

public class WeekdayConstraint : IRouteConstraint
{
    public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
    {
        if (values.TryGetValue(routeKey, out var value) && value is string stringValue)
        {
            var date = DateTime.Parse(stringValue);
            return date.DayOfWeek != DayOfWeek.Saturday && date.DayOfWeek != DayOfWeek.Sunday;
        }
        return false;
    }
}
When Should We Create Custom Route Constraints in ASP.NET Core MVC?

Custom route constraints are useful in several scenarios:

  • Complex Validation Logic: When the built-in route constraints (such as int, bool, guid, etc.) do not meet your specific validation needs. For example, if you need to validate a parameter against a database value or if the parameter must follow a complex pattern not covered by regular expressions.
  • Enhanced Readability and Maintenance: Custom route constraints can make routes more readable and easier to maintain by encapsulating validation logic within constraints rather than spreading it across controllers or actions. This leads to cleaner code and easier maintenance.
  • Performance Optimization: In some cases, custom route constraints can be used to improve the performance of your application by preventing unnecessary processing for requests that do not meet specific criteria. By filtering out invalid requests early in the routing process, you reduce the workload on your controllers and actions.
  • Security: Custom route constraints can also add an extra layer of security by ensuring that only URLs with valid parameters are processed. This can help prevent certain attacks that rely on manipulating URL parameters.

In the next article, I will 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 *