How to roll your own custom action filter in ASP.NET MVC?

In this post I’ll explain you how to roll your own custom action filter in ASP.NET MVC framework. Make sure you know all the out of the box action filters available in the framework so that you can either reuse or extend them.

If you would like to apply any pre or post processing logic to a controller action and it’s result, ASP.NET MVC framework provides what is called as action filters that can be used in your application.. An action filter can be consumed at different levels like at controller or action or global level. If a filter is applied to just an action, it’s only available to that action. If it is applied at controller level, it works for all the actions inside that controller. And self-explanatory, if it is defined at the global level, i.e. using FilterConfig in Global.asax.cs file, then it applies to all of the controllers and thus, actions.

Action filters are very powerful as it allows you to intercept the action’s requesting, requested and result’s executing, executed methods to perform some custom processing that your application needs. This can be very useful if you don’t want to rewrite some piece of code for every action or controller and that’s a good way to roll your own action filter.

Let us look at the important step to create a custom action filter. This is done by creating a class that derives from ActionFilterAttribute that is found in System.Web.Mvc namespace. Below are the methods that are marked as virtual so that the derived class can override them as per the requirements.

Let us take a scenario where there is a requirement to log something when the execution of an action:-  method starts, ends and result starts, ends. Below is the code to create such a custom action filter:

/// <summary>
/// A custom action filter for logging
/// </summary>
public class WebActivityLogger : ActionFilterAttribute
{
    /// <summary>
    /// Called by the ASP.NET MVC framework before the action method executes.
    /// </summary>
    /// <param name="filterContext">The filter context.</param>
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        Debug.WriteLine("Action method execution starts."); // use a logger with StopWatch to log the time.
        base.OnActionExecuting(filterContext);
    }

    /// <summary>
    /// Called by the ASP.NET MVC framework after the action method executes.
    /// </summary>
    /// <param name="filterContext">The filter context.</param>
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        base.OnActionExecuted(filterContext);
        Debug.WriteLine("Action method execution ends."); // use a logger with StopWatch to log the time.
    }

    /// <summary>
    /// Called by the ASP.NET MVC framework before the action result executes.
    /// </summary>
    /// <param name="filterContext">The filter context.</param>
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        Debug.WriteLine("Action result execution starts."); // use a logger with StopWatch to log the time.
        base.OnResultExecuting(filterContext);
    }

    /// <summary>
    /// Called by the ASP.NET MVC framework after the action result executes.
    /// </summary>
    /// <param name="filterContext">The filter context.</param>
    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        base.OnResultExecuted(filterContext);
        Debug.WriteLine("Action result execution ends."); // use a logger with StopWatch to log the time.
    }
}

The parameter that is passed in each override is very useful if you would like to know more about the context or change something, examples:

  • Get the parameters that were passed to the action, names of controller & action.
  • Manipulate the result that is returned by an action.
  • Look for any exception if it was encountered and check if it was handled or not.

Look into the definition of each context and see what are the other options available that can be helpful to make most of the custom action filter. Remember to call the base methods after your custom code so that the system can still continue to process the request after your code execution.

Now, the usage of this filter at different levels will look like this:

// Register the filter at global level in FilterConfig.cs file
// This will work for all the controllers in application.
public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        // A logger instance can be passed to the custom filter by
        // creating a constructor.
        filters.Add(new WebActivityLogger());
    }
}

// Apply it on a controller level.
// This will work for all the actions in this controller.
[WebActivityLogger]
public class HomeController : Controller
{
}

// Apply it on a action only.
// This will just work for this action only.
[WebActivityLogger]
public ActionResult About()
{
    return Content("About");
}

As I said above, before writing a custom filter from scratch, make sure you are aware of the existing filters available in the framework. Then make a decision to either reuse them and extend for your scenario. Anyway, with the steps mentioned above, one can easily create a custom action filter in ASP.NET MVC framework.

Siddharth Pandey

Siddharth Pandey is a Software Engineer with thorough hands-on commercial experience & exposure to building enterprise applications using Agile methodologies. Siddharth specializes in building, managing on-premise, cloud based real-time standard, single page web applications (SPAs). He has successfully delivered applications in health-care, finance, insurance, e-commerce sectors for major brands in the UK. Other than programming, he also has experience of managing teams, trainer, actively contributing to the IT community by sharing his knowledge using Stack Overflow, personal website & video tutorials.

You may also like...

Advertisment ad adsense adlogger