Bon*_*arp 4 c# asp.net asp.net-mvc action-filter
我目前正在使用动作过滤器我认为是一个线程问题,在我的应用程序上我使用ActionFilter来执行每个动作的跟踪,此跟踪将提供统计信息,例如调用的持续时间,并记录参数被送到行动.
实际的跟踪实现(由其他团队完成)与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();
}
}
Run Code Online (Sandbox Code Playgroud)
异常并没有告诉我太多,基本上它是试图处理元素而其他人仍处于活动状态,我仍然需要查看跟踪代码...但我发现这篇文章说明如下:
在以前版本的ASP.NET MVC中,除少数情况外,每个请求都创建了操作过滤器.这种行为从来都不是保证行为,而只是一个实现细节,而过滤器的合同是将它们视为无状态.在ASP.NET MVC 3中,过滤器被更积极地缓存.因此,任何不正确地存储实例状态的自定义操作过滤器都可能被破坏.
对我来说这看起来非常奇怪,因为动作过滤器应该是对等请求,这就是我们在其上放置公共属性,并为特定动作配置其行为的原因,不是吗?
我很感激任何帮助,问候.
一种可能的解决方法是将对象实例存储在类中,HttpContext.Items而不是存储在ActionFilter类中的私有变量中.
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();
}
}
Run Code Online (Sandbox Code Playgroud)