17 Jun 2011

How to get ELMAH and MVC3 Error Handling to play nicely

It takes a bit of effort to get ELMAH and MVC3 to play nicely. Hopefully this post will help someone struggling with the same issues.

I needed the following:

  1. All errors should show the friendly error page, even on Localhost (normally the error page only shows remotely, not on localhost).
  2. Errors should be logged to Elmah when showing the default error view (normally the error view shows, but no Elmah errors get logged, because they were already handled by MVC3's error handling).
  3. The Elmah error view should only be visible remotely, but only to one specific user (by default the Elmah.axd view is only visible on localhost).

To meet the requirements stated above, you need to do the following:

Ensure the friendly error page shows:

In web.config:

<customErrors mode="On" >
        </customErrors>

Note that the "DefaultRedirect" attribute is not required.

Ensure that errors are logged in Elmah when MVC error handling kicks in:

Create the following filter:

public class ElmahHandledErrorFilter : IExceptionFilter
        {
                public void OnException(ExceptionContext context)
                {
                        // Log only handled exceptions, because all other will be caught by ELMAH anyway.
                        if (context.ExceptionHandled)
                                ErrorSignal.FromCurrentContext().Raise(context.Exception);
                }
        }

And ensure the filter always gets used (in Global.asax):

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
                filters.Add(new ElmahHandledErrorFilter());
                filters.Add(new HandleErrorAttribute());
        }

Ensure that the Elmah error page is viewable remotely:

In web.config:

<elmah>
        <security allowRemoteAccess="1" />
  </elmah>

Ensure that the Elmah error page is only viewable by a specific user:

In web.config:

<location path="elmah.axd">
        <system.web>
          <authorization>
                <allow users="TheUserName" />
                <deny users="*" />
          </authorization>
        </system.web>
  </location>

These stackoverflow questions and answers helped me figure this out: