Exception Filters in MVC

Introduction

Exceptions are part and parcel of an application. They are a boon and a ban for an application too. Isn't it? This would be controversial, for developers it helps them track minor and major defects in an application and sometimes they are frustrating when it lets users land on the Yellow screen of death each time. This would make the users mundane to the application. Thus to avoid this, developers handle the exceptions. But still sometimes there are a few unhandled exceptions.

Now what is to be done for them? MVC provides us with built-in "Exception Filters" about which we will explain here.

exception
         cc: Google

Let's start!

A Yellow screen of Death can be said is as a wardrobe malfunction of our application.

Get Started

Exception filters run when some of the exceptions are unhandled and thrown from an invoked action. The reason for the exception can be anything and so is the source of the exception.

Creating an Exception Filter

Custom Exception Filters must implement the builtin IExceptionFilter interface. The interface looks as in the following:
  1. public interface IExceptionFilter
  2. {  
  3.    void OnException(ExceptionContext filterContext)  
  4. }  
Whenever an unhandled exception is encountered, the OnException method gets invoked. The parameter as we can see, ExceptionContext is derived from the ControllerContext and has a number of built-in properties that can be used to get the information about the request causing the exception. Their property's ExceptionContext passess are shown in the following table:

 

Name Type Detail
Result ActionResult The result returned by the action being invoked.
Exception Exception The unhandled exceptions caused from the actions in the applications.
ExceptionHandled BOOL This is a very handy property that returns a bool value (true/false) based on if the exception is handled by any of the filters in the applicaiton or not.

The exception being thrown from the action is detailed by the Exception property and once handled (if), then the property ExceptionHandled can be toggled, so that the other filters would know if the exception has been already handled and cancel the other filter requests to handle. The problem is that if the exceptions are not handled, then the default MVC behavior shows the dreaded yellow screen of death. To the users, that makes a very impression on the users and more importantly, it exposes the application's handy and secure information to the outside world that may have hackers and then the application gets into the road to hell. Thus, the exceptions need to be dealt with very carefully. Let's show one small custom exception filter. This filter can be stored inside the Filters folder in the web project of the solution. Let's add a file/class called CustomExceptionFilter.cs.

  1. public class CustomExceptionFilter: FilterAttribute,  
  2. IExceptionFilter   
  3. {  
  4.     public void OnException(ExceptionContext filterContext)   
  5.     {  
  6.         if (!filterContext.ExceptionHandled && filterContext.Exception is NullReferenceException)   
  7.         {  
  8.             filterContext.Result = new RedirectResult("customErrorPage.html");  
  9.             filterContext.ExceptionHandled = true;  
  10.         }  
  11.     }  
  12. }  
Now let us understand what this actually does. As we can see, this implements the interface as said earlier and thus implements the method, OnException. This method has the parameter ExceptionContext, the properties of which is specified in the table. In this custom filter we have handled the most common and neglected exception "Null Reference Exception" that arises when a value returning null is not handled/checked and used in further implementations. The custom filter derives the FilterAttribute so as to be used as an Attribute over the action or the controller directly like [CustomExceptionFilter]. In this implementation above, we have used nearly all the important properties of the ExceptionContext. First, the check is used for the ExceptionHandled that returns a Boolean value if the exception has been handled or not. If not then Check for the type of exception that has arisen.

Since here we have used the NullReferenceException, we check for that exception. Then if the conditions are satisfied/passed we manipulate the result and return the RedirectResult (ActionResult type) and let the users land on a custom error page created in the application, to avoid the yellow dreaded screen. The use of the filter is pretty simple since this custom filter extends from the FilterAttribute. So based on the usage, this can be used as [CustomExceptionFilter] on the Controller Level or the individual Action level, whichever is relevant.

 

  1. //Over controller  
  2. [CustomExceptionFilter]  
  3. public class HomeController:Controller 
  4. {  
  5.    //......  
  6. }  
  7.   
  8.   
  9. //Over the Action  
  10. [CustomExceptionFilter]  
  11. public ActionResult Index() 
  12. {  
  13.    //.......  
  14. }  
Now, let's explain the builtin HandleAttribute. This is a built-in class used in a similar way as a filter attribute in MVC applications. The most important thing is this attribute works only when the custom errors in the web.config is enabled or set to true.

The default mode for this element is RemoteOnly that will only work out when the application is deployed and the request is made from some other systems. Let's look at the properties of the HandleError Attribute.
  • ExceptionType: This property, as the name suggests, indictes the attribute of the type of exception it needs to handle.

  • View: This is the property that we need to specify to let the attribute land the end users after handling the exception.

  • Master: If we have a special layout for the error page then this master can be set to that layout path. If left empty, this will take the default layout of the application for the error pages.

Thus, the following code snippet shows how to use the HandleError attribute.

  1. [HandleError(ExceptionType = typeof(NullReferenceException), View = "CustomErrorPage")] 
  2. {  
  3.    public Action Result 
  4.    {  
  5.       //........  
  6.       var testVal = null;  
  7.       //Unhandled and used..  
  8.    } 
Caution

While reading through the Adam Freeman, a very interesting note of caution was said for when using the HandleError attribute. In the custom error page, we would be using the HandleError Info like the Stack Trace, the exception message and so on. Since we would not like to show this to the end user, we need to put the stack trace inside a hidden field or make the HTML tag invisible because The view is not displayed to the user unless the Exception.StackTrace is included in the View.

Conclusion

Thus, we learned the creation of custom exception filters as well as the built-in filters in MVC applications. There are various ways/tools now to handle exceptions, but still we can make use of these filters to avoid detrimental effects on our applications.
 
References: Adam Freeman-Professional ASP.Net MVC 4 and MSDN
 
I hope this would help developers and beginners. The concept is interesting when we use them. So start using and enjoy coding.