MVC3: Filter Order Redux

Two points that I didn’t mention before about the Filter class and how filters are ordered. Firstly, the Order property on Filter is not nullable but the parameter you pass in on the constructor is. If you set this parameter to an integer when creating a new Filter then that will become the Order value for the filter. If you set this parameter to null then the new Filter class will see if the Instance implements IMvcFilter and use its Order property. If the Instance does not implement the IMvcFilter interface the new filter will use the Filter.DefaultOrder constant (which is currently –1 but you are better off referring to it as Filter.DefaultOrder in case it ever changes).

The second thing of interest as it relates to filter ordering is what happens when filters have the same Order and Scope. Filters for a particular action are retrieved from the FilterProviders, then put in order using an order preserving sort. This means that if two filters have the same Order and Scope then they will be executed (relatively) in the order that they were retrieved from the FilterProviders in the first place. By default this order is:

  1. All of the global filters (from GlobalFilters)
  2. All of the attribute filters (from FilterAttributeFilterProvider)
  3. The controller filter (from ControllerInstanceFilterProvider)
  4. All of the filters from the first custom FilterProvider you register
  5. All of the filters from the second custom FilterProvider you register
  6. …and so on

You can change this order by clearing and re-filling the FilterProviders.Providers collection like this:

FilterProviders.Providers.Clear();
FilterProviders.Providers.Add(new MyCustomFilterProvider());
FilterProviders.Providers.Add(GlobalFilters.Filters);
FilterProviders.Providers.Add(new FilterAttributeFilterProvider());
FilterProviders.Providers.Add(new ControllerInstanceFilterProvider());

And now any filters that get created by your MyCustomFilterProvider will get priority (all else being equal).

You could probably also do this:

FilterProviders.Providers.Insert(0, new MyCustomFilterProvider());

But the magic "0" is a little dirty-feeling.

Posted by: Mike Minutillo
Last revised: 27 May, 2011 02:55 PM History

Comments

No comments yet. Be the first!

No new comments are allowed on this post.