views:

60

answers:

3

I have a controller called MetricsController with a single action method:

public class MetricsController
{
  public ActionResult GetMetrics(int id, string period)
  {
    return View("Metrics");
  }
}

I want to route calls to this controller like this:

http://mysite/metrics/getmetrics/123/24h

I've mapped an additional route in my Global.asax.cs like this:

routes.MapRoute(
  "Metrics",
  "{controller}/{action}/{id}/{period}",
  new { controller = "Metrics", action = "GetMetrics", id = 0, period = "" }
);

routes.MapRoute(
  "Default", // Route name
  "{controller}/{action}/{id}", // URL with parameters
  new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

I just added this to the default template project that Visual Studio 2010 creates.

When I run the application, instead of defaulting to the HomeController, it starts in the MetricsController instead.

Why is this happening? There's nothing in the url when I start the application that matches the url pattern specified in the Metrics route.

This is all being tried in Visual Studio 2010 using the built-in web server.

+1  A: 

Because it matches first root, of course.

Thing is - when You provide default values - they become optional. If every one of routedata values are optional and route is first - it's guaranteed that it will hit first.

Something like this should work:

routes.MapRoute(
  "Metrics",
  "Metrics/GetMetrics/{id}/{period}",
  //assuming id, period aren't supposed to be optional
  new { controller = "Metrics", action = "GetMetrics" }      
);

routes.MapRoute(
  "Default", // Route name
  "{controller}/{action}/{id}", // URL with parameters
  new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Arnis L.
Thanks! the penny has just dropped :)
Kev
+1  A: 

Remove the defaults from your Metrics route:


routes.MapRoute(
  "Metrics",
  "{controller}/{action}/{id}/{period}",
  new { controller = @"Metrics", action = "GetMetrics"}
);

With the default values MVC is able to map to the GetMetrics action in the Metric controller pretty much any URL that you pass to it.

Hector
+1  A: 

In short: it's using the Matrics route because it matches the Matrics route.

In long: The default route defines defaults for all the route components and all of the route components are optional. All that your Metrics route is doing is adding another optional route parameter with a default... it's basically no different from the default route because the whole route contains optional parameters.

If you want it to work, you need to differentiate your Metrics route from the default route.

E.g.

routes.MapRoute(
  "Metrics",
  "metrics/{action}/{id}/{period}",
  new { controller = @"Metrics", action = "GetMetrics", id = 0, period = "" }
);

HTHs,
Charles

Side note:

There's nothing in the url when I start the application that matches the url pattern specified in the Metrics route.

Let's look at this from a different angle - what in the url matches the url pattern specified in the default route?

Charlino