Click here to Skip to main content
15,891,951 members
Articles / All Topics

Understanding Filters in MVC

Rate me:
Please Sign up or sign in to vote.
5.00/5 (3 votes)
8 Mar 2015CPOL8 min read 24.7K   9  
Understanding Filters in MVC

Introduction

There are scenarios when we have an implementation which will be reused at many places, which is not confined to a single place or method. This is fulfilled by the Filters in MVC. This is a very good concept introduced in MVC. The implementation which is mentioned above is called cross-cutting concerns. Thus, in simple terms, this add an extra logic to be implemented into the request being processed. Some of the examples of cross cutting concerns are Authorization & Output Caching. Let's discuss the different types of filters and how to create them and use them.

Getting Started

Let's see first a glimpse of how the filters are used:

C#
namespace WebSecurityDemoTest.Filters
{
    public class WebSecurityAuthorize:AuthorizeAttribute
    {
        protected bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (!httpContext.Request.IsAuthenticated)
            {
                return false;
            }
            if (HttpContext.Current.Session["SessionHelper"] == null)
            {
                return false;
            }

            return true;
        }

        protected void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            filterContext.Result = new RedirectResult("/");
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
}

The above snippet is an example of an CustomAuthorize attribute. This attribute is a kind of Filter only. As this is defined here once and is used as an MVC attribute at many places, this needs to be checked at every controller level in every application where authorization is a must. Now let's see if this would not have been the case, how explicitly we would have checked at every action level.

C#
namespace WebDemo.Controllers{
    public class DemoController : Controller {
        //..instances or constructor if any read only variables used
        public ActionResult Index() {
         if(!Request.IsAuthenticated) {
           FormsAuthenticationn.RedirectToLoginPage();//MVC WebSecurity
          }
         //else rest implementation..
         }
     }
}

In the above snippet, as you can see, the Request.IsAuthenticated is checked at each action level, as the authentication needs to be checked before letting the anonymous user access the action. Thus its redundancy can be normalized by the use of Filters.

By just using [Authorize] or [CustomAuthorize] at the controller/action level. Thus, we can say Filters are attributes that help in adding an extra check at the routing level as this needs to be checked during the request processing only. Attributes are special classes which get derived from the namespace System.Attribute.

Basically, there are four types of filters that the MVC framework support. They are:

Filter Type Inheritance What this does
Authorization IAuthorizationFilter Runs first during the request processing before any other filters or the action execution
Action IActionFilter Runs before the action execution (Action level)
Result IResultFilter Runs before after the action execution (Action level)
Exception IExceptionFilter Runs only when any action method or any other filter throws exception

Before the invocation of any action method, the framework first looks for any definition of any filter attributes, then moves into the action method execution, which in turn gives an extra level of security to the application without writing redundant codes.
Let's look into each briefly.

Authorization Filter

This as the name suggests is required to provide authorization level in the application. The default attribute is [Authorize]. Its constructor also can accept parameters like Roles [Authorize(Roles=”Admin”)] which is very handy as the roles based application are very common now a days.

Authorization filters as mentioned in the table above runs the first before any filter’s execution or even before the action method's execution.

The below snippet shows how the Interface from which it extends looks like:

C#
namespace System.Web.MVC {
    public interface IAuthorizationFilter {
        void OnAuthorization(AuthorizationContext filterCOntext);
    }
}

The best thing is we can customize the Authorize attribute by extending our custom authorize class from the Authorize attribute class and manipulate our logic there, which I have mentioned in the very first snippet. A nice tip here is to keep the Custom Authorize attribute very simple.

Built in Authorize attribute also accepts the Users parameter like [Authorize(Users=”Suraj”,”Simon”,”Mike”)], which filters the action based on the users access level.

The use is also very simple. Either we can use at the controller level or the action level. Just place [CustomAuthorize] before the controller class or the action methods.

Action Filter

The action filter can be used for any purpose, why any as the Interface it extends supports two methods to be invoked. As mentioned in the table, this filter may be executed before the Action execution but not the first. Let's look at the Interface:

C#
namespace System.Web.MVC {
    public interface IActionFilter {
       void OnActionExecuting(ActionExecutingContext filterContext);
       void OnActionExecuted(ActionExecutedContext filterContext);
    }
}

As you can see in the above snippet, the interface has two methods to be defined, as the method names suggest, the first one OnActionExecuting tells us that before the action method has been invoked, we can use this method, similarly the second one says that once the action method gets executed then this can be invoked. Now let's see each of them one by one .

actionFilter

OnActionExecuting Method

As we have already discussed, this method is invoked before the action starts getting executed. The filterContext of type ActionExecutingContext passed as the parameter contains the following properties:

Name Description
ActionDescriptor This provides the details of an action method.
Result This gives the result for the action method, the filter can be manipulated to cancel the request also.

Let's look into the implementation of this method, in a custom action filter attribute:

