– How to properly handle 404 in ASP.NET MVC

I am using RC2

Using URL Routing:

     new { controller = "Errors", action = "NotFound" }  // 404s

The above seems to take care of requests like this (assuming default route tables setup by initial MVC project): "/blah/blah/blah/blah"

Overriding HandleUnknownAction() in the controller itself:

// 404s - handle here (bad action requested
protected override void HandleUnknownAction(string actionName) {
    ViewData["actionName"] = actionName;

However the previous strategies do not handle a request to a Bad/Unknown controller. For example, I do not have a "/IDoNotExist", if I request this I get the generic 404 page from the web server and not my 404 if I use routing + override.

So finally, my question is: Is there any way to catch this type of request using a route or something else in the MVC framework itself?

OR should I just default to using Web.Config customErrors as my 404 handler and forget all this? I assume if I go with customErrors I'll have to store the generic 404 page outside of /Views due to the Web.Config restrictions on direct access.

Best Solution

The code is taken from and works in MVC 1.0 as well

Here's how I handle http exceptions:

protected void Application_Error(object sender, EventArgs e)
   Exception exception = Server.GetLastError();
   // Log the exception.

   ILogger logger = Container.Resolve<ILogger>();


   HttpException httpException = exception as HttpException;

   RouteData routeData = new RouteData();
   routeData.Values.Add("controller", "Error");

   if (httpException == null)
       routeData.Values.Add("action", "Index");
   else //It's an Http Exception, Let's handle it.
       switch (httpException.GetHttpCode())
          case 404:
              // Page not found.
              routeData.Values.Add("action", "HttpError404");
          case 500:
              // Server error.
              routeData.Values.Add("action", "HttpError500");

           // Here you can handle Views to other error codes.
           // I choose a General error template  
              routeData.Values.Add("action", "General");

  // Pass exception details to the target error View.
  routeData.Values.Add("error", exception);

  // Clear the error on server.

  // Avoid IIS7 getting in the middle
  Response.TrySkipIisCustomErrors = true; 

  // Call target Controller and pass the routeData.
  IController errorController = new ErrorController();
  errorController.Execute(new RequestContext(    
       new HttpContextWrapper(Context), routeData));