What are the definitive guidelines for custom Error Handling in ASP.NET MVC 3

asp.netasp.net-mvcasp.net-mvc-3error handling

The process of doing custom error handling in ASP.NET MVC (3 in this case) seems to be incredibly neglected. I've read through the various questions and answers here, on the web, help pages for various tools (like Elmah), but I feel like I've gone in a complete circle and still don't have the best solution. With your help, perhaps we can set a new standard approach for error handling. I'd like to keep things simple and not over-engineer this.

Here are my goals:

For Server errors/exceptions:

  1. Display debugging information in dev
  2. Display friendly error page in production
  3. Log errors and email them to administrator in production
  4. Return 500 HTTP Status Code

For 404 Not Found errors:

  1. Display friendly error page
  2. Log errors and email them to administrator in production
  3. Return 404 HTTP Status Code

Is there a way to meet these goals with ASP.NET MVC?

Best Answer

I'll share the way I ended up doing this, that was part of the original question.

First, the problems I encountered:

  1. With customErrors on (i.e. in production) the global HandleError attribute swallows exceptions and renders your error view, but then you can't log it with an addon tool like elmah, since elmah never sees it. You could log it in your view I suppose, but it's a view, that seems wrong. The global HandleError attribute appears new in the MVC 3 RTM Visual Studio project template.

  2. customErrors with urls for MVC endpoints returns 302 status codes. There is the redirectmode property, but you cannot match mvc urls in customErrors and use the ResponseRewrite mode. ( https://stackoverflow.com/questions/781861/customerrors-does-not-work-when-setting-redirectmode-responserewrite/3770265#3770265 )

  3. Avoiding customErrors completely and handling everything custom in your app leads to a lot of complexity, IMO. (Iloved this: https://stackoverflow.com/questions/619895/how-can-i-properly-handle-404s-in-asp-net-mvc/2577095#2577095 , but it wasn't right for our project)

My solution

I've taken MVC out of the equation completely. I've removed HandleErrorAttribute global filter in global.asax and focus entirely on the customErrors configuration, shifting it to use WebForm redirects and change to redirectmode to ResponseRewrite in order to avoid the 302 HTTP response codes.

<customErrors mode="On" defaultRedirect="/Error.aspx" redirectMode="ResponseRewrite">
  <error statusCode="404" redirect="/NotFound.aspx" />
</customErrors>

Then, in NotFound.aspx page_load event, set the Response.StatusCode to 404 and in Error.aspx set the code 500.

Results:

The goals for both have been achieved with the Elmah logs, the friendly error page, and the status code with one line of code on the code-behinds. We're not doing it the "MVC Way" as the earlier solution does, but I'm OK with that if it's two lines of code.