Routing in ASP.Net MVC

Introduction
 
ASP.NET MVC uses ASP.NET routing to map incoming browser requests to controller action methods. It is a pattern-matching system for mapping incoming requests to specified MVC Controllers and Actions. If it fails to map the route for a incoming request then MVC will show a 404 error. ASP.NET Routing uses a route table. A route table is created when your web application first starts. When an MVC application first starts, the Application_Start() method is called. This method, in turn, calls the RegisterRoutes() method. The RegisterRoutes() method creates the route table and registers one or more route patterns to the route table. If we create an application using MVC 4 or MVC 5, it has a default route register in Route.config as in the following.
 
Global.asax File 
  1. protected void Application_Start()  
  2. {  
  3.    AreaRegistration.RegisterAllAreas();  
  4.   
  5.    WebApiConfig.Register(GlobalConfiguration.Configuration);  
  6.    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);  
  7.    RouteConfig.RegisterRoutes(RouteTable.Routes);  
  8.    BundleConfig.RegisterBundles(BundleTable.Bundles);  
  9. }  
RouteConfig 
  1. public static void RegisterRoutes(RouteCollection routes)  
  2. {  
  3.    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");  
  4.    routes.MapRoute(  
  5.    name: "Default",  
  6.    url: "{controller}/{action}/{id}",  
  7.    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }  
  8.    );  
  9. }  
These lines of code would register a “Default” route with a pattern as "{controller}/{action}/{id}”. MVC also has default values for controllers and actions. That means that if we hit a URL like http:// <ApplicationDomain> / without a controller then it would get “HomeController” and “Index” as the action. If we hit a URL having only Controller name then it will get “Index” as the action. “Id” is a parameter that is passed to the action method and kept optional for this route. We saw that MVC Routing consists of the following three parts.
  • Controller Name
  • Action Method Name
  • Parameter that is passed to the action method
Please note that in case you are registering more than one route in your application then the route name must be unique for each route. With this default route we can have the following types of URL that can be served by MVC.

 Route  Controller  Action  id
 http://<ApplicationDomain>/   HomeController  Index  Null
 http://<ApplicationDomain>/Home/   HomeController  Index  Null
 http://<ApplicationDomain>/Home/index   HomeController  Index  Null
 http://<ApplicationDomain>/Home/index/10   HomeController  Index  10
 http://<ApplicationDomain>/Home/index?id=10   HomeController  Index  10

We can also tell the framework to ignore some kinds of requests using routes.IgnoreRoute(). Suppose we don’t want MVC to serve the following request:
 
http://<ApplicationDomain>/Home/
http://<ApplicationDomain>/Home/index
http://<ApplicationDomain>/Home/index/10
 
For this we need to ignore that route with routes.IgnoreRoute(). 
  1. public static void RegisterRoutes(RouteCollection routes)  
  2. {  
  3.    routes.IgnoreRoute("Home/*pathInfo}");  
  4.   
  5.    routes.MapRoute(  
  6.    name: "Default",  
  7.    url: "{controller}/{action}/{id}",  
  8.    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }  
  9. );  
  10.   
  11. }  
Now try the entire URL listed in the above table. Only first would be served by the Server and we would get 404 for the other requests.
 
server error 
 
Adding Custom Route and Constraints
 
Now to test the Route constraint I have added a new controller as Department with action as Details.
  1. public ActionResult Details(int DepartmentID)  
  2. {  
  3. return Content("received the DepartmentID as : "+ Convert.ToString(DepartmentID));  
  4. }  
Now add a new route for Department as:
  1. public static void RegisterRoutes(RouteCollection routes)  
  2. {  
  3.    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");  
  4.   
  5.    routes.MapRoute(  
  6.    name: " Department",  
  7.    url: "Department/{DepartmentID}",  
  8.    defaults: new { controller = "Department", action = "Details"}  
  9.    );  
  10.   
  11.    routes.MapRoute(  
  12.    name: "Default",  
  13.    url: "{controller}/{action}/{id}",  
  14.    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }  
  15.    );   
  16. }  
Please note we should register a specific route before general route. Whenever the application receives a request the framework matches it with the fist register route in the routing table and if it is ok then directs the request to the corresponding controller and action else tries with the next route in the routing table and so on. If no route matches the incoming request then the server issues a 404 to the client.
 
Now if you hit http://localhost:[Port]/Department/[int value] then you would get output as in the following.
 
Output 
 
If you try to pass a string then you would get the following error. As DepartmentID is expected as Integer.
 
parameter dictionary 
 
When adding the route we can also define the constraints to the route. We can add constraints to a route using:
  • Regular expressions
  • An object that implements IRouteConstraint interface 
Now we want to restrict our user to pass only a numeric value to call the same action. For this we need to add a constraint from DepartmentID. We can do it using a Regular Expression aka RegEx. We can define the constraint as DepartmentID=@"\d+". So our route becomes:
  1. routes.MapRoute(  
  2. name: "Department",  
  3. url: "Department/{DepartmentID}",  
  4. defaults: new { controller = "Department", action = "Details" },  
  5. constraints: new { DepartmentID=@"\d+"}  
  6. );  
Now again hit both URLs. First run it as-is. But the output for the second URL would change to 404 errors since MVC can’t find the matching route in the Route table.
 
The resource cannot be found 
 
Please note that it is very possible to add a RegEx constraint to any part of the Route i.d. Controller or Action or Parameter.
 
We can also create a route using IRouteConstraint. It is a member of System.Web.Routing and has one method with the signature as:
  1. public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)  
Suppose we need to restrict our user to enter a DepartmentID only in the certain range, say it should be between 20 and 30.
 
To do that we need to create a class that implements IRouteConstraint as in the following.
  1. public class MyConstraint :IRouteConstraint  
  2. {  
  3.   
  4.    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDir   ection)  
  5.    {  
  6.       int id=0;  
  7.       int.TryParse(values[parameterName].ToString(), out id);  
  8.       if (20 <= id && id <= 30)  
  9.       return true;  
  10.       else  
  11.       return false;  
  12.    }  
  13. }  
Now we need to add this constraint with our route as in the following:
  1. routes.MapRoute(  
  2. name: "Department",  
  3. url: "Department/{DepartmentID}",  
  4. defaults: new { controller = "Department", action = "Details" },  
  5. constraints: new { DepartmentID=new MyConstraint()}  
  6. );  
Now test the constraint and see the output.
 
The resource cannot be found 
 
The resource cannot be found 
 
Output 


Similar Articles