ASP.NET MVC Custom Action Filters

Posted by: Suprotim Agarwal , on 2/2/2014, in Category ASP.NET MVC
Views: 112509
Abstract: This article talks about creating Custom Action Filters in ASP.NET MVC

Filters in ASP.NET MVC are a way to apply cross-cutting logic at the controller level. Some examples of cross-cutting logic is Security and Logging. Security is a cross cutting concern because, once enabled, we need to apply it for all incoming requests in the web Application. Imagine a world where you don’t have filters, in such case for every request that comes in, your Action method in controller will have to check if the user was Authorized to perform the action and view its result.

This not only violates single responsibility principle of the Action Method (it’s doing two things, evaluating security and computing the Action’s output) but is also an extremely verbose and repetitive work that we’ve to do irrespective of what the Action is supposed to do. Moreover, writing Authentication Code in action method cannot be guaranteed. There is no certainty that a developer may or may not miss out on implementing the code!

 

 

 

In comes Security Filters! The Authorize Attribute that we set at a class, method or property level in a Controller is nothing but a Security Filter implementation. All your security related code is now abstracted out of the Action method into the filter, that’s executed before the action method is executed. Voila!

Types of Filters in ASP.NET MVC and their Sequence of Execution

There are four types of Filters in ASP.NET MVC 4

1. Authorization Filters: Responsible for checking User Access, these implement the IAuthorizationFilter interface in the framework. The AuthorizeAttribute and RequireHttpsAttribute are examples of Authorization Filters.

2. Action Filters: These implement the IActionFilter interface that have two methods OnActionExecuting and OnActionExecuted. OnActionExecuting runs before the Action and gives an opportunity to cancel the Action call.

3. Result Filters: These implement the IResultFilter interface which like the IActionFilter has OnResultExecuting and OnResultExecuted. The OutputCacheAttribute class is example of a Result Filter.

4. ExceptionFilters: These implement the IExceptionFilter interface and they execute if there are any unhandled exceptions thrown during the execution pipeline. The HandleErrorAttribute class is an example of such a filters.

Apart from using the Filter Attribute, each controller class implements all four interfaces; so if applying an attribute is not something you prefer, you can override the methods in your controller class if you want.

Action Filters – Whys and Hows

As we saw above, Action Filters are second in line to be executed in the MVC Pipeline. They are kind of the ‘catch all’ filters. You do all ‘other’ filtering activity there. What could be an example of such ‘other’ activity that is a cross-cutting concern? Well, Logging comes to mind as comes Session Management.

One neat use of IActionFilter interfaces I’ve seen is by Ayende Rahien to save Data in RavenDB. Ayende uses the OnActionExecuting method to open a RavenDb Session and the OnActionExecuted method to save the Session data if there are no errors. This leaves the Controller method with the responsibility of checking/validating the incoming data only. In the above example, Ayende overrides the interface method of the controller itself thus making a base controller for you to derive your controller classes from.

Another good example can been seen when you create a new MVC 4 project using the Internet template, Visual Studio actually code-gens the filter that creates default database for Forms Authentication in the InitializeSimpleMembershipAttribute attribute.

Today we will take a simple example where we will profile how much time the Action method took to execute.

Building your own speed-profiling Action Filter

1. Create a new ASP.NET MVC 4 Project. You can use the Internet or Intranet template

2. If a ‘Filters’ folder does not exist, create one in the project

3. Add a class to the Filters folder and call it ActionSpeedProfilerAttribute. Add the default interface implementations for IActionFilter interface from the System.Web.Mvc namespace. You also need to derive the class from FilterAttribute base class for ActionFilters and ResultsFilters

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class ActionSpeedProfilerAttribute : FilterAttribute, IActionFilter
{
     public void OnActionExecuted(ActionExecutedContext filterContext)
     {
         throw new NotImplementedException();
     }
    public void OnActionExecuting(ActionExecutingContext filterContext)
     {
         throw new NotImplementedException();
     }
}

We have added an ‘AttributeUsage’ attribute indicating where our filter can be used.

