Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / All-Topics

Filters in MVC

3.00/5 (1 vote)
24 Jan 2015CPOL5 min read 30.6K  
Filters in MVC

The post Filters in MVC appeared first on codecompiled.

Filters

Filters is defined as an attribute which contains the common functionality or the cross cutting concern. The logic contained in a filter executes when the action method with which the filter is attached executes. Common examples of such cross cutting concerns are the logging and the caching functionality. Logging is used across the different layers in an application so it makes sense to encapsulate such functionality.

Instead of duplicating such functionality across different action methods and controllers, we can encapsulate the common functionality in a filter. So we define a filter once and then apply it to the different controllers and action methods.

We can apply a filter to an action method or to a controller, applying a filter to a controller has the same effect as applying the filter to each of the action methods in a controller.

So the following two code snippets are effectively the same:

  1. Attaching filter to a controller

    In the following example, we are attaching the HandleError filter to the Home Controller.

    C#
    [HandleError]
    public class HomeController : Controller
    {
    public ActionResult Index()
    {
    return View();
    }
    
    public ActionResult About()
    {
    return View();
    }
    }
  2. Attaching filter to action methods in a controller

    In the following example, we are attaching the HandleError filter to each of the action methods in the Home Controller.

    C#
    public class HomeController : Controller
    {
    [HandleError]
    public ActionResult Index()
    {
    return View();
    }
    [HandleError]
    public ActionResult About()
    {
    return View();
    }
    }

Different Types of Filters

Filters are classified in the following types according to the types of functionality which they provide and their sequence in the request processing pipeline. Also, different filter types implement different interfaces. Filters and their execution sequence is as follows:

  • Authentication filters: Verify if the request can execute the action method
  • Authorization filters: Verify if the request is Authorized to execute the action method
  • Action filters: Provide functionality which is executed before and after the action method executes
  • Result filters: Provide functionality which is executed before and after the action result executes
  • Exception filters: Provide functionality which executes if an unhandled error occurs

The above filters are called in a sequence. So, if both the Authentication and the Authorization filters are attached to an action method, the Authentication filter will be called before the Authorization filter.

Let's see how we can use the above filters.

Authentication filter is the first filter to execute and is used to authenticate the request. Authentication filter was introduced in MVC 5.

Authentication filter implements the filter IAuthenticationFilter interface which is defined as:

C#
public interface IAuthenticationFilter
 {
void OnAuthentication(AuthenticationContext filterContext);
void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext);
 }

OnAuthetication method is the first of all the filter methods which gets called. We can allow or deny access to the user making the request in this method. So this is the method in which we can implement our authentication policy. It is passed a parameter of the type AuthenticationContext. AuthenticationContext has a property Result of type ActionResult.

If we want to deny the access to action method for the current request, then we can assign a HttpUnauthorizedResult object to the Result property as:

C#
public class AuthenticationAttribute : ActionFilterAttribute, IAuthenticationFilter
 {
public void OnAuthentication(AuthenticationContext filterContext)
{
filterContext.Result = new HttpUnauthorizedResult();
}
public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
 {
// filterContext.Result = new ViewResult();
 }
}

If we apply the AuthenticationAttribute to any action method, the following login screen is displayed. As we have set the result property to HttpUnauthorizedResult type, so the user is redirected to the login screen.

authentication filter

Authorization filter implements the IAuthorizationFilter interface which is defined as:

C#
public interface IAuthorizationFilter {
void OnAuthorization(AuthorizationContext filterContext);
}

Instead of creating a custom Authorization filter attribute, there is a built in AuthorizeAttribute which we can use to define the authorization policy. This attribute has two important properties:

  • Users: A comma separated list of users who are allowed to access the action method
  • Roles: A comma separated list of roles which are allowed to access the action method

The following Authorize attribute limits the access to the action method only to the user “user1″.

C#
[Authorize(Users="user1")]
public ActionResult Index()
{
return View();
}

Action filter: We use action filters to define the functionality which we want to execute before an action method executes or after an action method executes.

Normally, we define custom functionality using the Action filters. Though there are few built in Action filters also. OutputCache is an example of a built in action filter.

Action filters implements the IActionFilter interface. This interface is defined as:

C#
public interface IActionFilter {
void OnActionExecuting(ActionExecutingContext filterContext);
void OnActionExecuted(ActionExecutedContext filterContext);
}
  • OnActionExecuting defines the functionality which we want to execute before the action method executes.
  • OnActionExecuted defines the functionality which we want to execute after the action method executes

So we can define an action filter by defining a class implementing IActionFilter interface as:

C#
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class ActionTestAttribute : FilterAttribute, IActionFilter
{
public void OnActionExecuted(ActionExecutedContext filterContext)
{
filterContext.HttpContext.Response.Write("Action method executed.");
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.HttpContext.Response.Write("Action method going to execute </br>");
}
}

So we get the following response in browser if we apply the above filter attribute to any action method.

action filters in mvc

As we have implemented the OnActionExecuting and OnActionExecuted methods so our filter logic executes before the action method executes and after the action method executes.

Result filter: Defines functionality which executes after the action result is returned by the action method. Result filters implement the interface IResultFilter which is defined as:

C#
public interface IResultFilter {
void OnResultExecuting(ResultExecutingContext filterContext);
void OnResultExecuted(ResultExecutedContext filterContext);
}
  • OnResultExecuting executes after the action result is returned by the action method but before the action result executes.
  • OnResultExecuted executes after the action result completes execution.

Exception filter: We use exception filters to handle exceptions which are not handled in our action method. Exception filters implements the interface IExceptionFilter which is defined as:

C#
public interface IExceptionFilter {
void OnException(ExceptionContext filterContext);
}

The OnException method is called when an unhandled exception occurs.

Instead of creating a class implementing the IExceptionFilter interface, we can use the built in HandleError attribute. HandleError attribute defines the following two important properties:

  • ExceptionType: The type of exception the HandleError attribute will handle
  • View: The view that is rendered if an unhandled error occurs

To handle the ArgumentNullException, we can apply the HandleError attribute as:

C#
[HandleError(ExceptionType=typeof(ArgumentNullException),View="CustomError")]
public ActionResult Details(int id)
{
return View();
}

If no value is passed for the action method’s id parameter, then the view specified in the View property will be displayed to the user.

Overriding the Controller Base Class Methods

As we have seen above, we can create custom filters by creating an attribute and then attaching the attribute to the controller or the action method. Instead of explicitly defining the attributes implementing these interfaces, we can directly implement the methods defined by these interfaces in the controller class. The controller class implements all the different filter interfaces.

As the controller class implements these filter interfaces, so it defines the methods declared by these interfaces. These methods are defined as virtual which we can override in our controller class:

C#
protected virtual void OnActionExecuted(ActionExecutedContext filterContext);
protected virtual void OnActionExecuting(ActionExecutingContext filterContext);
protected virtual void OnAuthentication(AuthenticationContext filterContext);
protected virtual void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext);
protected virtual void OnAuthorization(AuthorizationContext filterContext);
protected virtual void OnException(ExceptionContext filterContext);
protected virtual void OnResultExecuted(ResultExecutedContext filterContext);
protected virtual void OnResultExecuting(ResultExecutingContext filterContext);

So instead of applying the action filter attributes to our action methods or the controller, we can override the above methods in our controller class as:

C#
public class HomeController : Controller
{
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
// executes before the action method execution 
}

protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
// executes after the action method executes
}

}

So we can use the different types of filters for implementing cross cutting concerns and avoid the code duplication.

The post Filters in MVC appeared first on codecompiled.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)