简体   繁体   English

ASP.NET MVC3:在解析视图之前触发了OnActionExecuted

[英]ASP.NET MVC3: OnActionExecuted triggered before parsing the view

I use this action filter to log time elapsed executing every action (available here ): 我使用此动作过滤器来记录执行每个动作所花费的时间( 在此处可用):

public class LoggingFilterAttribute : ActionFilterAttribute
{
    protected static readonly log4net.ILog log = log4net.LogManager.GetLogger("PerfLog");
    private const string StopwatchKey = "DebugLoggingStopWatch";

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (log.IsDebugEnabled)
        {
            var loggingWatch = Stopwatch.StartNew();
            filterContext.HttpContext.Items.Add(StopwatchKey, loggingWatch);

            log.DebugFormat("Action started: {0}/{1}",
                filterContext.ActionDescriptor.ControllerDescriptor.ControllerName,
                filterContext.ActionDescriptor.ActionName);
        }
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (log.IsDebugEnabled)
        {
            if (filterContext.HttpContext.Items[StopwatchKey] != null)
            {
                var loggingWatch = (Stopwatch)filterContext.HttpContext.Items[StopwatchKey];
                loggingWatch.Stop();

                long timeSpent = loggingWatch.ElapsedMilliseconds;

                log.DebugFormat("Action started: {0}/{1} - Elapsed: {2}ms",
                    filterContext.ActionDescriptor.ControllerDescriptor.ControllerName,
                    filterContext.ActionDescriptor.ActionName,
                    timeSpent);

                filterContext.HttpContext.Items.Remove(StopwatchKey);
            }
        }
    }
}

It seems that OnActionExecuted is triggered before parsing the view .cshtml file. 似乎在解析视图.cshtml文件之前触发了OnActionExecuted。 More precisely I called the following action: 更准确地说,我将以下操作称为:

private IEnumerable<string> GetData()
{
    yield return "Item1";
    Thread.Sleep(2500);
    yield return "Item2";
    Thread.Sleep(2500);
    yield return "Item3";
}

public ActionResult TestPerf()
{
    var model = GetData();
    return View(model);
}

While the page is served only 5000ms after the request, the log shows: 虽然仅在请求后5000毫秒为页面提供服务,但日志显示:

2014-03-01 20:25:41,630 [12] DEBUG PerfLog - Action started: Test/TestPerf
2014-03-01 20:25:41,632 [12] DEBUG PerfLog - Action finished: Test/TestPerf - Elapsed: 2ms

I am not necessarily interested in measuring network times (eg how long the content stream takes to be sent to the client). 我不一定对测量网络时间感兴趣(例如,将内容流发送到客户端需要多长时间)。 But the problem here is that yield-lazy-evaluation might hide a slow database query, which obviously has to be taken into account by the log. 但是这里的问题是yield-lazy-evaluation可能隐藏了一个缓慢的数据库查询,显然日志必须考虑到这一点。

So, how can I get 5000ms written within the log in this case? 那么,在这种情况下,如何在日志中写入5000ms?

I think you need OnResultExecuting/ed rather than OnActionExecuting/ed . 我认为您需要OnResultExecuting/ed而不是OnActionExecuting/ed

  • OnActionExecuting executes once the action has been decided upon but before it is executed 一旦确定了动作但执行之前, OnActionExecuting执行
  • OnActionExecuted executes after the action has returned an ActionResult 在动作返回ActionResult之后执行OnActionExecuted
  • OnResultExecuting executes once there is a result (including if another filter changes the result before the action was executed, I believe), but before it has been executed against the HTTP response 一旦有结果(我相信包括其他过滤器在执行操作之前更改了结果)之后,但在针对HTTP响应执行结果之前, OnResultExecuting就会执行
  • OnResultExecuted executes after the result has been executed against the HTTP response 针对HTTP响应执行结果后执行OnResultExecuted

The actionfilterattribute indeed executes before the action. actionfilter属性确实在操作之前执行。 The times you see are from executing the filter not the request. 您看到的时间来自执行过滤器而不是请求。 If your match method would call getdata 3 times I would IDD expect 5 seconds. 如果您的match方法将调用getdata 3次,则IDD期望5秒。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM