Logging Errors with ELMAH in ASP.NET MVC 3 – Part 4 - (HandleErrorAttribute)

Tags: ASP.NET, MVC, Logging, Error Handler, Elmah

Creating a custom HandleErrorAttribute for ELMAH (Optional)

Remember when we commented out that line from our Global.asax.cs in Part 1? Well, building our own HandleErrorAttribute will allow us to put it back or more importantly prevent the HandleErrorAttribute from overriding our ELMAH behavior. Currently the HandleError attribute will prevent any errors from bubbling up to ELMAH and we can't guarantee down the line, someone won't use a HandleError attribute like this...

[HandleError]
public class MyClass
{
    // This error won't be handled by ELMAH
    public MyMethod() {
        throw new Exception("oops");
    }
}

The solution to this problem is to implement our own custom HandleErrorAttribute. Add the following class to your project...

using System;
using System.Web;
using System.Web.Mvc;
using Elmah;

namespace ElmahAndMvc3
{
    public class ElmahHandleErrorAttribute : System.Web.Mvc.HandleErrorAttribute
    {
        public override void OnException(ExceptionContext context)
        {
            base.OnException(context);

            var e = context.Exception;
            if (!context.ExceptionHandled   // if unhandled, will be logged anyhow
                || RaiseErrorSignal(e)      // prefer signaling, if possible
                || IsFiltered(context))     // filtered?
                return;

            LogException(e);
        }

        private static bool RaiseErrorSignal(Exception e)
        {
            var context = HttpContext.Current;
            if (context == null)
                return false;
            var signal = ErrorSignal.FromContext(context);
            if (signal == null)
                return false;
            signal.Raise(e, context);
            return true;
        }

        private static bool IsFiltered(ExceptionContext context)
        {
            var config = context.HttpContext.GetSection("elmah/errorFilter")
                         as ErrorFilterConfiguration;

            if (config == null)
                return false;

            var testContext = new ErrorFilterModule.AssertionHelperContext(
                                      context.Exception, HttpContext.Current);

            return config.Assertion.Test(testContext);
        }

        private static void LogException(Exception e)
        {
            var context = HttpContext.Current;
            ErrorLog.GetDefault(context).Log(new Error(e, context));
        }
    }
}

And modify the RegisterGlobalFilters in your Global.asax.cs...

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

Now you have no worries about [HandleError] intercepting errors on your site.

Next Step: Logging Errors with ELMAH in ASP.NET MVC 3 – Part 5 – (JavaScript) »

This Post is Part of a Multi-Part Series

Add a Comment