Click here to Skip to main content
15,886,518 members
Articles / Web Development / ASP.NET

FluentFilters for ASP.NET MVC 3 - Register global filters by specified conditions

Rate me:
Please Sign up or sign in to vote.
4.20/5 (4 votes)
22 Jun 2011Apache3 min read 47.4K   28   3
This article describes how to use the FluentFilters library with ASP.NET MVC 3 to add support for criteria for global filters.

Fluent Filters

Introduction

Last year I wrote about FluentFilters and how to use them with ASP.NET MVC 2 to implement the functionality of global filters. With ASP.NET MVC 3 was added native support for global filters. You can register a global filter by using the GlobalFilters.Filters static registration endpoint. It works great, but sometimes it would be nice to specify conditions for running the filter like criteria in FluentFlters.

Recently, I updated the library and added a version for ASP.NET MVC 3 in which I implemented the functionality described above. This version was completely rewritten in accordance with the new features of ASP.NET MVC 3. As a result of this, the library became smaller and easier to use.

Please note that the versions for ASP.NET MVC 2 and ASP.NET MVC 3 are different. The assembly for ASP.NET MVC 2 is now located in the /bin/mvc2 folder of the library binary package (to learn how to use it, please read the previous article).

Below, I describe the FluentFilters for ASP.NET MVC 3:

  1. How to configure the application to work with the library
  2. How to register filters and specify conditions by criteria
  3. How to create custom criteria

Let's start

To start using FluentFilters is very simple:

  1. Download the latest version of the library from the Downloads page at CodePlex.
  2. Unzip the zip file and add a reference to /bin/mvc3/FluentFilters.dll in your MVC project.
  3. Instead of steps 1-2, you can use NuGet. Right click on References and click Add Library Package Reference. Click Online on the left side, and in the Search box at the upper right, type in "FluentFilters". Click Install. Alternatively, open the Package Manager Console and type "Install-Package FluentFilters".
  4. Register the FluentFiltersCollection filter provider in Global.asax.cs.
  5. Use the FluentFiltersBuider.Filters static registration endpoint to register a global filter with conditions.

It should look like below:

C#
protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
 
    // Register provider
    FilterProviders.Providers.Add(FluentFiltersBuider.Filters);
    // Register Global Filters
    RegisterGlobalFilters(GlobalFilters.Filters, 
                          FluentFiltersBuider.Filters);
 
    RegisterRoutes(RouteTable.Routes);
}

public static void RegisterGlobalFilters(GlobalFilterCollection filters, 
                   FluentFilterCollection fluentFilters)
{
    filters.Add(new HandleErrorAttribute());
 
    fluentFilters.Add<DisplayTopBannerFilterAttribute>(c => {
        c.Require(new AreaFilterCriteria("Blog")).Or(new AreaFilterCriteria("Forum"));
        c.Exclude(new ControllerFilterCriteria("Admin")).And(
                  new AreaFilterCriteria("Forum"));
    });
}

Registering filters

To register a filter, you need to call the method FluentFilterCollection.Add(). The provider has a few method definitions:

C#
// Register filter by type
void Add<T>()
void Add<T>(int order)
void Add<T>(Action<IFilterCriteriaBuilder> criteria)
void Add<T>(Action<IFilterCriteriaBuilder> criteria, int order)

// Register filter by instance
void Add(object filter, Action<IFilterCriteriaBuilder> criteria)
void Add(object filter, Action<IFilterCriteriaBuilder> criteria, int order)

By using registration, for instance, you can set values for the properties:

C#
fluentFilters.Add( new HandleErrorAttribute() { View = "ErrorPage" }, 
              c => { c.Require(new AreaFilterCriteria("Admin"))} );

Specify conditions

To specify the conditions, you should set the chain of criteria for the filter at registration. Using criteria, you can set whether to execute a filter or not. The library already provides three criteria for use:

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

For one filter, you can only specify two chains of criteria. These are the chains of criteria that are required and which should be excluded.

C#
fluentFilters.Add<CheckAuthenticationAttribute>(c =>
{
    // Execute if current area "Blog"
    c.Require(new AreaFilterCriteria("Blog"));
    // But ignore if current controller "Account"
    c.Exclude(new ControllerFilterCriteria("Account"));
});

Chains of criteria are constructed by using the methods And(IFilterCriteria criteria) and Or(IFilterCriteria criteria), which work as conditional logical operators && and ||.

C#
fluentFilters.Add<DisplayTopBannerFilterAttribute>(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 using the C# language, then the code above can be understood as (like pseudocode):

C#
if( IsFreeAccountFilterCriteria() || area == "Blog" || 
    (area == "Forum" && IsMemberFilterCriteria()) ) 
{
    if(area != "Administrator")
    {
        DisplayTopBannerFilter();
    }
    else if(controller != "Account" && action != "LogOn")
    {
        DisplayTopBannerFilter();
    }
}

Creating a custom criteria

To create a custom criteria, you should inherit your class from the FluentFilters.IFilterCriteria interface and implement only one method Match. For example, see the source code for ActionFilterCriteria:

C#
public class ActionFilterCriteria : IFilterCriteria
{
    #region Fields

    private readonly string _actionName;

    #endregion

    #region Constructor

    /// <summary>
    /// Filter by specified action
    /// </summary>
    /// <param name="actionName">Name of the action</param>
    public ActionFilterCriteria(string actionName)
    {
        _actionName = actionName;
    }

    #endregion

    #region Implementation of IActionFilterCriteria

    public bool Match(ControllerContext controllerContext, 
                ActionDescriptor actionDescriptor)
    {
        return string.Equals(_actionName, 
          controllerContext.RouteData.GetRequiredString("action"), 
          StringComparison.OrdinalIgnoreCase);
    }

    #endregion
}

License

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


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

Comments and Discussions

 
GeneralMy vote of 5 Pin
shatl7-Jan-12 1:25
shatl7-Jan-12 1:25 
GeneralGood Article Pin
aamironline10-Feb-11 18:02
aamironline10-Feb-11 18:02 
GeneralRe: Good Article Pin
Dmytro Antonenko10-Feb-11 19:40
professionalDmytro Antonenko10-Feb-11 19:40 

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.