MVC-Routing,Why i can not ignore defaults,The matched route does not include a 'controller' route value, which is required

asp.net-mvc, asp.net-mvc-routing

Solution

The MVC pipeline needs the `controller` and `action` route values. If you define your route as:

routes.MapRoute(
    name: "TestRoute",
    url: "home/MyTestDrillDown/{productcat}"
);

when a url matches this route, a single route value will be extracted by the routing system, the `productcat` parameter. There will be no `controller` and `action` route values extracted. That's why you need to define such a route like this:

routes.MapRoute(
    name: "TestRoute",
    url: "home/MyTestDrillDown/{productcat}",
    defaults: new { controller = "Home", action = "MyTestDrillDown" }
);

This way, when a url matches this route, there will be `controller` and `action` route values extracted (even though they are defined as default values and not extracted from the actual url)

You need to bear in mind that the routing system is independent from MVC, and happens earlier in the ASP.Net pipeline, before the MVC specific code is run.

When you call `routes.MapRoute()` you are just calling an extension method that will add a `Route` instance to the route table. Every route you add in ASP.Net needs an `IRouteHandler` which in turn returns an `IHttpHandler`. All the routing system does to find the first route that matches the current url and extract the route data values. It is then the route handler the component that will start the specific code handling the request matched by that route. (See routing on the msdn).

In the case of MVC, using the `MapRoute` extension adds an `MvcRouteHandler`, which in turn returns an `MvcHandler`. The `MvcHandler` is the one that starts the MVC specific pipeline. For example, take a look at the `ProcessRequestInit` in the source code, and you will see how it requires a route value named `controller`, which is used to create the controller instance:

string controllerName = RequestContext.RouteData.GetRequiredString("controller");

where `RouteData.GetRequiredString` throws an exception if there is not a route value with such a name in the parameters extracted by the route. (This is the exception you noticed in your question)

Problem

I have this configuration ``` public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "TestRoute", url: "home/MyTestDrillDown/{productcat}", defaults: new { controller = "Home", action = "MyTestDrillDown" } ); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } ``` I want to configure TestRoute as ``` routes.MapRoute( name: "TestRoute", url: "home/MyTestDrillDown/{productcat}" ); ``` but i see following error. The matched route does not include a 'controller' route value, which is required. My understanding is that if i have a hard coded a url then it directly matches to a controller and an action, in my case `"home/MyTestDrillDown/{productcat}"` matching to HomeController and MyTestDrillDown action. I am sure i am missing something very basic and important here as there exists an overload of `MapRoute` method which takes only Name and Url as parameter. Thanks

Original source