Click here to Skip to main content
Click here to Skip to main content
Technical Blog

Tagged as

Creating custom route constraints in ASP.NET MVC

, 15 Apr 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
RoutingIn ASP.NET MVC the Routing Module is the URL routing engine that directs the incoming requests to controller actions. There are cases where we need to impose constraints over the incoming requests that are mapped routes. These constraints are used to avoid from directing invalid requests to t

"THE ARTICLE IS NO LONGER MAINTAINED HERE. PLEASE POST ANY FURTHER DISCUSSIONS/QUESTIONS IN MY BLOG http://www.prideparrot.com/blog/archive/2012/3/creating_custom_route_constraints_in_asp_net_mvc" - Author

Routing

In ASP.NET MVC the Routing Module is the URL routing engine that directs the incoming requests to controller actions. There are cases where we need to impose constraints over the incoming requests that are mapped routes. These constraints are used to avoid from directing invalid requests to the controller actions.

In this article we are going to see how to create a simple custom route constraint and supply it to a mapped route.

Constraints

All the mapped routes are stored as RouteCollection in the Routes property of the RouteTable class. The RouteCollection has bunch of extension methods to map or ignore routes. One of the overloaded methods of MapRoute takes the constraints parameter through which we can supply our constraint to the route.

public static Route MapRoute(this RouteCollection routes, string name, 
    string url, object defaults, object constraints);

We can pass constraints in two ways. We can either pass as a regular expression string or we can pass an instance that implements IRouteConstraint. In simple cases we can use regular expressions and in the advanced cases we can go for the IRouteConstraint implementations.

DateConstraint

Let say we have a BlogController with an action Archive that takes a single parameter datetime as a string

public ActionResult Archive(string datetime)
{
    //
}

The input datetime should be in the format yyyyMMdd ex. 20120404. Since the datetime is passed as a string the routing engine directs requests that contain invalid dates also to the action. All the below requests will be received by the action even though the first two requests have invalid dates.

Ex.
http://mysite.com/blog/archive/1 (invalid)
http://mysite.com/blog/archive/posts (invalid)
http://mysite.com/blog/archive/20120404 (valid)

Lets create a date constraint that checks the passed string is a valid datetime and if then direct the request to the action else reject it. For creating that constraint we have to implement the IRouteConstraint interface. The IRouteConstraint is a simple that contains a single method.

public interface IRouteConstraint
{        
    bool Match(HttpContextBase httpContext, Route route, string parameterName, 
        RouteValueDictionary values, RouteDirection routeDirection);
}

If the request is valid then we should return true from the Match method else false.

Here is our implementation which is simple and straight.

public class DateConstraint : IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        DateTime dt;

        return DateTime.TryParseExact(values[parameterName].ToString(), 
        "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None, out dt);
    }
}

Let see how we can pass the constraint on registering the route.

routes.MapRoute(
    name: "archive",
    url: "blog/archive/{datetime}",
    defaults: new { controller = "Blog", action = "Archive" },
    constraints: new { datetime = new DateConstraint() }
);

Issue with the default route

Whenever we create an MVC application a default a route is registered in Global.asax.cs.

routes.MapRoute(
   name: "Default",
   url: "{controller}/{action}/{id}",
   defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

If we have this default route after our constrained route then again the invalid requests are directed to the action, this is because the routing engine works in that way. Whenever the application receives a request the framework matches it with the first registered route in the routing table and if it is ok then directs the request to the corresponding controller and action else tries for the next route and so on. If no route matches the incoming request then the server issues a 404 to the client.

In our example the invalid requests rejected by the constrained route is accepted by the following default route. To avoid that we have to specify another constraint to the default route to avoid any requests that will be directed to the Archive action of the BlogController.

public class EliminateControllerAction : IRouteConstraint
{
    private readonly string _controller;
    private readonly string _action;

    public EliminateControllerAction(string controller, string action)
    {
        _controller = controller;
        _action = action;
    }

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        return String.Compare(values["controller"].ToString(), _controller, true) != 0 
            || String.Compare(values["action"].ToString(), _action, true) != 0;
    }
}

In the Match method we are returning false if the controller is Blog and action is Archive. So all the requests that will be directed to that action will not be matched by this route.

That's it. Now if anyone tries sending an invalid date in the request they will get a 404 resource not found.

Download Sample

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

After2050
Software Developer Trigent Software Private Limited
India India
I'm a software developer from south tip of India. I spent most of the time in learning new technologies. I've a keen interest in client-side technologies especially JavaScript and admire it is the most beautiful language ever seen.
 
I like sharing my knowledge and written some non-popular articles. I believe in quality and standards but blames myself for lagging them.
 
I believe in small things and they makes me happy!
Follow on   Twitter

Comments and Discussions

 
GeneralMy vote of 5 PinmemberGaurav.Kumar.Arora27-Oct-14 12:29 
GeneralMy vote of 5 PinmemberShiv Dutta13-Sep-12 11:44 
GeneralRe: My vote of 5 PinmemberAfter205013-Sep-12 21:52 
GeneralMy vote of 5 PinmemberRupeshKumar24-Jul-12 6:30 
GeneralRe: My vote of 5 PinmemberAfter205013-Sep-12 21:52 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.141223.1 | Last Updated 15 Apr 2014
Article Copyright 2012 by After2050
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid