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:
- Display debugging information in dev
- Display friendly error page in production
- Log errors and email them to administrator in production
- Return 500 HTTP Status Code
For 404 Not Found errors:
- Display friendly error page
- Log errors and email them to administrator in production
- 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:
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.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 )
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 toResponseRewrite
in order to avoid the 302 HTTP response codes.Then, in
NotFound.aspx
page_load event, set theResponse.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.