ASP.NET MVC ROUTING
Introduction
ASP.NET MVC uses ASP.NET routing, to map incoming browser requests to controller
action methods. It is a pattern matching system which is responsible for mapping
the incoming requests to specified MVC Controller/Action. If it fails to map the
route for a incoming request then MVC will show 404 error. ASP.NET Routing makes
use of route table. 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
pattern to route table. If we create any application using MVC 4 or MVC 5, it
has a default route register in Route.config as below.
Global.asax File
- protected void Application_Start()
- {
- AreaRegistration.RegisterAllAreas();
-
- WebApiConfig.Register(GlobalConfiguration.Configuration);
- FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
- RouteConfig.RegisterRoutes(RouteTable.Routes);
- BundleConfig.RegisterBundles(BundleTable.Bundles);
- }
RouteConfig
- public static void RegisterRoutes(RouteCollection routes)
- {
- routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
- routes.MapRoute(
- name: "Default",
- url: "{controller}/{action}/{id}",
- defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional
- }
These line of code would resister a “Default” route with a pattern as
"{controller}/{action}/{id}”. MVC have also given default values for controller
and action this means that if we hit a URL like http:// <ApplicationDomain> /
i.e. without controller the it would get “HomeController” and “Index” as action.
If we hit a URL having only Controller name then it will get “Index” as the
action. “Id” is a parameter which is passed to the action method and kept
optional for this route. We saw that MVC Routing consist of three parts
- Controller Name
- Action Method Name
- Parameter that is passed to the action method
Please note in case you are registering more than one route in your application then route name must be unique for each route. With this default route we can have following types 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 kind to request with help of routes.IgnoreRoute().
Suppose we don’t want MVC to serve the following request as
http://<ApplicationDomain>/Home/
http://<ApplicationDomain>/Home/index
http://<ApplicationDomain>/Home/index/10
For this we need to ignore that route with routes.IgnoreRoute().
- public static void RegisterRoutes(RouteCollection routes)
- {
- routes.IgnoreRoute("Home/*pathInfo}");
-
- routes.MapRoute(
- name: "Default",
- url: "{controller}/{action}/{id}",
- defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
- );
-
-
- }
Now try the entire URL listed in the above table. Only first would be served by Server and we would get 404 for rest of the 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.
- public ActionResult Details(int DepartmentID)
- {
- return Content("received the DepartmentID as : "+ Convert.ToString(DepartmentID));
- }
- Now add a new route for Department as
- public static void RegisterRoutes(RouteCollection routes)
- {
- routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
-
- routes.MapRoute(
- name: " Department",
- url: "Department/{DepartmentID}",
- defaults: new { controller = "Department", action = "Details"}
- );
-
- routes.MapRoute(
- name: "Default",
- url: "{controller}/{action}/{id}",
- defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
- );
- }
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 corresponding controller and action else tries with the next route in routing table and so on. If no route matches the incoming request then server issued a 404 to the client.
Now if you hit http://localhost:[Port]/Department/[int value] then you would get the output as below.
**department id**
If you try to pass any string then you would get below error. As DepartmentID is expected as Interger.
**interger expexted**
While adding the route we can also define the constraints to the route. We can add constraints to a route with the help of
- Regular expressions
- An object that implements IRouteConstraint interface
Now we want to restrict our user to pass only numeric value to call the same action. For this we need to add a constraint from DepartmentID. We can do it with the help of Regular Expression aka RegEx. We can define the constraint as DepartmentID=@"\d+". So our route becomes
- routes.MapRoute(
- name: "Department",
- url: "Department/{DepartmentID}",
- defaults: new { controller = "Department", action = "Details" },
- constraints: new { DepartmentID=@"\d+"}
- );
Now again hit the both URL. First would run as it is. But the output for second URL would change to 404 errors as MVC can’t find the matching route in Route table.
**MVC not found**
Please note it is very much possible to add RegEx constraint to any part of the Route i.d. Controller or Action or Parameter.
We can also create route using IRouteConstraint. It is member of System.Web.Routing and has one method with the signature as
- public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
Suppose we have to restrict our use to enter DepartmentID only in the certain range, say it should be between 20 and 30.
To achieve this we have to create a class which implements IRouteConstraint as below
Now we need to add this constraint with our route.
routes.MapRoute(
name: "Department",
url: "Department/{DepartmentID}",
defaults: new { controller = "Department", action = "Details" },
constraints: new { DepartmentID=new MyConstraint()}
);
Now test the constraint and see the output.
**test the constraints**
**resource not found**
**receive the department id**
Join the conversation! Your thoughts help the community grow.