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!