Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Routing in MVC3

0.00/5 (No votes)
21 Jun 2012 1  
Brief introduction of routing in MVC.

Introduction

I got a lot of people questioning me about how routing works in MVC so here is the article where I will be giving you all a brief about it. 

The function of a routing system can be divided to two parts:

  1. RouteData: This mechanism is used to examine an incoming URL and then decide which controller and action the request is need to be send.
  2. VirtualPath: This mechanism is responsible for generating Outbound url. These are the URLs that appear in the HTML rendered from our views so that a specific action will be invoked when the user clicks the link. 

In the current Article we will be looking into RouteData only. In order to learn basic of MVC3 please read following article click here.

Let’s start by creating a Routing Project 

Create a new MVC application using Internet Template naming Routing. As we have selected this template we will get some pre written routing.

As Routing is defined in Global.asax, open the file, and you can see the following lines of code:

namespace Routing
{
    public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapRoute(
                "Default",
                "{controller}/{action}/{id}",
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
            );
        }
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
        }
    }
}

As we all can see that the Application_Start method is responsible for calling the RegisterRoutes method which has down the routing criteria. This Application_Start method is called by ASP.NET platform when the application is started. 

Note: Fortunately MVC provide us to define URL pattern which each route need to follow instead of manually typing out all of the individual URLs. If the pattern of the route matches the URL, then it is taken care by it.

Let’s examine a simple URL if you run your application without deleting the current routing  and open http://localhost:xxxx/Home/About, you can see the following screen

Lest have a quick discussion on this. URLs can be broken down into segments. These are the parts of the URL, excluding the hostname and query string, that are separated by the / character. In the example URL, there are two segments:

  1. Home – It’s the first segment of the URL which is referring to the Home Controller.
  2. About - It’s the second segment of the URL which is referring to the About Action. 

The URL pattern is {controller}/{action}

When processing an incoming URL, the job of the routing system is to match the URL to a pattern, and then find out the values from the URL for the segment variables. The segment variables are expressed using curly braces (the { and } characters). Our example has two segment variables having the names controller and action.

We say match to a pattern, because an MVC application. 

Now let’s have a quick look at what all cases this rote can handle. 

Request URL Segment Variables
http://testsite.com/Home/Indexcontroller = Home, action = Index 
http://testsite.com/Index/Homecontroller = Index, action = Home
http://testsite.com/HomeNo match  (too few segments)
http://testsite.com/Home/Index/SoccerNo match  (too many segments)

As we can see that in case first and second the URL pattern matches the correct no of segment and we can reach to respective controller and action while in case third and fourth the URL pattern doesn't matches. 

These are the default behaviors, and soon we will be learning how to change the default.

Creating and Registering a Simple Route

As we are going to start from basics for the time being lets delete the content of RegisterRoutes method as we are going to learn how to write routers Step by Step.

Once you have a URL pattern in mind, you can use it to define a route.

Now lest create a custom rote to handle the above example 

public static void RegisterRoutes(RouteCollection routes) {
      routes.MapRoute("CustomRoute", "{controller}/{action}");
}

Here we are creating a new route called CustomRoute which will process the URL segment to its specified controller and action respectively.

For example:

The URL http://testsite.com/Home/Index will route to controller = Home and action = Index

Defining Default Values 

The above defined route will work fine for case first and second but what if need to make sure that the cases third also works. In order to do that we need to define Default value for the View as follows:-

public static void RegisterRoutes(RouteCollection routes) {
      routes.MapRoute("CustomRoute ", "{controller}/{action}", new { action = "Index" });
}

This route tell us that if we don’t provide any value for Action please invoke the Index action by default which means The URL http://testsite.com/Home/ will route to controller = Home and action = Index as no other action is specified, mean while URL http://testsite.com/Home/Xyz will route to controller = Home and action = Xyz as it is explicitly mentioned.

Next thing which comes to mind is if we want even a default controller to be fired in case it is missing, yes we can handle that as follows:-

public static void RegisterRoutes(RouteCollection routes) {
     routes.MapRoute("CustomRoute ", "{controller}/{action}", new { controller = "Home", action ="Index" });
}

By providing default values for both the controller and action variables, we have created a route that will match URLs that have zero, one, or two segments, the below mentioned table gives an overview of the behavior 

Request URL  Segment Variables
http://testsite.com/ controller = Home, action = Demo
http://testsite.com/Homecontroller = Home, action = Demo
http://testsite.com/Demo/Testcontroller = Demo, action = Test
http://testsite.com/Test/Demo controller = Test, action = Demo
http://testsite.com/Test/Demo/ListNo match (too many segments) 

Static URL Segments 

