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?
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
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.
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With