2

There are many articles on SO and the web in attempts to handle 404's and exceptions gracefully.

From what I have read the best advice seems to be have a route for 404's like so:

routes.MapRoute(
    "404-PageNotFound",
    "{*url}",
    new { controller = "ErrorController", action = "PageNotFound" }
    );

Then for other errors have the HandleError atribute on the Controller and have CustomErrors turned on in web.config so it goes to the error.cshtml page.

However I have read that if you get a exception that does not set the HTTP code to 500 the HandleError will not work.

Can we finally produce an answer/best practice that handles 404's/Exceptions/ASP.Net errors where we can apply to this to all our projects?

Thanks

Jon
  • 38,814
  • 81
  • 233
  • 382
  • possible duplicate of [How to have a custom 404 and 500 error pages with a stock standard ASP.NET MVC3 website?](http://stackoverflow.com/questions/6173168/how-to-have-a-custom-404-and-500-error-pages-with-a-stock-standard-asp-net-mvc3-w) – Pure.Krome Jun 05 '11 at 23:32

2 Answers2

1

I use a simple error handling setup. Nice and simple. More info can be found at http://erictopia.com/2010/04/building-a-mvc2-template-part-7-custom-web-errors-and-adding-support-for-elmah/

Install ELMAH and have it handle all the errors.

Next create an Error controller. Add a catch all route like this:

routes.MapRoute(
    "ErrorHandler", // Route name
    "{*path}",      // URL
    new { controller = "Error", action = "Index" }
);

Then in web.config add this section:

<customErrors mode="RemoteOnly" defaultRedirect="/Error/Index">
        <error statusCode="403" redirect="/Error/NoAccess" />
        <error statusCode="404" redirect="/Error/NotFound" />
</customErrors>
37Stars
  • 2,489
  • 20
  • 23
  • does this append some crap to the querystring? something like errorurl=/blah/foo or whatever? – Pure.Krome Jun 06 '11 at 13:20
  • The problem with this is that you will catch by default all 404 including static resources (images, css, ...). – Softlion Jun 06 '11 at 14:19
  • @Softion - and what's wrong with that? if a browser asks for an image that isn't there, they should get a 404, right? how would this compare to your solution? U still need to handle 404's for static resources. – Pure.Krome Jun 07 '11 at 01:32
  • No, nothing is appended to the querystring – 37Stars Jun 09 '11 at 05:07
  • @Softion - that is exactly what I want. This will enable your application to catch those nasty Russian bots that are trolling for holes in Joomla and Word Press, then automatically black list their IP address. – 37Stars Jun 09 '11 at 05:09
0

No need to set up a 404 route. In global asax application start, set up a global filter to catch 404 where the controller exists but not the action, or if an action returns a 404 result.

        filters.Add(new HttpNotFoundFilterAttribute { Order = 99 });

where the filter is an ActionFilterAttribute with this override:

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.Result !=null && 
            (filterContext.Result.GetType() == typeof(HttpNotFoundResult) )
        {
            //You can transfer to a known route for example
            filterContext.Result = new TransferResult(SomeAction, SomeController);
        }
    }

And also in Application_Error, in case no controller exists:

        Exception ex = Server.GetLastError();
        string uri = null;
        if (Context != null && Context.Request != null)
        {
            uri = Context.Request.Url.AbsoluteUri;
        }

        Exception baseEx = ex.GetBaseException();
         var httpEx = ex as HttpException;

         if ((httpEx != null && httpEx.GetHttpCode()==404) 
              || (uri != null && Context.Response.StatusCode == 404) )
             { /* do what you want. */ 
               //Example: show some known url
               Server.ClearError();
               Server.TransferRequest(transferUrl);
             }

To avoid handling 404 for static resources, you should install SP1 on Windows 7 or windows 2008 R2 to upgrade IIS7 and set in web.config:

...
<modules runAllManagedModulesForAllRequests="false">
...
Softlion
  • 12,281
  • 11
  • 58
  • 88
  • does this need to have (in the web.config file) customerrors=on ? – Pure.Krome Jun 05 '11 at 23:34
  • Well no. This filter is not an error handling filter, and will be called before any error filters - which won't be called as the code is mutating the 404 result into something else. – Softlion Jun 06 '11 at 14:17
  • what does runAllMan...ts=false do? as in .. which module (or modules) are really being turned off? Secondly, with `new TransferResult(SomeAction, SomeController);` is the Action and the Controller your error controller the action method on that? – Pure.Krome Jun 07 '11 at 01:33
  • 1) with =true every request event static ones (jpg js,...) goes through the routing pipeline. This is very cpu consuming and not a nice behavior. With false and SP1 only mapped extensions and extensionless urls goes through this pipeline. Without SP1 extensionless urls bypass the pipeline. As in MVC you have lots of extensionless urls you must make sure your configuration is correct. Http404 which don't go through the pipeline obey the customError rules (and only them) and the rules defined in IIS (see 404 module config in IIS). 2) yes in my own case. – Softlion Jun 08 '11 at 12:12