ASP.NET MVC – URL routing

This is the seventh part of Paul Cociuba’s series on ASP.net 4.5. In this we will look at a feature that is more commonly associated with ASP.net MVC – URL routing.


URL routing first became available in the .Net Framework 3.5, and was used heavily in the releases of the MVC out of band update. But routing can also be used in the other design paradigms from ASP.net, and in this video I show how it can be used with ASP.net WebForms.

For your convenience, here is an annotated timeline through the video:

  • 1:30 – Since the last video was completed, the application was also updated to include pages for displaying products (Products.aspx) and to view, edit or insert a product (ProductDetails.aspx). These work just like their equivalents for categories and use strongly typed data binding.
  • 2:00 – To show the usage of HTML 5 controls by ASP.net WebForms, we run the ProductDetails.aspx page in edit mode to edit an existing product. Since Opera is HTML 5 compatible, the textboxes for Units in Stock and Price show up as numerical fields, with up and down arrows permitting the selection of a value.
  • 3:02 – To achieve this on the input controls, it was sufficient to change the TextMode property of the textbox control for the units in stock and price from ‘SingleLine’ which is the default value, to ‘Number’ which is one of the new HTML 5 values possible for this control. HTML 5 browsers will interpret this and show the correct output on the screen.
  • 3:30 – The ProductDetails.aspx page also includes a drop down control to allow the selection of a category with which the product is associated. The DropDown control in the EditItemTemplate is data bound to objects of type ToyCategory, using the ItemType property of the control. It makes use of a method called GetCategories() in the code behind to retrieve the list of available categories. This method returns a list (IEnumerable<ToyCategory>) objects. Finally, the control is strongly typed data-bound to the CategoryID property of the Product object being displayed via the SelectedValue property of the drop down.
  • 4:33 – With these changes in mind, we can now look at the implementation of simple routes. Routes are defined in the Global.asax file, when the Application_Start event is fired off. To be able to use the routing objects, I bring in the System.Web.Routing namespace.
  • The RouteTable object exposes a Routes property which contains the collection of all routes. The Routes collection exposes a MapPageRoute method that has 5 overloads that can be used to map new routes in the application.
  • Using the first overload of the method, we create a new route that will map all requests coming in with a URL of /SiteAdministration/Categories to /SiteAdministration/Categories.aspx, giving the route a name which we will be able to use later on.
  • 6:03 – With the route in place, we proceed with testing the application. Entering a URL that ends with /SiteAdministration/Categories yields the same output as running the Categories.aspx page, while the URL is formatted in a much more SEO friendly fashion.
  • 6:40 – We now move on to more advanced route creation. The objective would be to replace the urls that create new products and categories (which are of type CategoryDetails.aspx?command=new) with something more SEO friendly, like /Categories/New.
  • To do this, another overload of MapPageRoute is used, and this overload allows for the developer to also pass in a RouteValuesDictionary. This is a collection of named parameters and their values. With this object we can pass in a parameter called ‘command’ with a value of ‘new’.
  • 8:20 – To get the sample to work, we also have to modify the Page_Load event that is present in both the ProductDetails.aspx and CategoryDetails.aspx pages. This event handler checked if there was a query string parameter called ‘command’ present and if its value was set to ‘new’. Instead of looking in the query string, the new method code looks into the RouteData object exposed by the HttpRequest, to see if the pair is present.
  • 9:35 – When trying to run the sample following the above modifications, we still see that the sample is broken. This is because the New Product and New Category hyperlinks still pass in query string values instead of the new routes. We replace these hyperlinks with two others that use the GetRouteUrl method exposed by the page, to get the URL for a specific route using the name it was created under. The second parameter to the method is null since there is no need to pass in a RouteValuesDictionary object – one is created when the route was mapped when the application started (in the Application_Start event).
  • 11:15 – Running the sample application again, we are now able to see that the ASP.net Runtime extracted the route URL, by running the GetRouteUrl method, and placed it inside the HREF attribute of the anchor tag <a>
  • Finally, we also want to implement some more dynamic routes, which can take in dynamic parameter values. These will replace the URL by which we navigate from the category and product listings pages to the details pages. The URL currently looks like /CategoryDetails.aspx?id=1 and should look like /Categories/1
  • To do this, we will make use of a third overload of the MapPageRoute method. The route to be matched looks like /SiteAdministration/Categories/{id} where {id} is a dynamically populated parameter value. The route will map to the CategoryDetails.aspx page.
  • 13:05 – To complete the sample, we also have to replace the hyperlinks on the product and category listings pages to no longer pass in query string values to the details pages, but to use the new route URL. This can be done by changing the controls to use the GetRouteUrl method, and by passing in a new RouteValuesDictionary to the method. The RouteValuesDictionary object will contain one parametric pair: a parameter called ‘id’ and its value that gets strongly data-bound from the CategoryID or ProductID properties of the model objects.
  • 15:19 – To get the sample to work, one more change is needed in the code behind of the CategoryDetails.aspx and ProductDetails.aspx pages. The methods used to select a product or a category take in a parameter that is loaded from the query string – by using the [QueryString] attribute. We replace this attribute with [RouteData] to indicate to the ASP.net runtime that it should look for the parameter in the route data collection and not the query string.
  • 15:42 – Running the completed sample shows that the hyperlink controls on the listings pages now show the correct URLs (of type /Categories/1 and /Products/1) and clicking on these links actually load the details listings page which is able to retrieve the object from the database.
  • 17:50 – Should we wish to change the name of the parameter in the routes we have defined (change the route from /Categories/{id} to /Categories/{CategoryID}) but not change the name of the parameter on the code-behind method (leaving it as int id), we can accomplish this by using the [RouteData(“CategoryID”)] – and this would tell the ASP.net runtime that it should look for a parameter called CategoryID (instead of just id) in the route data collection.

In the next video of the series, we will be looking at adding validation to the application to ensure that only expected input and input ranges are allowed. Read more about URL routing at the links given below:


Original content from Paul Cociuba; posted by MSPFE editor Arvind Shyamsundar