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.

August 9, 2008

15 Comments

Cory on August 25, 2008 at 3:09 pm.

Is it possible to eliminate the need for the Default.aspx page in an MVC application? It seems a little ridiculous that a redirect is necessary before the app is even launched. I thought I read somewhere that IIS7 handles MVC differently than Cassini and that the default page is only necessary for Cassini. Can anyone confirm?

Richard on August 25, 2008 at 9:51 pm.

I’m not sure, Cory – I’ve always left it there. It would be interesting to know what the exact requirements are for IIS6, IIS7 and Cassini, and whether you can safely delete it in some configurations.

Cory on August 26, 2008 at 3:08 am.

I installed IIS7 last night and the app ran fine without the Default.aspx file. This post pretty much sums it up I think (http://forums.asp.net/t/1273646.aspx).

Neftali on March 4, 2009 at 2:59 am.

THANK YOU!!!! I have been searching for the answer to why my URL IDs were not getting passed to the action properly and yours was the first sit to lead me in the right direction… a simple renaming of my parameter to ‘id’ fixed it.

Richard on March 4, 2009 at 11:14 am.

@Neftali: that’s a good one :) had me banging my head for a few hours as well…

Troy on October 17, 2011 at 6:02 am.

Great! It was what I was looking for with ‘default’ actions for a specific URL.

Bill on May 9, 2012 at 10:43 pm.

Hi. I’m absolutely baffled. As I understand the above, my code should be working. I have a mixed app. A calendar is served via MVC, but I have standard pages as well. If I go to directly to my pages URL (ie. domain/Default.aspx), the pages load and work correctly. If not, my MVC calendar is always loaded. That is, my Default.aspx page no longer loads by default. If I remove Global.asax and Global.asax.cs from my code, my Default.aspx page loads normally (but, of course, the MVC stops working).

I have the following in my Global.asax.cs page:

public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute(“{resource}.axd/{*pathInfo}”);
routes.IgnoreRoute(“{resource}.aspx/{*pathInfo}”);
routes.IgnoreRoute(“{resource}.aspx”);

routes.MapPageRoute(“”, “{*anything}”, “/pages/Main.aspx”);

routes.MapRoute(
“Calendar”, // Route name
“Calendar/{controller}/{action}/{id}”, // URL with parameters
new { controller = “Calendar”, action = “Index”, id = UrlParameter.Optional } // Parameter defaults
);

}

protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}

Any idea why “Default.aspx” won’t load by default when someone goes to my URL?

Thank you.

Richard on May 10, 2012 at 5:20 pm.

@Bill: not sure either. Have you tried the ASP.NET MVC Route Debugger?

fetr on August 2, 2012 at 7:52 am.

very nice

Arora on September 11, 2012 at 11:44 am.

Great! but i want to hide id from url like
from
http://your.site/Product?productID=64
to
http://your.site/Product/

Thanks

Diogo Martinho on April 29, 2013 at 5:43 pm.

Thanks for your post. I was able to fix a nasty bug in my code with your help.
:)

Leave a Reply