Three common ASP.NET MVC URL routing issues

Following on from my post last week about consistent ASP.NET MVC URLs, here are a few tips that helped when I was first getting started with ASP.NET MVC and its URL routing system.

Have you got your routes registered in the correct order?

ASP.NET MVC checks incoming URL requests against routes in the order they were registered, so you need to add them in the order of most to least specific. Thus, even though you might have a very specific route defined later on that matches the incoming URL perfectly, ASP.NET MVC will choose whichever route matches first. You can’t just drop in extra rules at the bottom of the list and expect them to work.

For example, if you have ten routes, with an {*anything} pattern registered first, the other nine routes will always be ignored, because the anything route will always be matched first.

In a real scenario, one application I am working on uses the default ASP.NET MVC route for most pages, but uses some extra routing rules as well.

  • Ignore any request for the Charts directory, and let ASP.NET handle those URLs as normal.
  • Allow browsing one controller’s resources by name, instead of by numeric ID.
  • Anything else can go to the 404 handler.

Here’s the code I use to implement these rules, in the correct order:

public static void RegisterRoutes(RouteCollection routes)
{
	// Ignore dynamic image handlers e.g. Charts/Summary.ashx?year=2008&month=08
	routes.IgnoreRoute("Charts/{*path}");

	// Allow browsing categories by name, instead of by ID.
	routes.MapRoute("Categories", "Categories/{action}/{name}",
		new { controller = "Categories", action = "Index", name = "" }
	);

	// All other pages use the default route.
	routes.MapRoute("Default", "{controller}/{action}/{id}",
		new { controller = "Applications", action = "Index", id = "" }
	);

	// Show a 404 error page for anything else.
	routes.MapRoute("Error", "{*url}",
		new { controller = "Error", action = "404" }
	);
}

Have you set the default redirection in Default.aspx.cs?

So you’ve changed the default controller, but your application still directs to /Home. If you take a look in Default.aspx.cs, you’ll see the following:

public void Page_Load(object sender, System.EventArgs e)
{
    Response.Redirect("~/Home");
}

This code gets called when a user browses to the directory where your application is installed, but doesn’t specify any controller (i.e. an empty URL path). It redirects requests to a default controller, which, in the case for a new ASP.NET MVC Web Application project, is called Home.

If you want to use something other than HomeController, this path needs to be changed as well.

Do your parameter names match?

Here’s another one that might catch you off-guard. The ASP.NET MVC routing system uses Reflection to assign parameter values by argument name when a controller action is called — not by argument index as I originally thought. For example:

routes.MapRoute("Product", "Product/{action}/{id}",
    new { controller = "Product", action = "Detail" });
public class ProductController : Controller
{
    public ActionResult Detail(int? productID) { .. }
}

Here, the product ID can’t be passed through automatically because the Detail() method’s parameter is called productID, where in the route it is defined as simply id.

http://your.site/Product?productID=64

http://your.site/Product/64

When browsed to, the first URL will work, because you’ve explicitly specified a query string parameter with the right name. The second (desired) URL will not work, because the name of the parameter in the route doesn’t match that of the controller method.

If you want the parameter to be passed through automatically, the name in the controller action must match the name in the route.

Leave a Reply

Your email address will not be published. Required fields are marked *