ASP.NET MVC routing
Routing is important feature of ASP.NET MVC. The routing module is responsible for mapping incoming browser request to unique controller action method. Routing is an entry point of ASP.NET MVC Request life cycle
Below picture shows how ASP.NET MVC handles requested url
Routing data gets filled in Application_Start event. It uses RouteTable object to fill routes. Route engine uses this table to match incoming request and execute action methods.
You can add route details to application by adding Route object to static Routes property of RouteTable. The Routes property is RouteCollection object.
Below is an example of adding routes to RouteTable. You can use Global.asx file or RouteConfig.cs from App_Start folder to add Routes.
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Order", // Route name
"orders/{controller}/{action}/{id}",// URL with parameters
new { controller = "order", action =
"Index", blogid = "" } // Parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index",
id = "" } // Parameter defaults
);
}
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
}
}
I have use Global.asax file. I added two routes with name order and default.
All below URLs will match Order route.
http://example.com/orders/customer/showorder/4567
http://example.com/orders/customer/updateorder/4567
http://example.com/orders/customer/placeorder
http://example.com/orders/report/orders
http://example.com/orders/report/customer
http://example.com/orders/report/customer/4567
Notice that each url has orders before any other part of url and route which is added with name Order has similar URL parameters. Some of URLs listed above does not have id parameter, still it is taken care by Order route as default empty string has provided to id parameter.
URLs which are not mapped by first route, will be mapped to default route. Here second route is most generic route and will be use for all other URLs.
Below urls will be matched by default route.
http://example.com/customer/showorder/4567
http://example.com/order/showorder/4567
http://example.com/order/showorders
http://example.com/home/index
http://example.com/home
http://example.com
You can also mix path segments with route parameters however you cannot have two consecutive route parameters.
Below routes are valid.
{language}-{country}/{controller}/{action}
{controller}-{action}-{id}
{controller}.{action}.{id}
However below route is invalid as there is no way for the route to know when the controller part of the incoming request URL ends and when the action part should begin.
{controller}{action}/{id}
Custom Routing ASP.NET MVC
For most of the request your applications default route will work fine, however you might see different needs to which are not satisfied by default routing.
Below are some examples where you need custom routing
URL has date and date should be in specific format e.g. 12-10-2014
URL has id which should be integer.
Request should be HTTP Post method.
Request should be coming from local
Request has {Area} segment.
You can also create Custom routing modules when you need to treat requests to PDF / txt / html files differently. You can override GetRouteData and GetVirtualPath of Route class.
Attribute Routing
Attribute Routing is new type of routing feature of ASP.NET MVC 5. Attribute routing uses attributes to create Routes. Attribute routing gives you more control to handle URI by adding routes directly on controller and actions.
Attribute Routing should be registered in RegisterRoutes method of Global.asax or in RouteConfig file. It should be configured before convention based routing.
Below code shows how to register Attribute Routing
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//Add the following line of code
routes.MapMvcAttributeRoutes();
//convention based routes
}
}
In case if you are using both Attribute routing and convention based routing, the actions which are configured for Attribute routing will work as per Attribute Routes and the actions which are not configured will work as convention based routes.
Below is an example of AttributeRouting specified for Controller Action methods
public class HomeController : Controller
{
[Route("Users/about")]
public ActionResult About()
{
ViewBag.Message = "You successfully reached USERS/About route";
return View();
}
}
URL http://example.com/users/about will be handled by above action method.
You can also use routing with Controller. Below code shows how you can use AttributeRouting with Controller.
[RoutePrefix("AppHome")]
[Route("{action=index}")]
//default action used when URL action parameter is not exist in controller.
//e.g. http://example.com/apphome or http://example.com/apphome/details
public class HomeController : Controller
{
//new route: /AppHome/Index
public ActionResult Index()
{
return View();
}
//new route: /AppHome/About
public ActionResult About()
{
ViewBag.Message = "Application About us page.";
return View();
}
//new route: /AppHome/Contact
public ActionResult Contact()
{
ViewBag.Message = "Application contact us page.";
return View();
}
}
Routing Constraints
Routing constraints allows you to use validation on defined routes. It enables you to prevent getting route map with browser request unless specific validation matched. For example browser request should be matched with specific route only if id parameter is type of int.
Below route definition creates Route with constraint which allows only integer value for id parameter.
routes.MapRoute("Default", // Route name
"{controller}/{action}/{id}", // Route Pattern
new { controller = "Orders", action = "GetOrder",
id = UrlParameter.Optional }, // Default values for parameters
new { id = @"\d+" } //Restriction for id
);
If you need more complex validation, you can implement IRouteConstraint interface and use Match method to implement logic.
Below code creates custom route constraints by implementing IRouteConstraint. Which checks whether provided parameter is valid date or not.
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);
}
}
Add route with Constraint
routes.MapRoute("sample", "{controller}/{action}/{reportdate}", null,
new { reportdate = new DateConstraint() });
Catch-all Route
A catch-all parameter useful for a route to match part of a URL with an, unpredictable number of segments. If any query string used, it excludes from URL. A catch-all parameter is allowed only for the last segment of the route template.
For example, the following traditional route created with catch-all parameter with * symbol.
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute("catchallroute", "blog/{blog-name}/{*extrastuff}",
new { controller = "blog", action = "showblog"));
}
It handles below url
http://example.com/blog/how-to/2015/12/01
http://example.com/blog/abc/2015/12/
http://example.com/blog/abc/2015/
http://example.com/blog/xyz/
http://example.com/blog/xyz
Area Registration
Area is feature of MVC2. It allows you to organize applications part in better way. For example you have billing application you may have different parts like Billing, Admin, , Order and so on. You will create different Area for each part. Each area will contain Views, Controllers and Models specific to Area.
You can register specific area by inherting AreaRegistration class
Below code shows how to register Admin Area.
public class HelpDeskAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Admin";
}
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"admin_default",
"admin/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}