Overview Of Filters In MVC

In ASP.NET MVC, a user request is routed to the appropriate Controller and action method. We need situations where you want to execute some logic before or after an action method executes. ASP.NET MVC provides filters for this. 

ASP.NET MVC filter is a custom class where you can write logic that needs to be executed before or after an action is called. There are mainly 4 kinds of filters in MVC.

  1. Authorization Filters
  2. Action Filters
  3. Result Filters 
  4. Exception Filters

To implement custom filters on the above filters, we can implement the required filter interface. Let us discuss one by one and implementation of custom filters in each type. 

Authorization Filters

This filter handles authorization and authentication logic. This logic gets executed before the action gets executed. We implement the authorization of an action just by decorating the authorize attribute to an action as shown below. 

  1. [Authorize]    
  2. public ActionResult Index()    
  3. {    
  4.     return View();    
  5. }   

Now, let us learn how to customize the authorization for our application. To implement custom authorization, we extend the authorizeAttribute class to our custom class as shown below. Now, we override the authorizeCore and then implement the custom logic that determines the user is authorized or not.

In the below sample code, we have extended our custom Authorization class with the Authorize attribute and implemented the authentication as well. If the user is not authenticated, it returns false as in line 15. And it will not execute the action. In line 22, we are determining whether the logged in user is authorized for the action called. If it returns false, it prevents the action execution.

  1. namespace Application.Filters    
  2. {    
  3.     public class CustomAuthorize:AuthorizeAttribute    
  4.     {    
  5.         ISecurityRepos securityRepos;    
  6.         public CustomAuthorize()    
  7.         {    
  8.             securityRepos = new ISecurityRepos();    
  9.         }    
  10.         protected override bool AuthorizeCore(HttpContextBase httpContext)    
  11.         {    
  12.             IPrincipal user = httpContext.User;    
  13.             if (!user.Identity.IsAuthenticated)    
  14.             {    
  15.                 return false;    
  16.             }    
  17.             string action, controller;    
  18.             MvcHandler mvc = httpContext.CurrentHandler as MvcHandler;    
  19.             action = mvc.RequestContext.RouteData.Values["action"].ToString();    
  20.             controller = mvc.RequestContext.RouteData.Values["controller"].ToString();    
  21.             string path = string.Format("{0}/{1}", controller, action);    
  22.             bool isAuthorized = securityRepos.IsAuthorized(path,user.Identity.Name);    
  23.             return isAuthorized ;    
  24.         }    
  25.     }    
  26. }  

Since we have defined the logic for our custom authorization,  we just decorate the action with CustomAuthorize attribute to implement this authorization.

  1. [CustomAuthorize]      
  2. public ActionResult Index()      
  3. {      
  4.     return View();      
  5. }   

Now, that we have learned how to implement AuthorizeCore, let us learn how we can implement HandleUnauthorized requests. 

Whenever the authorizeCore method returns false, the HandleUnauthorizedRequest method is called, where we can implement the logic to handle unauthorized requests, as shown below.

  1. protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)    
  2. {    
  3.            filterContext.Controller.ViewData["AuthorizationError"] = "You are not authorized for this action";    
  4. }   

Action Filters

These implement the IActionFilter interface that have onActionExecuting and OnActionExecuted methods. OnActionExecuting runs before the Action. We can use the action filters for logging the action calls. We can also check for any exception occured during action execution and log the exception details into your database. 

  1. public class LoggingFilterAttribute : ActionFilterAttribute    
  2. {    
  3.     public override void OnActionExecuting(ActionExecutingContext filterContext)    
  4.     {    
  5.         filterContext.HttpContext.Trace.Write("(Logging Filter)Action Executing: " +    
  6.             filterContext.ActionDescriptor.ActionName);    
  7.     
  8.         base.OnActionExecuting(filterContext);    
  9.     }    
  10.     
  11.     public override void OnActionExecuted(ActionExecutedContext filterContext)    
  12.     {    
  13.         if (filterContext.Exception != null)    
  14.             filterContext.HttpContext.Trace.Write("(Logging Filter)Exception thrown");    
  15.     
  16.         base.OnActionExecuted(filterContext);    
  17.     }    
  18. }   

We shall learn the implementation of logging the exception into database using ActionFilters in my next article.

Result Filters

These implement the IResultFilter. IResultFilter mainly has two methods - OnResultExecuting and OnResultExecuted. OnResultExecuting gets executed before the ActionResult is executed. OnResultExecuted runs after the result.

  1. public override void OnResultExecuted(ResultExecutedContext filterContext)    
  2.   {    
  3.       Log("OnResultExecuted", filterContext.RouteData);          
  4.   }    
  5.     
  6.   public override void OnResultExecuting(ResultExecutingContext filterContext)    
  7.   {    
  8.       Log("OnResultExecuting ", filterContext.RouteData);          
  9.   }   

Same as Action Filters, we can use Result Filters for logging the steps. In real time usage, we can use ResultFilters to log exceptions when an exception is raised when a View is executed. 

Exception Filters

These implement IExceptionFilter and it gets executed if there is an unhandled exception thrown during the execution of code. Exception filters can be used for tasks, such as logging or displaying an error page. 

We can implement the IExceptionFilter by implementing the OnException method and implementing our custom logic within the OnException method, as shown below.

  1. namespace Application.Filters    
  2. {    
  3.     public class CustomException:FilterAttribute,IExceptionFilter    
  4.     {    
  5.         public void OnException(ExceptionContext filterContext)    
  6.         {    
  7.             if (!filterContext.ExceptionHandled && filterContext.Exception is NullReferenceException)    
  8.             {    
  9.                 filterContext.Result = new RedirectResult("ErrorPage.html");    
  10.                 filterContext.ExceptionHandled = true;    
  11.             }    
  12.         }    
  13.     
  14.             
  15.     }    
  16. }   

 As shown in the above code, we can redirect to a custom Error page whenever we get an unhandled exception.

In the next part of Filters in MVC, we shall learn order of execution of filters, different levels where we can apply these filters, and also, we will learn Action filters and Exception filters with more details.