One can also create patterns that have static segments. Suppose you have a requirement where you want to prefix URL with a word “Student”. 

http://testsite.com/Student/Home/Index  

public static void RegisterRoutes(RouteCollection routes) {
      routes.MapRoute("CustomRoute ", "{controller}/{action}", 
                       new { controller = "Home", action = "Index" });
      routes.MapRoute("StaticRoute", " Student /{controller}/{action}", 
                       new { controller = "Home", action = "Index" });
}

This URL pattern will match only URLs that contain three segments, the first of which must be Student. The other two segments can contain any value, and will be used for the controller and action variables.  

We can also create URL patterns that have segments containing both static and variable elements. 

public static void RegisterRoutes(RouteCollection routes) {
      routes.MapRoute("StaticRoute ", "XYZ{controller}/{action}"); 
      routes.MapRoute("CustomRoute ", "{controller}/{action}", 
                      new { controller = "Home", action = "Index" });
      routes.MapRoute("AnotherStaticRoute ", "Public/{controller}/{action}",
                      new { controller = "Home", action = "Index" });
}

The pattern in this route matches any two-segment URL where the first segment starts with the letter XYZ The value for controller is taken from the first segment, excluding the XYZ. The action value is taken from the second segment. 

As an example, the following URL would be matched by the route:

http://testsite.com/XYZ/Home/Index 

This URL would be directed to the Index action method on the Home controller. 

Custom Segment Variables 

MVC doesn’t restrict us to route to URL to just the controller and action variables. We are also free to define our own variables as 

public static void RegisterRoutes(RouteCollection routes) { 
      routes.MapRoute("CustomRoute ", "{controller}/{action}/{id}",
             new { controller = "Home", action = "Index", id = "DefaultId" }); 
} 

This route will match any zero-to-three-segment URL. The contents of the third segment will be assigned to the id variable, and if there is no third segment, the default value will be used.

Now the first thing which comes to our mind is how we can get this value and use it. 

So first let’s talk about fetching this id value, which can be done in following two ways:

  • We can access any of the segment variables in an action method by using the RouteData.Values property, hence id can be accessed as:
  • public ViewResult CustomVariable() {
          ViewBag.CustomVariable = RouteData.Values["id"];
          return View();
    }
  • We can define parameters to our action method with names that match the URL pattern variables, the MVC Framework will pass the values obtained from the URL as parameters to the action method.
  • public ViewResult CustomVariable(string id) {
          ViewBag.CustomVariable = index;
          return View();
    }

Now once we have fetch the id value we can display it in view as follows:-

@{
ViewBag.Title = "CustomVariable";
}
<h2>Variable: @ViewBag.CustomVariable</h2> 

Defining Optional URL Segments 

MVC also gives us leverage to have optional URL segment which means a URL segment that the user does not need to specify, but for which even no default value is also specified.

public static void RegisterRoutes(RouteCollection routes) {
      routes.MapRoute("CustomRoute", "{controller}/{action}/{id}",
                   new { controller = "Home", action = "Index", id = UrlParameter.Optional });
} 

This route will match URLs whether or not the id segment has been supplied. 

No of Segment  URL Mapping
http://testsite.com/ controller = Home, action = Demo
http://testsite.com/Testcontroller = Home, action = Demo
http://testsite.com/Test/Democontroller = Test, action = Demo
http://testsite.com/Test/Demo/List controller = Test, action = Demo, id = list
http://testsite.com/Test/Demo/List/NameIdNo Match (too  many segments) 

Defining Variable-Length Routes 

Till now we have seen that we manage routing for any specific no of segments but what if we want to handle cases for ‘n’ no segments.

MVC provide us to handle this case with ease too. One can define support for variable segments by designating one of the segment variables as a catchall, done by prefixing it with an asterisk (*).

public static void RegisterRoutes(RouteCollection routes) {
      routes.MapRoute("CustomRoute", "{controller}/{action}/{id}/{*catchall}",
                    new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}    

If you observe here we have extended the route from the previous example to add a catchall segment variable, which is we imaginatively called catchall. This route will now match any URL. The first three segments are used to set values for the controller, action, and id variables, respectively. If the URL contains additional segments, they are all assigned to the catchall variable 

No Of Segment URL Mapping
http://testsite.com/ controller = Home, action = Demo 
http://testsite.com/Test controller = Home, action = Demo
http://testsite.com/Test/Demo controller = Test, action = Demo 
http://testsite.com/Test/Demo/List controller = Test, action = Demo, id = list 
http://testsite.com/Test/Demo/List/NameId/ProfIdcontroller = Test, action = Demo, id = list, catch = NameId/ ProfId

There is no upper limit to the number of segments that the URL pattern in this route will match.   

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here