Q) What is ASP.NET MVC Routing?
Answer: When request is received from the browser, it is routed to URL routing module object which transfers request to the
MVCHttpHandler
. The MVCHttpHandler
is responsible to Map incoming request with controller [by adding suffix controller to the controller value], action and Parameter to action if any. Parameters to action are optional. ASP.NET URL pattern consists of literal and placeholders where placeholders are separated by '/' and defined by {placeholder name}. This process works like dictionary where keys are the placeholder names defined in the URL pattern, and the values are in the URL.
E.g. Let URL be www.myshop.com\products\show\cosmatics
Keys are {controller}/{action}/{id} and their values are products/show/cosmatics
To understand the MVC Application Execution Process, please refer to the following MSDN article.
Route table: Route table gets created in the global.asax. The Global.asax file, also known as the ASP.NET application file. Global.asax contains code for responding to application-level events raised by ASP.NET or by
HttpModules
. The route table is created during the Application Start
event.
Consider the following URL:
We are targeting home controller and index action.This is defined by adding an entry in to the "
routes
" collection using the "maproute
" function.
Let's have a look at the register route function in the Global.asax.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index",
id = UrlParameter.Optional } // Parameter defaults
);
}
routes.MapRoute(string name,string url,object default)
function takes 3 arguments:- Route name
- URL with parameter
- Object of class containing default parameter values
Q) How to create Custom Route?
All the mapped routes are stored as
RouteCollection
in the Routes
property of the RouteTable
class. You can add multiple entries of the route in the route collection by defining unique route name for each key.public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index",
id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Home", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index1",
id = UrlParameter.Optional } // Parameter defaults
);
}
The sequence of the
MapRoute
is important. In our case, route name "Default
" gets executed by default as it is before the route name "Home
". If you look at the controller class, it contains the suffix name "Controller
" to it, but you do not need to specify suffix controller to the URL as MVC routing engine will add suffix "Controller
" to controller name by default.Q) How to Add Constraint to the Route?
Constraints are the rule enforced on the parameter value of the URL. If the parameter values are not inline with the constraint for a route is not handled by the URL routing engine. You can add the constraint to the URL route based on your application requirement. Similar to the custom routes constraint can be added in the
MapRoute
function as argument. Constraints are defined by using regular expressions or by using objects that implement theIRouteConstraint
interface.
Using regular expression: Consider URL http://localhost/home/index/id, constraint to id variable that it should accept number only. We can apply regular expression as argument to the
MapRoute
function overload that accepts constraint as the object. MapRoute(string name,string url,object default,object constraint)
, the application requirement is to add:routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index",
id = "id" } // Parameter defaults
, new { id = @"\d+" } //Constraint
);
id = @"\d+"
regular expression enforces rule to accept number value of id variable. Route that contains id value other than the number is result into HTTP 404 page not found error.
You can get more information about regular expression in the following MSDN article.
Using object that implements the
IRouteConstraint
, consider URL http://localhost/home/index/idconstraint to id variable that it should accept Date
only. Let's create a class that implements the IRouteConstraint
.IRouteConstraint
in force to use method Match
having the following signature, the application requirement is to add:public class CustomContraint : IRouteConstraint
{
#region IRouteConstraint Members
public bool Match(HttpContextBase httpContext, Route route,
string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
throw new NotImplementedException();
}
#endregion
}
Let's add logic that validates
parameterName
id with date value only.public class CustomContraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route,
string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
DateTime dt;
bool result = DateTime.TryParseExact(values["id"].ToString(),
"yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None, out dt);
return result;
}
}
Let's create an object of Class that implements
IRouteConstraint
and pass to the MapRoute
function overload that accepts the constraint object.routes.MapRoute(
"Home", // Route name
"Home/Index1/{id}", // URL with parameters
new { id = DateTime.Now }, // Parameter defaults
new { isLocal = new CustomContraint() } //Constraint
);
New
CustomContraint()
objects implement the IRouteConstraint
interface.