ASP.NET MVC 3.0 introduces global action filters - an easy way to apply an action filter to every action in an MVC application. All you need to do is register the filters during application startup:
protected void Application_Start()
{
...
GlobalFilters.Filters.Add(new HandleErrorAttribute()); GlobalFilters.Filters.Add(new FooFilter()); GlobalFilters.Filters.Add(new BarFilter());... }
But what if you wanted to add (or remove) filters through configuration?
<configSections> <section name="filters" type="ConfigurableFilters.FiltersSettings, AssemblyName "/> </configSections> ... <filters> <add type="System.Web.Mvc.HandleErrorAttribute, System.Web.Mvc..." /> <add type="ConfigurableFilters.BarFilter, AssemblyName" /> <add type="ConfigurableFilters.FooFilter, AssemblyName" /> </filters>
In that case you'll need a ConfigurationElement.
public class FilterAction : ConfigurationElement { [ConfigurationProperty("type", IsRequired = true, IsKey = true)] public string Type { get { return base["type"] as string; } set { base["type"] = value; } } }
And a ConfigurationElementCollection.
public class FilterActionCollection : ConfigurationElementCollection { protected override ConfigurationElement CreateNewElement() { return new FilterAction(); } protected override object GetElementKey(ConfigurationElement element) { return ((FilterAction) element).Type; } }
And a ConfigurationSection.
public class FiltersSettings : ConfigurationSection { public static FiltersSettings Settings { get { var section = ConfigurationManager.GetSection("filters") as FiltersSettings; return section ?? new FiltersSettings(); } } [ConfigurationProperty("", IsDefaultCollection = true)] public FilterActionCollection Filters { get { return base[_filtersProperty] as FilterActionCollection; } set { base[_filtersProperty] = value; } } private readonly ConfigurationProperty _filtersProperty = new ConfigurationProperty( null, typeof (FilterActionCollection), null, ConfigurationPropertyOptions.IsDefaultCollection); }
One way to apply the configured filters is to use the following code during application startup:
var filters = FiltersSettings.Settings.Filters; foreach (var filter in filters.Cast<FilterAction>()) { var filterType = Type.GetType(filter.Type); GlobalFilters.Filters.Add(Activator.CreateInstance(filterType)); }
Another approach is to implement a filter provider. We'll take a look at the provider approach tomorrow.