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!