C#
namespace Filters.WebDemoInfra {
    public CustomActionFilter : FilterAttribute , IActionFilter {
       public void OnActionExecuting(ActionExecutingContext filterContext)
         if(filterContext.HttpContext.Request.IsLocal) {
              filterContext.Result = new HttpNotFoundResult();
          }
       }

Thus when we try and understand what we have written in the snippet above, we find that, when before the action gets executed, this method gets invoked, the method OnActionExecuting returns a not null result, i.e., HttpNotFoundResult, which will land the user on a 404 not found error page, even if the action has a view defined. This is the power of this filter.

Now let's look into its sister’s implementation.

OnActionExecuted

This method as defined ago, can be invoked to span the execution of the action method being processed based on the request. Let's check with the help of an example which will measure the time taken for the action to complete the full execution.

C#
namespace Filters.WebDemoInfra {
    public class CustomActionFilter : FilterAttribute , IActionFilter {
      private StopWatch watch; //System.Diagnostics
      
      public void OnActionExecuting(ActionExecutingContext filterContext) {
         timer = Stopwatch.StartNew();
       }

      public void OnAcionExecuted(ActionExecutedContext filterContext) {
       timer.Stop();
       if(filterContext.Exception == null) {
         filterContext.HttpContext.Response.Write(string.Format
		("Total Tme taken: {0}", timer.Elapsed.TotalSeconds));
       }
    }
  }
}

The above snippet is a very simple snippet to understand. The private variable is of type StopWatch which is an in-built class in the namespace System.Diagnostics. In the executing method, we are initializing the timer and after execution of the action method since the executed method gets invoked, so to the httpContext which contains both Request and response as well, we assign the time elapsed in seconds to the Response.

Let's look at the properties provided by the OnActionExecuted method.

Name Description
ActionDescriptor This provides the details of an action method
Canceled If in case the action has been canceled by any other filter, this property returns true
Exception If any filter or any action throws an exception, it is returned by this property
ExceptionHandled If any filter or any action throws an exception and it has been handled, this property returns true
Result This gives the result for the action method, the filter can be manipulated to cancel the request also

Thus, this was all about the Action filters.

Result Filter

These are quite similar to the Action Filters. These are the filters which are invoked or operate on the results being produced by the Action Result methods. This implements from the IResultFilter interface which also looks quite similar to the IActionFilter. Let's see how:

C#
namespace System.Web.MVC {
    public interface IResultFilter {
       void OnResultExecuting(ResultExecutingContext filterContext);
       void OnResultExecuted(ResultExecutedContext filterContext);
    }
}

OnResultExecuting

OnResultExecuting method gets invoked when the result has been returned by the Action method but before the action is executed fully. This also has the same properties as the OnActionExecuting method as described in the table.

OnResultExecuted

OnResultExecuted method gets invoked after the action result has been executed. Here also, the parameter filterContext contains the same properties as the OnActionExecuted method has described in the table above. The demonstration can be the same Timer as described in the Action filter section.
The below snippet will show you the built-in Action and Result Filter class.

C#
public Abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IResultFilter {
  public virtual void OnActionExecuting(ActionExecutingContext filterContext){
     }

public virtual void OnActionExecuted(ActionExecutedContext filterContext){
     }

public virtual void OnResultExecuting(ResultExecutingContext filterContext){
     }

public virtual void OnResultExecuted(ActionExecutedContext filterContext){
     }
   }
}

Using Global Filters

This is a very nice feature that can be implemented in the MVC application. Global.asax as we all know is the heart of the MVC web application. The Application_Start method is called from here whenever the application starts. We have a FilterConfig.cs file inside our App_start folder, where we can find a static method called RegisterGlobalFilters. In this method, we register our custom filter which needs to be invoked throughout the application which is applied to all controllers and actions in the application. Let's see how we register:

C#
namespace Filters { 
    public class FilterConfig {
        public static void RegisterGlobalFilters(GLobalFilterCollection filters) {
            filters.Add(new HandleErrorAttribute());
            filters.Add(new CustomAllAttribute());
        }
    }
}

Thus the second filter added/registered as the global filter is our custom attribute. This custom attribute implementation needs to be thought upon and then written as this would be used throughout the application, so this should also be very simple so that can be manipulated and maintained at any point of time.

Filter Ordering

In MVC framework, the order in which the filter get invoked (if there is more than one at the action), does not matter much. But even if you wish to add ordering based on the business logic we have, then we can use the Order keyword which accepts an int value to set the order of the Filter invocation/execution. Let's take an example and understand.

C#
[ProfileA(Message = "First")]
[ProfileB(Message = "Second")]
public ActionResult Index() {
   //Implementation
 }

In the above snippet, we have two custom filters ProfileA and ProfileB that take message as parameter and print that using the context response write method. Thus, this would write:

  • First” (For OnActionExecuting)
  • Second” (For OnActionExecuting)
  • Second” (For OnActionExecuted)
  • First” (For OnActionExecuted)

Thus, if we wish to modify the order like the “Second” would come first then the “First”, then we need the use of Order.

C#
[ProfileA(Message = "First"), Order=2]
[ProfileB(Message = "Second"), Order=1]
public ActionResult Index() {
   //Implementation
 }

Thus, here the output as previous will change based on the order specified in the above snippet. Thus based on the requirement, we can specify as many filters may it be built-in or custom and set the order of execution also. This is how flexible MVC framework is. :)

Conclusion

Thus here, I tried to explain the Filters that are being used in MVC framework. Here, I have discussed Authorize, Action & Result filters. I will try and explain the Exception filter in the next section.
Thanks for your patience. Corrections and suggestions are humbly accepted. :)

References

  • Adam Freeman- Pro ASP.NET MVC
This article was originally posted at http://surajpassion.in/understanding-filters-in-mvc

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --