ASP.NET MVC 5 has a new feature called Filter Overrides, which allows you to clear or replace certain filter types created in higher scopes. For example, if you created a global action filter or controller action filter, you could override those filters on a case-by-case basis at the controller action level. This allows you to set global or controller filters that apply in almost all cases and just override them in the few, specific places where those filters don't apply. I love this new Filter Overrides feature just as much as Attribute Routing in ASP.NET MVC 5. I'll take that same example I used for Attribute Routing and show how to implement Filter Overrides.
ASP.NET MVC 5 Filter Overrides
I've taken that same ProductsController from my Attribute Routing Example and decorated it with two new attributes. At the controller level, I have added the [RequireHttps] Attribute ( an IAuthorizationFilter ) that requires ALL controller actions be invoked using HTTPS. However, I have one controller action that I decided could be invoked without SSL, the Index Controller Action.
This is where Filter Overrides in ASP.NET MVC 5 can be helpful. I can decorate the Index Controller Action with an [OverrideAuthorization] Attribute, which essentially clears all IAuthorization Filters in the upper scopes ( controller, global, etc. ). Hence, the [RequireHttps] Attribute does not apply to this controller action and the Index Action can be invoked either with HTTP or HTTPS.
Filter Overrides in ASP.NET MVC 5 is perfect for those times where a filter applies almost globally or to all controller actions and there are just a few exceptions. In this case it is easier to declare a filter broadly and then just mark the exceptions with a Filter Override.
Note that although I didn't do it in this example, I could have decorated my Index Action with new filters, even IAuthorizationFilters, and those would be active since the Override Filter only applies to filters in a higher scope.
[RoutePrefix("products")] [RequireHttps] public class ProductsController : Controller { private readonly IProductCatalog _productCatalog; public ProductsController(IProductCatalog productCatalog) { _productCatalog = productCatalog; } [Route] [OverrideAuthorization] public ActionResult Index() { var products = _productCatalog.FetchAll(); return View(products); } [Route("{id:int}")] public ActionResult ViewById(int id) { var product = _productCatalog.FetchProduct(id); return View("View", product); } [Route("{code:alpha:length(6)}")] public ActionResult ViewByCode(string code) { var product = _productCatalog.FetchProduct(code); return View("View", product); } }
There are several Filter Override Attributes in ASP.NET MVC 5, allowing you to clear filters by their type:
- [OverrideActionFilters]
- [OverrideAuthentication]
- [OverrideAuthorization]
- [OverrideExceptionFilters]
- [OverrideResultFilters]
These all implement IOverrideFilter, which is an interface you can implement on your own classes to create custom FilterAttributes.
A Bug in Filter Overrides in ASP.NET MVC 5
Unfortunately, there is a bug in ASP.NET MVC 5 with Filter Overrides that has been fixed in the ASP.NET MVC 5.1 Preview. To get this to work in my example, I created my own [OverrideAuthorization] Attribute that implements IOverrideFilter, etc.
public class OverrideAuthorizationAttribute : FilterAttribute, IOverrideFilter { public Type FiltersToOverride { get { return typeof (IAuthorizationFilter); } } }
Conclusion
As you can see, Filter Overrides in ASP.NET MVC 5 are quite handy when you are implementing global or controller filters in your ASP.NET MVC Websites and only need to override them in a few places using Filter Overrides.
Make sure you check out Attribute Routing in ASP.NET MVC 5 as part of my ASP.NET MVC 5 Tutorials. For Orchard CMS Developers, we will be able to use these new ASP.NET MVC 5 features in Orchard 1.8!