如何包装所有actionfilters以进行性能监视?

时间:2011-09-12 23:32:59

标签: c# asp.net-mvc ninject

我在ASP.NET MVC网站上将越来越多的面向方面的问题转移到ActionFilters中。因此,我怀疑我的一些性能瓶颈可能已经转移到ActionFilters中,而不知道它们的性能是什么。我想挂钩到MVC的ActionFilter创建过程来包装每个ActionFilter,以便我可以记录该ActionFilter执行的时间。

到目前为止,我已经找到了以下网站链接,提示如何开始这条路,但我不确定如何实际包装每个ActionFilter。

2 个答案:

答案 0 :(得分:3)

您应该从ControllerActionInvoker派生和新类,并覆盖GetFilters方法。在此方法中,您应该创建一个诊断包装类的新实例,该实例包含封装实际过滤器的相同接口(IActionFilter)。 GetFilters作为InvokeAction方法的一部分被调用(也可以被覆盖),但GetFilters可能是最干净的。

另外你也可以尝试覆盖InvokeActionMethodWithFilters,这是实际调用动作过滤器的地方但是这可能会很麻烦,但如果你刚添加了一些东西可能会好的 像:

protected override ActionExecutedContext InvokeActionMethodWithFilters(ControllerContext controllerContext, IList<IActionFilter> filters, ActionDescriptor actionDescriptor, IDictionary<string, object> parameters)
{
    Stopwatch diagWatch = Stopwatch.StartNew();

    var context = base.InvokeActionMethodWithFilters(controllerContext, filters, actionDescriptor, parameters);

    diagWatch.Stop();

    return context;
}

要实现ControllerActionInvoker类,请参阅:

public class DiagControllerActionInvoker : ControllerActionInvoker
{
    protected override FilterInfo GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
        FilterInfo baseFilters = base.GetFilters(controllerContext, actionDescriptor);

        //Add new filters
        //e.g. baseFilters.ActionFilters.Insert(0, actionFilter);

        return baseFilters;
    }
 }

要实际指定调用自定义ControllerActionInvoker,您需要创建一个DefaultControllerFactory实现,如:

public class SiteControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if (controllerType == null)
        {
            return null;
        }

        // Create controller class. Here.
        IController controller = (IController)Activator.CreateInstance(controllerType)

        if (typeof(Controller).IsAssignableFrom(controllerType))
        {
            Controller controllerInstance = controller as Controller;

            if (controllerInstance != null)
            {
                controllerInstance.ActionInvoker = new DiagControllerActionInvoker();
            }
        }

        return controller;
    }
}

就像设置在你的应用程序代码中一样:

ControllerBuilder.Current.SetControllerFactory(new SiteControllerFactory());

答案 1 :(得分:1)

  1. 更简单的方法可能是编写集成测试来衡量每个操作过滤器或组合的性能。
  2. MVC3中有全局动作过滤器;您可能希望编写性能属性,该属性将启动和停止计时器,并为您提供运行过滤器的总时间。
  3. 如果您希望在整个生产过程中分析应用程序,可以使用DotTrace,Dynatrace等许多商业产品,这些产品可以提供每次调用的分解成本。