Adding Custom Exception Handling Attributes to Your Asp.Net MVC Actions

Attributes are a simple way to run common handling across many actions without repeating yourself

I ran into a position where I was handling exceptions and pushing them to xml ContentResults the same way on multiple actions across many controller repeating a lot of code. I was working on a REST interface that always was to return xml. All Exception were to be returned in xml as well. I found myself writing a lot of actions like this:
public ContentResult Fidget()
{
    try
    {
        //do a bunch of stuff
        //throw exceptions if I need to
    }
    catch(Exception ex) //now catch them and display xml
    {
        // turn the exception into xml
        return this.Content(myXmlException, "text/xml");
    }
    
    // if it made it here, return success xml
    return this.Content(successXml, "text/xml");
}

This worked great, but after a bunch of actions, the code was very redundant. I want to handle exception the same on a lot of actions, but not all, so I decided to go to an Attribute, specifically ActionFilterAttribute and the IExceptionFilter. If I override the OnException, I can automatically handle the Exceptions in the painted actions, so this is what I came up with:
[HttpGet]
public class XmlExceptionAttribute : 
    ActionFilterAttribute, IExceptionFilter
{
    public void OnException(ExceptionContext 
        filterContext)
    {
        if (filterContext.Exception == null) return;
        filterContext.ExceptionHandled = true;
        var response = filterContext.Controller
            .ControllerContext.HttpContext.Response;
        response.ContentType = "text/xml";
        response.Write((new Status(
            filterContext.Exception)).ToXmlString());
    }
}

*Note that the Status object is a just an object I made to be serializeable and .ToXmlString() is an extension method I came up with a while back to convert objects into xml strings on the fly.

Now, if the attribute is applied, all I have to do for the above behavior in an action is simply this:
[HttpGet]
[XmlException]
public ContentResult Fidget()
{
    //do a bunch of stuff, throw exceptions if I need to
    
    // if it made it here, return success xml
    return this.Content(successXml, "text/xml");
}

The behavior is now the EXACT same!

Add comment

Loading