ASP.NET MVC - Action Filters

In the previous section, you learned about filters in MVC. In this section, you will learn about another filter type called action filters in ASP.NET MVC.

Action filter executes before and after an action method executes. Action filter attributes can be applied to an individual action method or to a controller. When an action filter is applied to a controller, it will be applied to all the controller's action methods.

The OutputCache is a built-in action filter attribute that can be applied to an action method for which we want to cache the output. For example, the output of the following action method will be cached for 100 seconds.

Example: ActionFilter
[OutputCache(Duration=100)]
public ActionResult Index()
{
    return View();
}

Crete a Custom Action Filter

You can create a custom action filter in two ways, first, by implementing the IActionFilter interface and the FilterAttribute class. Second, by deriving the ActionFilterAttribute abstract class.

The IActionFilter interface include following methods to implement:

  • void OnActionExecuted(ActionExecutedContext filterContext)
  • void OnActionExecuting(ActionExecutingContext filterContext)

The ActionFilterAttribute abstract class includes the following methods to override:

  • void OnActionExecuted(ActionExecutedContext filterContext)
  • void OnActionExecuting(ActionExecutingContext filterContext)
  • void OnResultExecuted(ResultExecutedContext filterContext)
  • void OnResultExecuting(ResultExecutingContext filterContext)

As you can see, the ActionFilterAttribute class has four overload methods. It includes the OnResultExecuted and the OnResultExecuting methods, which can be used to execute custom logic before or after the result executes. Action filters are generally used to apply cross-cutting concerns such as logging, caching, authorization, etc.

The following example demonstrates creating a custom action filter class for logging.

Example: Custom ActionFilter for Logging
public class LogAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        Log("OnActionExecuted", filterContext.RouteData); 
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        Log("OnActionExecuting", filterContext.RouteData);      
    }

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        Log("OnResultExecuted", filterContext.RouteData);      
    }

    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        Log("OnResultExecuting ", filterContext.RouteData);      
    }

    private void Log(string methodName, RouteData routeData)
    {
        var controllerName = routeData.Values["controller"];
        var actionName = routeData.Values["action"];
        var message = String.Format("{0}- controller:{1} action:{2}", methodName, 
                                                                    controllerName, 
                                                                    actionName);
        Debug.WriteLine(message);
    }
}

Above, the Log class derived the ActionFilterAttribute class. It logs before and after the action method or result executes. You can apply the Log attribute to any controller or an action method where you want to log the execution of the action method.

Example: ActionFilter on Controller
[Log]
public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult About()
    {
        return View();
    }

    public ActionResult Contact()
    {
        return View();
    }
}

The above example will show the following output when browing to http://localhost/home request.

Output:
OnActionExecuting- controller:Home action:Index
OnActionExecuted- controller:Home action:Index
OnResultExecuting - controller:Home action:Index
OnResultExecuted- controller:Home action:Index

In this way, you can keep track of the action methods execution using action filters.