Saturday, 5 August 2017

Action Filters

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 action filter applied to controller then it will be applied to all the action methods in that controller.
OutputCache is a built-in action filter attribute that can be apply to an action method for which we want to cache the output. For example, output of the following action method will be cached for 100 seconds.
Example: ActionFilter

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

You can create custom action filter for your application. Let's see how to create custom action filters.

Custom Action Filter:

You can create custom action filter by two ways. First, by implementing IActionFilter interface and FilterAttribute class. Second, by deriving ActionFilterAttribute abstract class.
IActionFilter interface include following methods to implement:
  • void OnActionExecuted(ActionExecutedContext filterContext)
  • void OnActionExecuting(ActionExecutingContext filterContext)
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 that ActionFilterAttribute class has four methods to overload. It includes OnResultExecuted and OnResultExecuting methods, which can be used to execute custom logic before or after result executes. Action filters are generally used to apply cross-cutting concerns such as logging, caching, authorization etc.
Consider the following custom Log filter class for logging.
Example: Custom ActionFilter for Logging

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.IO;


namespace BookTicketOnline.Common
{
    public class TrackExecutionTime:ActionFilterAttribute,IExceptionFilter
    {

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            string data = "\n" + filterContext.ActionDescriptor.ControllerDescriptor.ControllerName 
                + filterContext.ActionDescriptor.ActionName + "->On Action Executing->  date time" + DateTime.Now.ToString()
                +"\n";

            LogExecutionTime(data);
            
               
        }

        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            string data = "\n" + filterContext.ActionDescriptor.ControllerDescriptor.ControllerName 
                + filterContext.ActionDescriptor.ActionName + "->On Action Executed->  date time" + DateTime.Now.ToString()
                + "\n";

            LogExecutionTime(data);
            
        }

        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            string data = "\n" + filterContext.RouteData.Values["controller"] 
                + filterContext.RouteData.Values["action"] + "->On Result Executing->  date time" + DateTime.Now.ToString()
                + "\n";

            LogExecutionTime(data);
            
        }

        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            string data = "\n" + filterContext.RouteData.Values["controller"] 
                + filterContext.RouteData.Values["action"] + "->On Result Executed->  date time" + DateTime.Now.ToString()
                + "\n";

            LogExecutionTime(data);
            LogExecutionTime("------------------------------------------------------");
        }

        public void OnException(ExceptionContext filterContext)
        {
            string data = "\n" + filterContext.RouteData.Values["controller"] 
                    + filterContext.RouteData.Values["action"] + "->" + filterContext.Exception.Message + DateTime.Now.ToString()
                    + "\n";

            LogExecutionTime(data);
            LogExecutionTime("------------------------------------------------------");
            
        }
        private void LogExecutionTime(string data)
        {
            File.AppendAllText(HttpContext.Current.Server.MapPath("~/Data/Data.txt"), data);
        }
    }
}

As you can see, Log class derived ActionFilterAttribute class. It logs before and after action method or result executes. You can apply Log attribute to any Controller or action methods where you want to log the action. For example, by applying Log attribute to Controller, it will log each action methods of that controller.
Example: Apply Log ActionFilter to Controller

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using BookTicketOnline.Common;

namespace BookTicketOnline.Controllers
{
    public class HomeController : Controller
    {

        [TrackExecutionTime]
        public string CustomFilters()
        {
            return "filter invoked";
        }

        [TrackExecutionTime]
        public string Welcome()
        {
            throw new Exception("Exception occured");
        }
}
The above example will show following output in the output window of Visual Studio on http://localhost:3207/Home/welcome  request.
Output:



Homewelcome->On Action Executing->  date time26/08/2017 00:17:50

Homewelcome->On Action Executed->  date time26/08/2017 00:17:55

Homewelcome->Exception occured26/08/2017 00:17:55
------------------------------------------------------
Homecustomfilters->On Action Executing->  date time26/08/2017 00:37:47

Homecustomfilters->On Action Executed->  date time26/08/2017 00:37:47

Homecustomfilters->On Result Executing->  date time26/08/2017 00:37:47

Homecustomfilters->On Result Executed->  date time26/08/2017 00:37:47
------------------------------------------------------



Points to Remember :

  1. Action filters allow pre and post processing logic to be applied to an action method.
  2. Action filters are generally used to apply cross-cutting concerns such as logging, caching, authorization etc.
  3. Action filter can be registered as other filters at global, controller or action method level.
  4. Custom action filter attribute can be created by deriving ActionFilterAttribute class or implementing IActionFilter interface and FilterAttribute abstract class.
  5. Every action filter must override OnActionExecuted, OnActionExecuting, OnResultExecuted, OnResultExecuting methods.

No comments:

Post a Comment