Learn ASP.NET Core Route Constraint in details with lots of examples

Learn ASP.NET Core Route Constraint in details with lots of examples

On my last tutorial I covered ASP.NET Core Convention-Based URL Routing. I will now teach to restrict Routes to a set of URL. This is done by Constraining Routes. Let’s start it with a simple example by add the following route to your application.

app.UseMvc(routes =>
{
    //Int constraint
    routes.MapRoute(
        name: "intConstraint",
        template: "{controller=Home}/{action=Index}/{id:int}");
});

I have applied the int constraint on the route. This tells to match the URL only when the id segment in the URL is of type int.

The constraints are provided after the segment name with a color (:) character.

To test how this int constraint works. Keep the ‘Check’ Action method in your Home Controller:

public IActionResult Check(string id)
{
    ViewBag.ValueofId = id ?? "Null Value";
    return View();
}

Now request the URL – ‘http://localhost:58470/Home/Check/Hello’. You will see a 404 message in your browser (image given below).

route constraint failed

The reason for this is because the id segment needed int value (route constraint) but I provided it a string (‘Hello’). Therefore the route finds no match for the action method and you get the 404 message.

Now request the URL – ‘http://localhost:58470/Home/Check/100’. This time you provided an int value of 100 for the id segment hence the route constraint passes and you get a match.

The view will display – Id value is: 100 as shown in the below image.

route constraint passed

In the above route you can also add the question mark (?) after the int to specify that the route also accepts null for the third segment (‘id’ one).

So the below route constraint tells MVC to match URL that have either null (i.e. empty) or int value for the 3rd segment.

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "intConstraint",
        template: "{controller=Home}/{action=Index}/{id:int?}");
});

Range Constraint

The range constraint tells routes to match only when the segment can be converted to Int and should lie in the specified range.

Consider the below route where I have applied the Range Constraint.

routes.MapRoute(
    name: "rangeConstraint",
    template: "{controller=Home}/{action=Index}/{id:range(5,20)?}");

So it will match URL like:

1. /Home/Index
2. /Admin/List/5
3. /Home/List/15
4. /Home/List/20

It won’t match the URLs like:

1. /Home/Index/3
2. /Home/Index/Hello
3. /Home/Index/21

Important Constraints

The below table gives some of the important & daily-use Constraints.

Constraint Description
int matches int values
float matches float values
decimal matches decimal values
datetime matches datetime values
double matches double values
bool matches ‘true’ or ‘false’
length(len) matches value with the same number of characters specified by parameter ‘len’
length(min,max) matches values that has length between parameters ‘min’ and ‘max’ (inclusive).
max(val) matches int values that are less than val.
min(val) matches int values that are more than val
range(min,max) matches int values that are between ‘min’ and ‘max’ (inclusive)
alpha matches values that have only alphabets (A-Z, a-z)
regex matches values defined by regular expression
Regex Constraint

With Regex Constraints you can apply regular expression in segments. It offers more flexibility. Consider the below route where I have applied regex constraint on the controller segment.

app.UseMvc(routes =>
{
    routes.MapRoute(
    	name: "regexConstraint",
    	template: "{controller:regex(^E.*)=Home}/{action=Index}/{id?}");
});

This route will match URL’s where the first segment (i.e. controller segment) should start with letter ‘E’.

Note that the default values are applied before the constraints. Therefore if you request url – ‘/’ then the default value of Home is applied but since Home does not start with letter ‘E’ therefore you will get 404 error message. Therefore change the controller segment to – controller:regex(^E.*)=Home so that it makes sense.

Let’s take another regex constraint example. Change your route to:

app.UseMvc(routes =>
{
    routes.MapRoute(
    name: "regexConstraint",
    template: "{controller:regex(^H.*)=Home}/{action:regex(^Index$|^About$)=Index}/{id?}");
});

In this route I have applied constraint on both controller and action segment of the URL. The controller segment specifies that it should start with letter ‘H’.

The action segment specifies that the action segment should be either Index or About.

So the following URLs will be matched:

