Friday, June 13, 2014

Widgets

An Absolute Beginner's Tutorial for Understanding ASP.NET MVC Routes

Introduction

In this article we will try to understand about ASP.NET MVC Routes. We will get to know the details about routes and try to see how we can implement route constraints.

Background

Developer coming from the the background of ASP.NET Webforms find it rather difficult to understand(when starting work in MVC) how the request gets mapped to a controller's action and ultimately a view gets rendered on the screen. In Web forms the request is actually mapped to the page that is physically present in the application directory. But in ASP.NET MVC the every request needs to be mapped to a controller. There is no concept of physical ASPX file in ASP.NET MVC.
In ASP.NET MVC we have controllers. Each controller will have multiple action and every action is supposed to take care of a user request. How the user requested URL gets mapped to the controller's action methods? The answer to this question is the Routing mechanism in ASP.NET MVC. The routes are the bridges between the user requested URL and the controller's action method. Routes takes care of the mapping strategy for mapping request URLs to the controllers and action methods.
This does not mean that we have to manually map all the URLs to the controllers and actions. ASP.NET MVC provides the mechanism of automating the routing by specifying the routes which are sort of hints/patterns. These hints/patterns will let the routing module understand the request URL and corresponding controller and action to invoke.
To let the routing engine understand better, we can specify the following in a route:
  • Patterns: This helps the parser understand how to break down request URL and map them to specific controller and action.
  • Route parameters: This let the engine understand the parameters coming in routes and maps them to the arguments of action methods.
  • Route Constraints: This let the parser know the type of the paramters being passed (string/int).
  • Ignore Rules: This let the parser know what all routes or pattern of routes should be ignored.

Using the code

To understand the above concepts in a better way, let us create a simple empty MVC 4 web application. We will see how we can specify various routes for this application.
All the route information is stored in a collection called as RouteCollection. If we want to specify route patterns for our application we need to add these patterns to this collection whenever our applicaiton starts. MVC 4 Project templates provides a default route already added to the RouteCollection. This default route exists inRegisterRoutes method of RouteConfig.cs file. This method is called from Application_Start life cycle event in global.asax file. Let us look at this default route and try to understand the pattern.
routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

The first property is the name of the route. Every route we add to the route collection should have unique name so that it can be uniquely identified. The second property is the url, It specifies the pattern of of request URL to act{controller}/{action}/{id}. So if a user is requesting a URL like: www.example.com/Customer/Edit/1, this URL will invoke the Customer controller's Edit Action method with a parameter id a 1. The third property specifies the default value of controller, action and id parameter i.e. If the user requests for www.example.com then since the controller, action and id part are absent in the URL, the routing engine will take the default values and invoke Home controller,s Index action with no id parameter(since it is specified as optional).
Now the first question that comes in mind is - what if we have to supply 2 parameters to the action method. Well, that is fairly easy to do. All we need to do is to specify mulitple parameter values in the route:
routes.MapRoute(
    name: "multipleparams",
    url: "{controller}/{action}/{param1}/{param2}",
    defaults: new { controller = "Home", action = "Action2", param1 = UrlParameter.Optional, param2 = UrlParameter.Optional }
);

In the similar manner, we can specify any number of route parameters in the route pattern. Also, we can choose to make any of these parameters as optional.

Route Constraints

Route constraints are mainly used to restrict the request URL that match a particular route and this particular route. This can be used to restrict the routes that are invalid for our application. The route constraint i specified in form of a regular expression. Lets try to understand the problem by defining a simple action method to edit the an entity. Lets define the action method for it.
public class HomeController : Controller
{
    public ActionResult Edit(int id)
    {
        ViewBag.Message = "Home/Edit/" + id;
        return View();
    }
}

Now this action method is expecting an int value to be passed to it. There is a view for this action method which is simply displaying the route. So lets call this action method with the following URL: "Home/Edit/1". The result will be:


What happened was that our default route was sufficient for the routing engine to parse the requested URL and invoke the Edit action. Now Let us try to pass an invalid int value in the route i.e. "Home/Edit/test". The result now is:


The reason for this is that non integer values are not valid for this action method. So for our application this is an invalid path and to mark this path as invalid path we can define a custom route with route constraint. lets try to define this route with the route constraint.
routes.MapRoute(
    name: "home_Edit",
    url: "Home/Edit/{id}",
    defaults: new { controller = "Home", action = "Edit" },
    constraints: new { id = @"\d+" }
);

This route will now only accept valid number values for this route. Now if we try to hit the same URL again the browser will clearly say that this is an invalid URL.

Ignoring some routes

There are some scenarios where we would also like to completely ignore some of the routes. If we look at theRouteConfig class, we can see a code like:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

What this does is that it restricts the access to all the URLs ending with .axd extension because we dont want the end user to be able to access Trace.axd or other resource axd files.
Before wrapping up this small tip, one important thing to keep in mins. The order insert the routes into theRouteCollection is very important. The routing module i.e the route handler will start looking into this map from top to bottom. So if we need to put some specific routes along with generic ones, we should put the specific ones before the generic ones.
If you like this post, then Please Share this Post with others!
M.S. Saggoo is a Software Designer and Developer and founder of 
a popular  programming news and development blog since 2013.
I can be found on  and can be reached by email .

No comments:

Post a Comment