啥也不说,先上代码:
public class ValidateAttribute : ActionFilterAttribute
{
private string _Name=null;
//Action执行前的过滤器
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
_Name=filterContext.HttpContext.Request.Form["name"];
......
}
}
按我们通常的理解,只要不是static标记的静态变量,每次进入的时候_Name初始值都应该为null对吧,我当初设计时候也是这样想的。
但是今天多线程下测试发现私有字段_Name第一个线程进入时,_Name被改变、第二个,第三个,第N个线程进入过滤器后,_Name初始值竟然不是Null,已经被前面的线程给改变了,那么只能找问题所在了,下面是我的推断。
推断
虽然没有看mvc过滤器的源码,但是个人推测过滤器是以单例的形式在进程中运行,即进程启动时候初始化一个单例,以后所有的线程都公用一个单例,等同于下面的代码。
public static ValidateAttributeInstance=new ValidateAttribute();
第一个线程、第二个,第N个线进入时候都是执行。
ValidateAttributeInstance.OnActionExecuting(filterContext);结论
在mvc的四种过滤器OnActionExecuting、OnActionExecuted、OnResultExecuting、OnResultExecuted中,如果有字段或属性会在OnActionExecuting方法中发生改变,那么就不能在外部定义,应该定义在内部,如下:
public class ValidateAttribute : ActionFilterAttribute
{
//Action执行前的过滤器
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
string _Name=null; //定义到内部
_Name=filterContext.HttpContext.Request.Form["name"];
......
}
}
以上是本人的踩坑经验总结,希望对大家有帮助。
如果有兴趣的朋友自己检验一下,在代码中获取当前对象并添加到集合中,最后再检测一下集合中对象是否相同,就知道是否是单例了。