Route Constraints in MVC
In
this post you will learn how to define ‘Route Constraints’ in MVC Application.
Route Constraints allow us to apply a regular expression to a URL segment to
restrict whether the route will match the request.
Introduction
As
you know every MVC application needs at least one route to define how the
application should handle requests. When you create MVC Application you get
following route defined inside RouteConfig.cs file.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
In
the above example, there are three URL segments. First segment is considered as
Controller (‘Home’ is marked as default controller), second segment is
considered as Action (‘Index’ is marked as default action) and third segment is
considered as Id (‘Id’ is marked as optional). So, in this case these are valid
requests:
http://localhost:55514/Home/Blog/2 (Home ‘Controller’,
Blog ‘Action’ and 2 ‘Id’)
http://localhost:55514/Blog/Category/mvc (Blog
‘Controller’, Category ‘Action’ and mvc ‘Id’)
http://localhost:55514/2013/10/learnmvc.html (2013
‘Controller’, 10 ‘Action’ and learnmvc.html ‘Id’)
Sometimes
you need more control on URLs, look at the last URL. If you are not careful
system will assume 2013 as Controller (2013Controller.cs) and a method called
10. However, just by looking at URL you can tell they should map to different
things.
Why Route
Constraints? Let’s study a problem.
Assume
I want to route following requests that ends with only .html extension to
‘Home’ controller and ‘Blog’ action and also make sure first segment of the URL
should be a valid four digit number (like a year) and second segment of the URL
should be a valid 2 digit number (like month).
Solution
This
is where ‘Route Constraints’ are useful. Constraints allow us to apply a
regular expression to a URL segment to restrict whether the route will match
the request.
Here
is what we need to use:
routes.MapRoute(
name: "MyCustomRoute",
url: "{year}/{month}/{pagename}",
defaults: new { controller = "Home", action = "Blog" },
constraints: new { year = @"\d{4}", month = @"\d{2}", pagename = @".*?$(?<=\.html)" }
);
Remember to put new
route definition before the default simple route because routes are evaluated
in order.
In
above route definition, URL has three segments {year}, {month} and {pagename}.
And for each segments I have defined constraints. For ‘year’ I have used \d{4} which is nothing but a normal regular expression that
will allow any four digits number similarly for ‘month’ I have used \d{2} which is also a normal regular expression that will
allow any two digits number. And for ‘pagename’ segment I have used .*?$(?<=\.html), a regular expression which will allow all
the URLs ends with .html extension. Also notice I have used ‘Home’ as a default
controller and ‘Blog’ as default action.
Few
RegEx for you
Do
not accept URLs ends with .aspx, accepts query string:-
.*?$(?<!\.aspx)
Do
not accept URLs ends with .aspx and .php, accepts query strings:-
.*?$(?<!\.aspx|.php)
Only
accept urls ends with .html and .aspx, accepts query strings:-
.*?$(?<=\.html|.aspx)
So,
in this case following URLs are not valid: because they are not ending with
http://localhost:55514/2013/10/learnmvc.aspx - Not ending with
.html extension
http://localhost:55514/2013a/10/learn-asp.html - Not a valid year
http://localhost:55514/2013/9/learn-asp.html - Not a valid two
digit month
Pretty
easy to work with route constraints, but sometimes it gets painful when you
specify incorrect controller or action. Let’s look at a tool now.
Using Route Debugger
Tool
Let
me tell you about a tool ‘Route Debugger’ which you can use here. Sometimes a
bug in your route can break application because it invokes either an incorrect
controller or action. So, do not worry just install this tool in the
application and it will make your route debugging easier like never before.
To
install this tool, just open Package manage console and type ‘Install-Package
RouteDebugger’ and you done.
Once you installed, look
at the screenshot and see how it works.
If
you do not want Route Debugger, you can turn it off from Web.config.
<add
key="RouteDebugger:Enabled" value="true" />
change it to one given below
<add
key="RouteDebugger:Enabled" value="false" />
Hope
this helps.
Looking back at the example above:
ReplyDeletehttp://localhost:55514/2013/10/learnmvc.aspx
What if I want to redirect the user to the correct route which is http://localhost:55514/2013/10/learnmvc.html?
How can i do that? Thank you
As both URLs matching same route (if constraint not defined) you can use request filtering in controller or you can write your customer filter and redirect the requests on appropriate views.
Deletehi
ReplyDelete