4. To time how fast our Action method executes, we will use a StopWatch from the System.Diagnostics namespace. We’ll start the timer in the OnActionExecuting method and stop the timer OnActionExecuted method. Then print the elapsed time inside a div that will be at the absolute top left corner of our page. The implementation is as follows

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class ActionSpeedProfilerAttribute : FilterAttribute, IActionFilter
{
     public void OnActionExecuted(ActionExecutedContext filterContext)
     {
         throw new NotImplementedException();
     }
    public void OnActionExecuting(ActionExecutingContext filterContext)
     {
         throw new NotImplementedException();
     }
}

We are initializing the time in OnActionExecuting. In the OnActionExecuted method, we are simply checking if the filterContext has an exception or not. If not, we are inserting a div with the time elapsed string in it to be shown on the top left corner of the page.

5. Add the attribute at class level on the HomeController.cs

[ActionSpeedProfiler]
public class HomeController : Controller
{
public ActionResult Index()
{
  …
}

}

6.    Now run the application. Once the page loads on the top left hand corner, you will see the time required to execute the ‘Index’ Action Method in the Home Controller

action-filter-first-run

7.    To verify the result is actually true, you can add a Thread.Sleep(1000) in the Index() method of HomeController and run the application again. This time the Action method will take 1+ seconds to execute because of the mandatory 1 second Thread.Sleep we introduced

action-filter-with-delay

8. You can navigate to the About and Contact pages to see how fast they load as well. Essentially any action method you add to the HomeController now will show the result div.

9. If you don’t want the result to be shown for all Action methods, you can remove it from the Class and add it to one Action method only. For example the following will only show the action method for the Index method and not the About or Contact methods

public class HomeController : Controller
{
[ActionSpeedProfiler]
public ActionResult Index()
{
   ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
    Thread.Sleep(1000);
    return View();
   }

}

10.    If we put a breakpoint in the OnActionExecuted method and watch the filterContext, we’ll see we have a host of information about the request and we can utilize all this information to return an appropriate result

action-filter-fiter-context

Conclusion

With that we conclude this introduction to ASP.NET MVC Action Filters. As you can see, they are a ‘catch-all’ type of Filters in MVC where you can write implementation to do pre or post processing of Action Method calls. One sample use we saw was creation of a simple speed profiler.

Download the entire source code of this article (Github)

This article has been editorially reviewed by Suprotim Agarwal.

Absolutely Awesome Book on C# and .NET

C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.

We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).

Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.

Click here to Explore the Table of Contents or Download Sample Chapters!

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Author
Suprotim Agarwal, MCSD, MCAD, MCDBA, MCSE, is the founder of DotNetCurry, DNC Magazine for Developers, SQLServerCurry and DevCurry. He has also authored a couple of books 51 Recipes using jQuery with ASP.NET Controls and The Absolutely Awesome jQuery CookBook.

Suprotim has received the prestigious Microsoft MVP award for Sixteen consecutive years. In a professional capacity, he is the CEO of A2Z Knowledge Visuals Pvt Ltd, a digital group that offers Digital Marketing and Branding services to businesses, both in a start-up and enterprise environment.

Get in touch with him on Twitter @suprotimagarwal or at LinkedIn



Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!
Comment posted by Nabeel on Monday, February 24, 2014 6:36 AM
I want to implement totally Custom Authentication and Authorization based on Roles and Rights on specific area of web application.

How can we achieve these using Custom Action Filters?
Comment posted by ashwini on Tuesday, May 13, 2014 8:03 AM
I have created custom helper named AntiForgeryTokenForm() which validates Antiforgerytoken.added this attribute in controller from global.asax.I want replace BeginForm()with AntiForgeryTokenForm()OnActionExecuting please help me how to do it
Comment posted by Michael Sullivan on Monday, June 2, 2014 12:39 PM
I've been trying to figure out why everyone refers to OutputCache as a result filter. It actually does all the caching and retrieval from the cache inside OnActionExecuting, and not OnResultExecuted/Executing.
Comment posted by Rick on Friday, July 4, 2014 3:55 PM
I have a basic question that I can't find an answer to online: Do the attributes execute when the action method is being unit tested?
Comment posted by Suprotim Agarwal on Monday, July 7, 2014 12:26 PM
@Rick Good question. AFAIK you'll have to use Reflection to verify an attribute.
Comment posted by Vishal Patwardhan on Thursday, November 6, 2014 3:37 AM
You could inherit the custom filter class from ActionFilterAttribute as It Implements FilterAttribute,IActionFilter,IResultFilter