Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC [HandleError] HandleErrorAttribute called twice when using global logging

In an MVC3 web application I was using

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

to apply global error handling where the user was shown the 'Error' view if an unhandled exception occured.

For one particular View, I also wanted a different error view to be displayed if an unhandled exception occurred by decorating the method with [HandleError(View = "SpecialError")]. This worked fine.

I then wanted to add global logging of unhandled exceptions. I created a custom HandleError attribute with logging code:

public class MyHandleErrorAttribute : HandleErrorAttribute
    {
        public override void OnException(ExceptionContext context)
        {
            // Write to log code
            base.OnException(context);
        }
    }

And updated RegisterGlobalFilters and method decoration to use this attribute name instead. This works generally but when an exception occurs within the method that is decorated with MyHandleError(View = "SpecialError")] the OnException method is called twice. I originally presumed that decorating the method with this attribute superseded the global handler, but it seems that it is simply added to (which makes more sense, but it isn't what I want). By calling OnException twice, the same exception is logged twice which must not happen. I don't think OnException is being called twice because it is a custom attribute - I believe this happens with the standard HandleError attribute also, it is simply now visible as I am creating a record of it.

Ultimately, I want to log all unhandled exceptions (once), while retaining the features offered by [HandleError], particularly setting different views for particular method exceptions. Is there a clean way of doing this?

like image 991
Paul George Avatar asked Jul 12 '12 10:07

Paul George


2 Answers

I believe I found a clean solution to this myself. Extending HandleError seemed like a good idea but now I think it was a step in the wrong direction. I didn't want to handle any errors differently, just write exceptions to log once before HandleError picked them up. Because of this, the default HandleError can be left in place as-is. Although OnException can be called multiple times, it appears to be entirely benign in the standard implementation of HandleErrorAttribute.

Instead I created an exception logging filter:

public class LoggedExceptionFilter : IExceptionFilter
    {
        public void OnException(ExceptionContext filterContext)
        {
            // logging code
        }
    }

It doesn't need too inherit from FilterAttribute as it is just registered once within RegisterGlobalFilters alongside HandleErrorAttribute.

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

This allows exceptions to be logged neatly without changing the standard [HandleError] features

like image 186
Paul George Avatar answered Oct 09 '22 00:10

Paul George


Try this,

public class MyHandleErrorAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext context)
    {
         var exceptionHandled = context.ExceptionHandled;

         base.OnException(context);                          

         if(!exceptionHandled && context.ExceptionHandled)
           // log the error.
    }
}
like image 33
VJAI Avatar answered Oct 09 '22 02:10

VJAI