Click here to Skip to main content
13,355,018 members (57,054 online)
Click here to Skip to main content
Add your own
alternative version


9 bookmarked
Posted 5 Nov 2010

Fluent Filters - Global Action Filters for ASP.NET MVC 2

, 8 Nov 2010
Rate this:
Please Sign up or sign in to vote.
This article describes a small library for ASP.NET MVC, that can be used as a facility for registering global filters. It is similar to Global Filter in ASP.NET MVC 3, but with different implementation and features.
Fluent Filters


Once in a project that was written in ASP.NET MVC 2, I needed to implement a means to register action filters for all controllers in the application, because it is not very convenient to specify the attributes for each class of controller if you want to perform the same operation globally, and as such, there is no flexibility. Later, I found mention of this only in ASP.NET MVC 3.

After that, I decided to write a similar functionality on my own, setting myself a series of requirements that had to be performed:

  1. Ease of registering a filter in the application
  2. Ability to add criteria to filter
  3. Ability to use dependency injection for filters

I have got an interesting approach and I decided to combine all this into a separate library to share it with others.

You can find the latest version of binary and source code on the project page on CodePlex. Working application examples are located in src\Samples folder of source code.

Using the Code

FluentFilters helps you to implement a global filters functionality in your ASP.NET MVC application. A global filter is a filter that is going to run for every single action on every single controller. Creating a custom filter for usage globally is very simple. All you need to do is to implement your custom filter class with one or more interfaces which are the four types of ASP.NET MVC filters:

  • IAuthorizationFilter
  • IActionFilter
  • IResultFilter
  • IExceptionFilter

For example, a filter can look like:

public class CustomFilter: IResultFilter, IAuthorizationFilter
    #region IResultFilter Members

    public void OnResultExecuted(ResultExecutedContext filterContext)
        // Some logic here ...

    public void OnResultExecuting(ResultExecutingContext filterContext) 
        // Or here ...


    #region IAuthorizationFilter Members

    public void OnAuthorization(AuthorizationContext filterContext)
        // May be here?


For working with filters, you should use class FluentFiltersBuilder. This is the recommended usage if you build MVC application without Inversion of Control(IoC) container. Using FluentFilters with IoC container is preferred rather than using the FluentFiltersBuilder. In this case, you can manage creation and lifetime of filter object and use Dependency Injection. To achieve this, you need to do several steps.

  1. Implement custom class which inherits FilterRegistry class and overrides GetFilterInstance method to resolve object by type instead of creating a new one. This class will be used instead FluentFiltersBuilder for registering filters.
  2. Create a custom Controller Factory for supporting IoC container and registering it.

You can find the sample application with IoC container in src\Samples\FluentFilters.Samples.IoC folder of the source code.

For basic configuration, it is sufficient to edit Global.asax.cs file like below:

// Global.asax.cs

using System.Web.Mvc;
using System.Web.Routing;
using FluentFilters;
using FluentFilters.Criteria;
using Website.Core.Filters;
namespace Website
    public class MvcApplication : System.Web.HttpApplication
        public static void RegisterRoutes(RouteCollection routes)
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", 
		id = UrlParameter.Optional } // Parameter defaults
        private static void RegisterFluentFilters()
            // Register global filter
        private static void RegisterControllerFactory()
            // Set controller factory
			(new FluentFiltersControllerFactory());
        protected void Application_Start()

You can see in the method RegisterFluentFilters registered filter BrowserDetectionFilter.

Later, when you added global filters for usage, you can set chain criteria for each of those. By criteria, you can set whether to execute filter or not. Create criteria is very simple too. You need to inherit your custom criteria class from IFilterCriteria interface and implement only method Match. The library already provides three criteria for use:

  • ActionFilterCriteria - Filter by specified action
  • AreaFilterCriteria - Filter by specified area
  • ControllerFilterCriteria - Filter by specified controller

For example, the code snippet below shows the source of the criteria ActionFilterCriteria:

public class ActionFilterCriteria : IFilterCriteria
    private readonly string _actionName;
    /// <summary>

    /// Filter by specified action
    /// </summary>
    /// <param name="actionName">Name of the action</param>

    public ActionFilterCriteria(string actionName)
        _actionName = actionName;
    #region Implementation of IActionFilterCriteria
    public bool Match(FilterRegistryContext context)
        return string.Equals(_actionName, 


For each filter, you can add two chains criteria. This is the criteria that is required and which should be excluded. If criteria are not specified, the filter will be executed for the entire application.

In the code below, we added filter BrowserDetectionFilter for area "Blog" and excluded for controller "Account":

(c =>

    c.Require(new AreaFilterCriteria("Blog")); // Execute if current area "Blog"
    c.Exclude(new ControllerFilterCriteria("Account")); // Ignore if current 
						// controller "Account"


You can build the Chain of criteria by methods And(IFilterCriteria criteria) and Or(IFilterCriteria criteria). Methods work as conditional logical operators && and ||.

Contrived example:

registry.Add<displaytopbannerfilter>(c =>
    c.Require(new IsFreeAccountFilterCriteria()).Or(new AreaFilterCriteria("Blog")).
	Or(new AreaFilterCriteria("Forum")).And(new IsMemberFilterCriteria());
    c.Exclude(new AreaFilterCriteria("Administrator")).
	Or(new ControllerFilterCriteria("Account")).
	And(new ActionFilterCriteria("LogOn"));

If speaking in C# language, then the code above can be understood as (like pseudocode):

if( IsFreeAccountFilterCriteria() || area == "Blog" || 
	(area == "Forum" && IsMemberFilterCriteria()) ) 
    if(area != "Administrator")
    else if(controller != "Account" && action != "LogOn")


  • 4th November, 2010: Initial version
  • 5th November, 2010: Updated article


This article, along with any associated source code and files, is licensed under The Apache License, Version 2.0


About the Author

Dmytro Antonenko
Software Developer (Senior) Epam Systems
United States United States
Who am I:
My name is Dmitry Antonenko and I'm developer with warm love to the web. My goal is to developing so it's beautifully simple and fast.

Currently I'm living in Irvine, CA and working as a lead software engineer at Epam Systems (Google TVC).

I do not specialize in one programming language or platform, I love to use all possible means to develop. I love to develop for front-end as well as for back-end ( but yes, front-end I like a little bit more ) Also like learn different algorithmic approaches that could be applied in development process.

What am I doing:
I try to make the Web better.


I like it:
.NET/C#, ASP.NET Core/MVC, HTML5, CSS3, JavaScript, Google Closure Library

You may also be interested in...

Comments and Discussions

GeneralNice Article. Pin
apoloion24-Nov-10 2:43
memberapoloion24-Nov-10 2:43 
GeneralMy vote of 5 Pin
jeka_kiselyov10-Nov-10 11:02
memberjeka_kiselyov10-Nov-10 11:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.180111.1 | Last Updated 8 Nov 2010
Article Copyright 2010 by Dmytro Antonenko
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid