44

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?

5
  • 2
    I'd like this question to be migrated BACK to SO so it can get more answers. I'm seeking coded answers. May 13, 2011 at 17:21
  • @Shawn That's unlikely to happen. The question is more on topic here than it is on SO and it has an accepted answer. Questions also generally don't get re-migrated for technical reasons. If you need help with coding a specific error-handling approach, please open a new question on StackOverflow. Otherwise, "coded answers" may be too broad a criteria to be useful or answerable. Last but not least, the best way to attract moderator attention to a question is to flag it. Your comment here likely would've gone unnoticed if it didn't trip an auto-flag by pushing the comment count over 20.
    – Adam Lear
    May 13, 2011 at 17:40
  • There used to be about 10 comments here, where'd they all go?
    – RyanW
    Jun 17, 2011 at 15:43
  • I found a solution which meets your goals. I have it as another answer on SO: stackoverflow.com/questions/6508415/…
    – Jesse Webb
    Jul 29, 2011 at 15:14
  • 1
    @AnnaLear I concur with Shawn. I only found this page via Google. Note that nearly all of the answers below contain links BACK to Stack Overflow. To me that speaks volumes, in that it should have been left there in the first place.
    – Rebecca
    Feb 20, 2012 at 10:32

2 Answers 2

23

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.

5

I think that MVC, ASP and your favourite logging/exception handling framework can handle your goals quite nicely. ELMAH and Enterprise Library both provide easy to use exception handling and logging so pick your favourite .. I'm not going to go into the pros and cons of each here.

NOTE: you can't display a friendly error page AND return a HTTP 404 or 500 like your question suggests. When you return a friendly error page the HTTP code returned to your browser will be 302.This is a redirect to the friendly error page.

Friendly Error Pages

It sounds like you can achieve your goals by the good 'ol fashioned web.config settings that have been part of ASP.net for some time. You mention showing debug information when in dev and showing friendly pages in production. You can use the web.config's custom errors section for this (Set CustomErrors="Off" to show debug information). I'm going to assume that you are familiar with the CustomErrors attribute, if not read this:

http://msdn.microsoft.com/en-us/library/h0hfz6fc.aspx

If you need greater granularity of control over which error views you display, then use MVC's HandleError Attribute. This way you can choose different error views for each Action/Controller.

http://weblogs.asp.net/scottgu/archive/2008/07/14/asp-net-mvc-preview-4-release-part-1.aspx

Exception Logging

It sounds like you want to respond to all your exceptions in the same way ('Log errors and email them to administrator in production'). If this is the case your simplest option is to add code to

Application_Error(object sender, EventArgs e)

in your global.asax. This is where you can pass off to your chosen logging framework.

If you want more control over your exception logging / handling then you can subclass HandleErrorAttribute and override

OnException(System.Web.Mvc.ExceptionContext filterContext)

this is another place where you can pass off to your chosen logging framework.

https://stackoverflow.com/questions/183316/asp-net-mvc-handleerror

This gives you more control than the Application_Error technique mentioned above.

In general MVC gives you a great granularity of control over how to handle errors. If you don't need this control then you can fall back on the ASP.net ways of doing things such as defining error pages on your web.config.

3
  • Thanks so much for adding your thoughts. I think the 302 status code is poor design choice by the original ASP.NET team. I'll get into that in my answers too, there are some options for doing that. It seems some in the MVC world are abandoning customErrors completely and handling it all in the app for better reusability and more control as you point out. But, I had limited success in implementing those and was adding a lot of code that seemed like it was better baked on. More in my answers below.
    – RyanW
    Feb 7, 2011 at 20:50
  • I prefer to override the OnException method for logging, in this way i know i can log everything , even error occuring from an Ajax call which i find will not trigger your Application_Error.
    – Alicia
    Jul 11, 2013 at 14:23
  • @Alicia full sample code?
    – Kiquenet
    Dec 6, 2018 at 21:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.