c# - MVC Action 过滤器和多线程

标签 c# asp.net asp.net-mvc action-filter

我目前认为是 Action 过滤器的线程问题,在我的应用程序上我使用 ActionFilter 来执行每个 Action 的跟踪,此跟踪将提供统计信息,例如调用的持续时间以及记录发送到操作的参数。

实际的跟踪实现(由其他团队完成)使用 IDisposable 对象,基本上在创建实例时初始化开始时间,在处理对象时设置结束日期,这两个调用都会在自定义日志中创建一个条目,代码如下(为简单起见删除了一些代码):

    public class TraceActionAttribute : ActionFilterAttribute
{
    private IDisposable logManagerBeginTrace;

    /// <summary>
    /// Called by the ASP.NET MVC framework before the action method executes.
    /// </summary>
    /// <param name="filterContext">The filter context.</param>
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        base.OnActionExecuting(filterContext);
        List<object> parameters = new List<object>();

        string actionName = filterContext.ActionDescriptor.ActionName;
        Type controllerType = filterContext.Controller.GetType();
        foreach (KeyValuePair<string, object> currentParameter in filterContext.ActionParameters)
        {
            parameters.Add(currentParameter.Value);
        }

        this.logManagerBeginTrace = LogManager.BeginMethodTrace(ApplicationConstants.ApplicationName, controllerType, actionName, Guid.NewGuid(), parameters.ToArray());
    }

    /// <summary>
    /// Called by the ASP.NET MVC framework after the action method executes.
    /// </summary>
    /// <param name="filterContext">The filter context.</param>
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        base.OnActionExecuted(filterContext);
        this.logManagerBeginTrace.Dispose();
    }
}

异常并没有告诉我太多,基本上它试图在其他元素仍处于事件状态时处理元素,我仍然需要查看跟踪代码...但我发现了 this post上面写着:

In previous versions of ASP.NET MVC, action filters were created per request except in a few cases. This behavior was never a guaranteed behavior but merely an implementation detail and the contract for filters was to consider them stateless. In ASP.NET MVC 3, filters are cached more aggressively. Therefore, any custom action filters which improperly store instance state might be broken.

这对我来说很奇怪,因为操作过滤器应该是对等请求,这就是我们在其上放置公共(public)属性并为特定操作配置其行为的原因,不是吗?

我很感激任何帮助,问候。

最佳答案

一个可能的解决方法是将对象实例存储在 HttpContext.Items 中,而不是在 ActionFilter 类的私有(private)变量中。

HttpContext.Items 是一种按请求存储机制,这听起来正是您所需要的。

修改后的代码大致如下所示:

 public class TraceActionAttribute : ActionFilterAttribute
{
    private IDisposable logManagerBeginTrace;

    /// <summary>
    /// Called by the ASP.NET MVC framework before the action method executes.
    /// </summary>
    /// <param name="filterContext">The filter context.</param>
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        base.OnActionExecuting(filterContext);
        List<object> parameters = new List<object>();

        string actionName = filterContext.ActionDescriptor.ActionName;
        Type controllerType = filterContext.Controller.GetType();
        foreach (KeyValuePair<string, object> currentParameter in filterContext.ActionParameters)
        {
            parameters.Add(currentParameter.Value);
        }

        filterContext.HttpContext.Items["TraceActionKey"] = LogManager.BeginMethodTrace(ApplicationConstants.ApplicationName, controllerType, actionName, Guid.NewGuid(), parameters.ToArray());
    }

    /// <summary>
    /// Called by the ASP.NET MVC framework after the action method executes.
    /// </summary>
    /// <param name="filterContext">The filter context.</param>
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        base.OnActionExecuted(filterContext);
        ((IDisposable)filterContext.HttpContext.Items["TraceActionKey"]).Dispose();
    }
}

关于c# - MVC Action 过滤器和多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8675103/

相关文章:

c# - ASP.NET 如何在请求中获取自定义 header ?

jquery - Ajax 分页 - 启用后退按钮

c# - ASP.NET MVC 3 中的更新面板

c# - 作为参数类型,T[] 不比 IEnumerable<T> 好吗? (考虑线程挑战)

c# - ASP.NET 中 C# 的人脸检测

c# - 这个天真的递归斐波那契实现如何不是stackoverflow?

asp.net - ASP.NET 表单中的 Paypal 表单

asp.net-mvc - 在查询字符串中使用 GUID 以确保安全

c# - 要使用多少线程?

c# - 使用 Thread.Sleep() 实现心跳