URL Routing in ASP.NET MVC – Part 1

Prior to ASP.NET MVC Framework, there was a direct relationship between requested URLs and the files on the server hard disk. For example in the Web Forms, a request such as

http://www.site.com/Default.aspx

was matched to a “Default.aspx” file on the server hard disk. On the other hand, in a MVC application, requests are processed by actions in controller classes and apparently, there isn’t a one-to-one correlation to the files on disk. The MVC Framework make use of the “Routing system” to handle URLs requests. This post will give you several examples to teach you how to define your own routes and reach with specific URLs the action methods in your controller classes. Let’s start.

Open Visual Studio 2012 and create a new ASP.NET 4 MVC Web Application named “UrlRouting”, selecting the “Basic” option as template and “Razor” as the view engine. At this point our solution contains a basic structure to start with plus some javascript and jquery support. If you try to run the application you will get an error since there aren’t any controllers and actions yet. So let’s create a few. Right click the “Controllers” folder and select

Add.. -> Controller

Choose the “Empty MVC Controller” option as the template and name the controller “SimpleController”. Change the default Index action contents as follow:

The actions we defined in our controllers are simple actions that pass the specific controller’s and action’s name in a View called “DisplayActionController”, using the ViewBag object. If you aren’t familiar with the ViewBag object you can check this post. Next we will create the above View in order to display details for the action and the controller that processed the requested URL and caused the page to load. Right click the Views/Shared folder and select

Add.. -> View

Name the new View “DisplayActionController”, choose “Razor” as the view engine and leave all other checkboxes unchecked. Change the default contents of the View to the following code.

Build and run your solution. You should get a “The resource cannot found be found” message again. Add to the default URL the “/Simple/Index” and view the result.

You may wonder what was the change that caused the Index action of the Simple controller to be invoked and where is this actually configured. You define the Routing behavior in your MVC application in a RouteConfig.cs file which relies under the App_Start folder. Go ahead and open this file. Take a look at the “RegisterRoutes” function of that class and it’s contents. Ignore the first line and pay attention at the highlighted code.

You define a route for your application using the “MapRoute” method of the “RouteCollection” class. The above code which is what MVC Framework adds by default when you create an application, defines a route named “Default”, with a url pattern:

{controller}/{action}/{id}

This means that the first word after the Root url, will match the “controller” segment, the second will match the “action” segment and the third the “id”. In other words, the respective controller’s action method will be invoked with a parameter id. The last line of the default code

defines the default values for the url segments. The default controller is the “HomeController” (which doesn’t exist in our application) and the default action is an “Index” action. The id parameter is defined as optional. But what does “ByDefault” values mean? When you started the application without adding the “Simple/Index” content in the URL, what actually happened is that MVC tried to call the default values for the route properties. So, it tried to call the Index action of a Home controller. That’s why you received that error. Let’s try something else before starting creating our own routes. Request the following URL in your browser (make sure you always change the port number to yours).

http://localhost:49529/Product

Notice that you didn’t specified a value for the “action” segment but only for the controller’s. But as we previously mentioned, by default an “Index” action will be invoked, if nothing is declared for that segment. If you put an action value for that segment such as

http://localhost:49529/Product/Junk

you will get an error since the “Junk” value will match the action segment, resulting the MVC Framework will try to call that action in the ProductController. But since it doesn’t exist an error will occur.

Build and run your application. At the default Root URL you should get an error since we haven’t defined default values either for the controller or the action segment. At this point, you must define values for both the controller and the action you wish to invoke. Let’s create default values now. You supply default values as properties in an anonymous type. Change the “MyRoute” route we create above, to the following.

Build and run the application. You will still get an error at the default root URL, but adding a value /Product or /Simple you will get the DisplayActionController View, since the default value (“Index”) for the action segment was invoked. Add a default value for the controller segment as well.

If you run the application, this time the root URL will match the Index action of the Simple controller.
Notice that you should use the same names as the segments for the anonymous type properties, when defining default values.

Now let’s try something else. Suppose you want to prefix all your URLs with a static word, “Static” for example. You can do that by defining a new route right before the previous one.

We declared the new route before the old one, because it’s more specific. If you add it after the previous one, requesting a URL such as

http://localhost:49529/Static/

would result to an error, since the MVC Framework tries to match a URL searching from TOP to BOTTOM in the “RegisterRoutes” function. When it finds a valid route to match the requested URL it stops. In the previous example, it will match the “Static” word to the controller segment of the “MyRoute” route, so it will try to invoke an Index (default) action in a StaticController controller.

One common scenario is to change controllers in your application. Consider that you used to have an “ItemController”, hence your URLs to invoke actions of this controller would look like this:

http://site.com/Item/ControllersAction/

and now you replaced the Item controller with our existing ProductController. You should create a new route to match the old URLs to the new controller like this.

I hope you have already got an idea about how MVC handles URL requests. To keep the post readable we will stop here for now and we ‘ll continue the MVC URL Routing discussion in next posts, where we are going to see more interesting and advanced features of the MVC’s Routing System.

The purpose of this blog is to broaden my education, promote experimentation and enhance my professional development. Albert Einstein once said that “If you can’t explain it simply, you don’t understand it well enough” and I strongly believe him!