views:

1592

answers:

3

I can't seem to figure this out. I'm experimenting with MVC Beta and am trying to implement a catchall route such that if the user enters mysite.com/blah instead of mysite.com/home/index it will hit the "Error" route.

Unfortunately it seems that the "Default" route always catches "blah" first. In fact the only route I've been able to get to the "Error" route with is blah/blah/blah/blah.

Is this the way it's supposed to work, because I've seen other examples that have the "Default" and "Error" route set up just like this and it seems that if they were to type in a controller that doesn't exist it would hit the "Error" route.

Is there something I'm missing (very possible) or will I just have to create a specific route for each controller?

Code I'm using:

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

        routes.MapRoute(
            "Error",
            "{*catchall}",
            new { controller = "Base", action = "Error", id = "404" }
        );

Thank you, Jeff

+2  A: 

MVC routes are checked in the order that they are entered.

Mysite/blah will be found by the default route. The controller will be blah, and the action is index.

When you entered the mysite/blah/blah/blah/blah route you gave it a route it could not map the default route to and then your catchall route was called.

For those other examples, did you notice if they had some error filters setup? I'm pretty sure the default asp.net mvc site has some error handling attributes on the pages already.

Min
Thanks, that's the understanding I came to, but just didn't want to accept based on what I've seen, and what I expect. But I'll learn to deal with it.
Jeff Keslinke
+2  A: 

In order to handle errors I used the Application_Error event in one of my projects:

protected void Application_Error(object sender, EventArgs e)
{
    Exception exception = Server.GetLastError();
    HttpException httpException = exception as HttpException;
    if (httpException != null)
    {
        RouteData routeData = new RouteData();
        routeData.Values.Add("controller", "Error");
        routeData.Values.Add("action", "HttpError500");
        if (httpException != null)
        {
            if (httpException.GetHttpCode() == 404)
            {
                routeData.Values["action"] = "HttpError404";
            }
        }
        Server.ClearError();
        Response.Clear();
        IController errorController = new ErrorController();
        errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
    }
}
Darin Dimitrov
This is the wrong place to do exception handling, and you're also changing the meaning of an exception by blowing it off. This could potentially make debugging very, very difficult.
Jeff Putz
I don't see why using Application_Error handler would make debugging difficult. If you log the exception you will have the full stack trace. Another problem with the *catchall route is that it won't be called if an exception occurs in a controller action, so if you want to handle 500 errors you will need to do it somewhere else. I prefer having all exception handling code at one place.
Darin Dimitrov
The biggest problem is that you lose a lot of your context by the time the error makes its way to Application_Error, such as the session object, and if you do not account for those things being gone, debugging becomes a nightmare.
NickLarsen
+3  A: 

Your first route will catch the most urls since you have defaults for the elements, you can visualize this using the route debugger from Phil Haack, see the link:

Route Debugger

Scott
This looks useful too. Thanks!
Jeff Keslinke