Getting more “granularity” from the MVC Mini Profiler

后端 未结 3 526
梦毁少年i
梦毁少年i 2021-02-04 10:58

Should this turn out to be useful for anyone, I\'ll gladly turn it into a community wiki thing.

I have some slow pages in an MVC3 app, and since little of the execution

相关标签:
3条回答
  • 2021-02-04 11:32

    There is already an action filter attribute in the MiniProfiler assembly that does the profiling for the actions. It is in the StackExchange.Profiling.MVCHelpers namespace and it's called ProfilingActionFilter. You can extend it to also profile your views.

    It uses the same approach as described by @Dommer but instead of storing the IDisposable directly, it stores a Stack in the HttpContext.Current.Items. You can do the same for the views.

    Here is the code for the action profiling:

    /// <summary>
    /// This filter can be applied globally to hook up automatic action profiling
    /// 
    /// </summary>
    public class ProfilingActionFilter : ActionFilterAttribute
    {
        private const string stackKey = "ProfilingActionFilterStack";
    
        /// <summary>
        /// Happens before the action starts running
        /// 
        /// </summary>
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (MiniProfiler.Current != null)
            {
                Stack<IDisposable> stack = HttpContext.Current.Items[(object) "ProfilingActionFilterStack"] as Stack<IDisposable>;
                if (stack == null)
                {
                    stack = new Stack<IDisposable>();
                    HttpContext.Current.Items[(object) "ProfilingActionFilterStack"] = (object) stack;
                }
                MiniProfiler current = MiniProfiler.Current;
                if (current != null)
                {
                    RouteValueDictionary dataTokens = filterContext.RouteData.DataTokens;
                    string str1 = !dataTokens.ContainsKey("area") || string.IsNullOrEmpty(dataTokens["area"].ToString()) ? "" : (string) dataTokens["area"] + (object) ".";
                    string str2 = Enumerable.Last<string>((IEnumerable<string>) filterContext.Controller.ToString().Split(new char[1] { '.' })) + ".";
                    string actionName = filterContext.ActionDescriptor.ActionName;
                    stack.Push(MiniProfilerExtensions.Step(current, "Controller: " + str1 + str2 + actionName, ProfileLevel.Info));
                }
            }
            base.OnActionExecuting(filterContext);
        }
    
        /// <summary>
        /// Happens after the action executes
        /// 
        /// </summary>
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            base.OnActionExecuted(filterContext);
            Stack<IDisposable> stack = HttpContext.Current.Items[(object) "ProfilingActionFilterStack"] as Stack<IDisposable>;
            if (stack == null || stack.Count <= 0) return;
            stack.Pop().Dispose();
        }
    }
    

    Hope this help.

    0 讨论(0)
  • 2021-02-04 11:48

    This looks like a cool idea. I believe that it's NOT a request safe way of doing things.

    You could link it to HttpContext.Items like this

    HttpContext.Items.Add("actionstep", actionStep);
    HttpContext.Items.Add("resultstep", resultStep);
    

    And then retrieve it in similar fashion

    actionStep = HttpContext.Items["actionstep"];
    resultStep = HttpContext.Items["resultstep"];
    

    Obviously putting in your own checks for nulls and so forth.

    The HttpContext is different for each user/request.

    The thing to remember about HttpContext.Current.Session.SessionID which I sometimes forget it that it is the SessionId of the current HTTP request (i.e. it changes each time you hit F5 or otherwise make a new request). The other important thing to remember is that, whilst at any on time, all HttpContext.Current.Session.SessionID values are necessarily unique (i.e. one for each user, or request), they can be reused, so dno't think of them as GUIDs which are only used once each.

    0 讨论(0)
  • 2021-02-04 11:53

    You can just wrap ExecuteCore method on Controller. :)

    0 讨论(0)
提交回复
热议问题