Click here to Skip to main content
Click here to Skip to main content

Tagged as

Go to top

Performance Tip: Measure performance of ASP.NET MVC Action Filters

, 26 Sep 2013
Rate this:
Please Sign up or sign in to vote.
Measure performance of ASP.NET MVC Action Filters.

Action Filtering is one of the “hidden parts” of ASP.NET MVC. When checking page execution time, it’s common to measure controller action or view generation, but it’s often uncommon to monitor filters (as for routing). After a few performance reviews, I now think it’s really important to not forget this part.

Just to remember, MVC filters are custom attributes that you put onto action methods/controllers/globally to add common functionality, with pre- and post-processing behaviors.

How does the filter work? A good starting point is ASP.NET MVC source code and especially ControllerActionInvoker.

Using Miniprofiler

We all love great debugging tools and ASP.NET MVC MiniProfiler is one of them. However it does not come with a native way to instrument filter execution. But that’s however the tool we will use to report execution timings.

In order to evaluate performance of filters, a typical ASP.NET developer could create a new base filter attribute, and use this attribute for every filter in the target solution.

A basic implementation could be :

public void OnActionExecuted(ActionExecutedContext filterContext)
{
     using (MiniProfiler.StepStatic("Filter: " + actionFilter.GetType().Name + ".OnActionExecuted", ProfileLevel.Info))
     {
          actionFilter.OnActionExecuted(filterContext);
     }
}

Even if it’s a valid OOP approach, I don’t like to change the default base class for all of the custom filters. Obviously, this will not work for third party filters coming from my favorites Nuget packages. The problem is not in this implementation but how we plug it into ASP.NET MVC. However, I keep the code for the future.

An experienced ASP.NET MVC developer knows it is relatively easy to customize the default ControllerActionInvoker. As suggested in this post . The next step is to create an ActionInvoker that will wrap all ActionFilterAttributes with our wrapper class.

Especially, we will override the GetFilters method as follows:

protected override FilterInfo GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
     FilterInfo baseFilters = base.GetFilters(controllerContext, actionDescriptor);

     WrapFilters(baseFilters.ActionFilters);
     WrapFilters(baseFilters.ResultFilters);

     return baseFilters;
}

Prior to ASP.NET MVC 4, the only way to switch out the action invoker was to write a custom controller factory. That’s not so complicated but it’s so long and annoying…

Since ASP.NET MVC 4, you can now simply inject an IActionInvoker using the dependency resolver. To understand how IoC/DI works in ASP.NET MVC, you could read the ASP.NET tutorial here. http://www.asp.net/mvc/tutorials/hands-on-labs/aspnet-mvc-4-dependency-injection

Using Ninject.MVC Nuget package, the final code is:

/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
     kernel.Bind<IActionInvoker>().To<ProfiledActionInvoker>();
}

That’s all, we did it! Here is the result for the standard MVC 4 template and two custom global filters.

profiledglobalfilter

The complete Gist is available here.

OK, I found a problem, how to solve it ?

The code in the filter is generally easy to understand and you should use standard tools (Visual Studio Profiler). However there are two things you’ve got to be carefully taught:

  • Filters instances

Using Filter Attributes, there is only a single attribute instance per application. Use an appropriate store for your filter state (see this post from Brad Wilson).

Using FilterProviders, the filter provider will have a chance to decide whether a particular filter applies to the current request. If so, a new instance of the filter will be created each time.

  • Canceling Filter Execution

According to MSDN, You can cancel filter execution in the OnActionExecuting and OnResultExecuting methods by setting the Result property to a non-null value. I’ve seen many cases where useless filters are invoked; remember everything has a cost.

What about Glimps ?

In Glimpse, the Execution tab shows the ASP.NET MVC execution pipeline of actions, action results, and action filters (including child actions) required to respond to the HTTP request. However, I find the execution tab not clear (too much data) and I’m also less confident in Glimpse for production.

Because you have nothing to do, it’s not so funny :-)

License

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

Share

About the Author

Betclic Tech
Chief Technology Officer Betclic
France France
I am Head of Software Development at Betclic France. I manage the Paris Dev Team, consisting of 35+ talented people, in various technical and functional projects in the fields of sports betting, poker, casino or horse betting.
 
Check out our technical blog at https://techblog.betclicgroup.com
Group type: Organisation

3 members

Follow on   Twitter

Comments and Discussions

 
GeneralMy vote of 4 PinmemberRobert Hoffmann26-Sep-13 5:12 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140916.1 | Last Updated 26 Sep 2013
Article Copyright 2013 by Betclic Tech
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid