14

Iv been experimenting the great tool, Mvc MiniProfiler.

I don't want to litter all my view with lots of Step commands, so I am wanting to use the profiler with every action call. Bad idea? This is what I have tried so far:

 public abstract class BaseController : Controller
 {
        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var profiler = MiniProfiler.Current;
            using (profiler.Step("Action: "+filterContext.ActionDescriptor.ActionName))
            {
                base.OnActionExecuting(filterContext);
            }
        }
}

But I don't think this is doing what I am intending? I think I need to start the profiler on OnActionExecuting and stop it on OnResultExecuted. How do I do this, considering the profiler is designed to be used with the using statement.

Dan
  • 29,100
  • 43
  • 148
  • 207
  • 1
    If you download the source of Mini Profiler theres a base controller class in the sample project that does exactly this. – Ben Foster Jun 28 '11 at 18:36

2 Answers2

24

You could define a global action filter:

public class ProfileActionsAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var profiler = MiniProfiler.Current;
        var step = profiler.Step("Action: " + filterContext.ActionDescriptor.ActionName);
        filterContext.HttpContext.Items["step"] = step;
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var step = filterContext.HttpContext.Items["step"] as IDisposable;
        if (step != null)
        {
            step.Dispose();
        }
    }
}

and register in Global.asax:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
    filters.Add(new ProfileActionsAttribute());
}

and that's pretty much all.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Darin is there an equivalent method for MVC 2? – JK. Oct 21 '11 at 01:11
  • 1
    Hah actually I just had to add [ProfileActions] to my BaseController, that was easy. – JK. Oct 21 '11 at 01:28
  • if you want to know which **Controller and Action** executed then use `var step = profiler.Step("Controller: " + filterContext.RouteData.Values["controller"].ToString() + " Action: " + filterContext.ActionDescriptor.ActionName);` , hope helps someone. – Shaiju T Jan 18 '17 at 09:26
2

It is alright to think and use ActionFilter. But MVC is still an ASP .NET application. To start and stop MiniProfiler at beginning and ending of each request, you can try the application events in Global.asax.cs file.

// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Global.asax.cs" company="Believe2014">
//   http://believeblog.azurewebsites.net/post/miniprofiler--log4net
// </copyright>
// <summary>
//   The mvc application.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

using System;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

namespace Mvc4Application
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    /// <summary>
    ///     The mvc application.
    /// </summary>
    public class MvcApplication : HttpApplication
    {
        /// <summary>
        ///     The application_ start.
        /// </summary>
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();

            Profiler.Initialize();
        }

        /// <summary>
        /// The event when the application acquires request state.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The event argument..
        /// </param>
        protected void Application_AcquireRequestState(object sender, EventArgs e)
        {
            Profiler.Start(HttpContext.Current);
        }

        /// <summary>
        /// This function is called by ASP .NET at the end of every http request.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The event argument.
        /// </param>
        protected void Application_EndRequest(object sender, EventArgs e)
        {
            Profiler.Stop();
        }
    }
}
Believe2014
  • 3,894
  • 2
  • 26
  • 46
  • I upvoted because Application_AcquireRequestState ended up being a good place for me to check if the user's authenticated and has access to use/see the profiler, but this doesn't strictly resolve the OP's question. This times the request, not the action specifically. Minor detail, but might be important. – DaveD Sep 08 '14 at 20:01
  • There are many tools out there that could track requests processing time. But this method is particular for tracking processing time for authenticated requests. It tells the story about each user and their wait time, not just generic requests. – Believe2014 Sep 08 '14 at 20:24