ASP.NET MVC Filters allow us to inject extra logic into MVC Framework request processing, this logic either before or after an action is executed. They provide a simple and elegant way to implement cross-cutting concerns. This term refers to functionality that is used all over an application and doesn’t fit neatly into any one place, where it would break the separation of concerns pattern. Classic examples of cross-cutting concerns are logging, authorization, and caching. In this article, I will show you the different categories of filters that the MVC Framework supports, how to create and use filters, and how to control their execution. We can make your own custom filters or attributes either by implementing ASP.NET MVC filter interface or by inheriting and overriding methods of ASP.NET MVC filter attribute class if available.
Understanding the Four Basic Types of Filters
The ASP.NET MVC Framework supports four different types of filters. Each allows you to introduce logic at different points during request processing. The four filter types are described in Table.
Filter Type | Interface | Default Implementation | Description |
---|---|---|---|
Authentication | IAuthenticationFilter | AuthenticationAttribute | Runs first before any other filters or the action method |
Authorization | IAuthorizationFilter | AuthorizeAttribute | Runs first before any other filters or the action method |
Action | IActionFilter | ActionFilterAttribute | Runs before and after the action method |
Result | IResultFilter | ActionFilterAttribute | Runs before and after the action result is executed |
Exception | IExceptionFilter | HandleErrorAttribute | Runs only if another filter the action method or the action result throws an exception |
Before the MVC Framework invokes an action, it inspects the method definition to see if it has Attributes that implement the interfaces listed in above Table. If so, then at the appropriate point in the request pipeline, the methods defined by these interfaces are invoked. The framework includes default attribute classes that implement the filter interfaces.
Note:- The ActionFilterAttribute class implements both the IActionFilter and IResultFilter interfaces. This class is abstract, which forces you to provide an implementation. The other classes, Authorize Attribute and HandleErrorAttribute, contain useful features and can be used without creating a derived class.
Applying Filters to Controllers and Action Methods Filters can be applied to individual action methods or to an entire controller. Following code shows, how can we apply the Authorize filter to the AdminController class, which has the same effect as applying it to each action method in the controller.
public class AdminController : Controller { // ... instance variables and constructor [Authorize] public ViewResult Index() { // ...rest of action method } [Authorize] public ViewResult Create() { // ...rest of action method } // ... other action methods }
Applying Multiple Filters in a Controller Class
You can apply multiple filters, and mix and match the levels at which they are applied—that is, whether they are applied to the controller or an individual action method. Following code shows three different filters in use.
[Authorize(Roles="trader")] // applies to all actions public class ExampleController : Controller { [ShowMessage] // applies to just this action [OutputCache(Duration=60)] // applies to just this action public ActionResult Index() { // ... action method body } }
Using Authentication Filters
Authentication Filters is introduced with ASP.NET MVC5. The IAuthenticationFilter interface is used to create CustomAuthentication filter. The definition of this interface is given below-
public interface IAuthenticationFilter { void OnAuthentication(AuthenticationContext filterContext); void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext); }
We can create our CustomAuthentication filter attribute by implementing IAuthenticationFilter , An example of CustomAuthentication is given below.
public class CustomAuthenticationAttribute : ActionFilterAttribute, IAuthenticationFilter { public void OnAuthentication(AuthenticationContext filterContext) { //Logic for authenticating a user } //Runs after the OnAuthentication method Public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext) { //TODO: Additional tasks on the request } }
Using Authorization Filters
Authorization filters are the filters that are run first—before the other kinds of filters and before the action method is invoked. As the name suggests, these filters enforce your authorization policy, ensuring that action methods can be invoked only by approved users. Authorization filters implement the IAuthorizationFilter interface, which is shown below.
namespace System.Web.Mvc { public interface IAuthorizationFilter { void OnAuthorization(AuthorizationContext filterContext); } }
You can, if you are so minded, create a class that implements the IAuthorizationFilter interface and create your own security logic.
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace Filters.Infrastructure { public class CustomAuthAttribute : AuthorizeAttribute { private bool localAllowed; public CustomAuthAttribute(bool allowedParam) { localAllowed = allowedParam; } protected override bool AuthorizeCore(HttpContextBase httpContext) { if (httpContext.Request.IsLocal) { return localAllowed; } else { return true; } } } }
This is a simple authorization filter. It allows you to prevent access to local requests (a local request is one where the browser and the application server are running on the same device, such as your development PC). We have used the simplest approach to creating an authorization filter, which is to subclass the AuthorizeAttribute class and then override the AuthorizeCore method. This ensures that we benefit from the features built in to AuthorizeAttribute. The constructor for our filter takes a bool value, indicating whether local requests are permitted.
Using Action Filters
Action filters are filters that can be used for any purpose. The built-in class for creating this kind of filter, IActionFilter, is shown in following code
namespace System.Web.Mvc { public interface IActionFilter { void OnActionExecuting(ActionExecutingContext filterContext); void OnActionExecuted(ActionExecutedContext filterContext); } }
This interface defines two methods. The MVC Framework calls the OnActionExecuting method before the action method is invoked. It calls the OnActionExecuted method after the action method has been invoked.
The OnActionExecuting method is called before the action method is invoked. You can use this opportunity to inspect the request and elect to cancel the request, modify the request, or start some activity that will span the invocation of the action.You can use a filter to cancel the request by setting the Result property of the parameter to an action result. To demonstrate this, we have created our own action filter class called CustomActionAttribute in the Infrastructure folder of the example project, as shown below.
namespace Filters.Infrastructure { public class CustomActionAttribute : FilterAttribute, IActionFilter { public void OnActionExecuting(ActionExecutingContext filterContext) { if (filterContext.HttpContext.Request.IsLocal) { filterContext.Result = new HttpNotFoundResult(); } } public void OnActionExecuted(ActionExecutedContext filterContext) { // not yet implemented } } }
Using Result Filters
Result filters are general-purpose filters which operate on the results produced by action methods. Result filters implement the IResultFilter interface, which is shown in following code.
namespace System.Web.Mvc { public interface IResultFilter { void OnResultExecuting(ResultExecutingContext filterContext); void OnResultExecuted(ResultExecutedContext filterContext); } }
Assuming, that we know about how action methods return action results, allowing us to separate the intent of an action method from its execution. When we apply a result filter to an action method, the OnResultExecuting method is invoked when the action method has returned an action result but beforethe action result is executed. The OnResultExecuted method is invoked after the action result is executed.
To demonstrate a simple result filter, we created a new class file called ProfileResultAttribute.cs in the Infrastructure folder and used it to define the class shown in following code sample.
using System.Diagnostics; using System.Web.Mvc; namespace Filters.Infrastructure { public class ProfileResultAttribute : FilterAttribute, IResultFilter { private Stopwatch timer; public void OnResultExecuting(ResultExecutingContext filterContext) { timer = Stopwatch.StartNew(); } public void OnResultExecuted(ResultExecutedContext filterContext) { timer.Stop(); filterContext.HttpContext.Response.Write( string.Format("<div>Result elapsed time: {0}</div>",timer.Elapsed.TotalSeconds)); } } }
Using Exception Filters
Exception filters are run only if an unhandled exception has been thrown when invoking an action method. The exception can come from the following locations:
1. Another kind of filter (authorization, action, or result filter)
2. The action method itself
3. When the action result is executed
Creating an Exception Filter Exception filters must implement the IExceptionFilter interface, which is shown in following code.
namespace System.Web.Mvc { public interface IExceptionFilter { void OnException(ExceptionContext filterContext); } }
The Result property is used by the exception filter to tell the MVC Framework what to do. To demonstrate how this all fits together, we have created a new class file called RangeExceptionAttribute.cs, which we added to the Infrastructure folder of our example project. The contents of this file are shown in following code.
using System; using System.Web.Mvc; namespace Filters.Infrastructure { public class RangeExceptionAttribute : FilterAttribute, IExceptionFilter { public void OnException(ExceptionContext filterContext) { if (!filterContext.ExceptionHandled && filterContext.Exception is ArgumentOutOfRangeException) { filterContext.Result = new RedirectResult("~/Content/RangeErrorPage.html"); filterContext.ExceptionHandled = true; } } } }
Order of Filter Execution in ASP.NET MVC
All ASP.NET MVC filter are executed in an order. Following list shows the order in which ASP.NET MVC Filters are executing.
1. Authentication filters
2. Authorization filters
3. Action filters
4. Result filters
Configuring Filters in ASP.NET MVC
It is very important to know about how to configure your own custom filter. We can divide the filter configuration into your application at following three levels:
Global level
If we will register our filter in Global.ascx.cs file at Application_Start event than it can be applied at global level, Following code example shows how we can register filter into of Global.asax.cs file with the help of FilterConfig class.
protected void Application_Start() { FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); }
Controller level
ASP.NET MVC also provides us the option to configure filters at controller level. Following code shows how we can do that by just putting your filter on the top of the controller name.
[Authorize(Roles="Admin")] public class AdminController : Controller { // }
Action level
ASP.NET MVC Filters can be applied at Action Level. By putting your filter on the top of the action name as shown below
public class UserController : Controller { [Authorize(Users="User1,User2")] public ActionResult LinkLogin(string provider) { // TODO: return View(); } }
Summary
By reading this article carefully, you must be able to understand about ASP.NET MVC Filters, It’s uses and working flows. I hope that you will like this article and will keep posting about other ASP.NET MVC concepts.