1. /
2. /Home/Index
3. /Home/About/
4. /Home/Index/2
5. /Home/About/3

The following URL will not match:

1. /Edit/Index/3
2. /Home/List

Combining Constraints

You can also combine constraints by character colon (:). See the below route where I am combining alpha and regex constraints, this means the route will match only when the id segment is either null or it should have the following things:

1. Starts with letter ‘H’
2. Should only have characters in it.

app.UseMvc(routes =>
{
    routes.MapRoute(
    name: "combiningConstraint",
    template: "{controller=Home}/{action=Index}/{id:alpha:regex(^H.*)?}");
});

The URLs that will match:

1. /Home/Index/Hello
2. /Home/Index/Hell
3. /Home/Index
4. /
5. /Home/List/Hello-Jackson

The URLs that will not match:

1. /Home/Index/100
2. /Home/About/Jackson

Custom Constraint

If you have a custom route constraining need then you can create your own Custom Constraint. I will now show how to create your custom constraint in the route.

“My custom constraint will allow only god’s names in the URL”. According to Hinduism there are many Gods like ‘Shiv’, ‘Vishnu’, ‘Ram’, ‘Krishn’, etc. My route will only allow the following 6 Gods name for value of id segment:

1. Ram
2. Shiv
3. Krishn
4. Vishnu
5. Brahma
6. Lakshmi

To create this custom constraint, follow the steps below:

1. Create a new folder in your application and name it ‘CustomConstraint’ (or any name of your choice).

2. Crate a new class inside this folder and name it ‘OnlyGodsConstraint’.

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using System.Linq;

namespace URLRouting.CustomConstraint
{
    public class OnlyGodsConstraint : IRouteConstraint
    {
        private string[] gods = new[] { "Ram", "Shiv", "Krishn", "Vishnu", "Brahma", "Lakshmi" };
        public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
        {
            return gods.Contains(values[routeKey]);
        }
    }
}

To create a custom constraint, the class should inherit from IRouteConstraint interface. This interface resides inside the Microsoft.AspNetCore.Routing;namespace.

The IRouteConstraint interface defines a match method and this method decides whether to match the URL or not.

The match method has the following parameters:

1. httpContext – HTTP request information.
2. router – the route applied.
3. routeKey – the segment that is being constrained.
4. RouteValueDictionary – the segment variables.
5. routeDirection – direction of the route (incoming or outgoing).

In the method I have grabbed the value of the id segment using routeKey parameter and checked if it contains the name of any god.

If there is the value of any god only then I will return value of ‘true’ from the method.

The final thing is to apply this constraint on the route so you will need to some configurations in your Startup class as highlighted in the below code:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Routing;
using URLRouting.CustomConstraint;

namespace URLRouting
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<RouteOptions>(options => options.ConstraintMap.Add("allowedgods", typeof(OnlyGodsConstraint)));
            services.AddMvc();
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseDeveloperExceptionPage();
            app.UseStatusCodePages();
            app.UseStaticFiles();
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "combiningConstraint",
                    template: "{controller=Home}/{action=Index}/{id:allowedgods}");
            });
        }
    }
}

In the Configure method you will have to tell ASP.NET CORE that you have created a custom constraint and that will be added to the route dictionary by the name as – ‘allowedgods’.

Then finally you can apply this constraint to the id segment like – {id:allowedgods}”);.
To check it run your application and go to URL – ‘http://localhost:58470/Home/Check/Shiv’. You will see ‘Id value is: Shiv’ on the browser, as shown in the below image:

custom constraint

Now If you go to the URL – ‘http://localhost:58470/Home/Check/Trump’ then there will not be a URL match since ‘Trump’ is not a God.

You can download the full codes of this tutorial from the below link:

Download

Conclusion

In this tutorial you learned to use Route Constaint in ASP.NET Core. Download the source codes and run it in your pc, that will help you to get a better understanding of this topic.

Share this article -

yogihosting

ABOUT THE AUTHOR

This article has been written by the Technical Staff of YogiHosting. Check out other articles on "WordPress, SEO, jQuery, HTML" and more.