2011-03-19 98 views
2

我只注意到MVC3中ActionFilterAttribute优先级的一个奇怪行为。事实证明,如果Controller和Action均使用AllowMultiple = false(缺省值)的相同ActionFilterAttribute进行修饰,则将选择具有较高Order值的ActionFilterAttribute。如果是平局(即两个Order值相同),则选择Action上的过滤器。我一直认为Action中的筛选器总是被选中(如果存在的话),无论Order值如何。实例:ASP.NET MVC3 ActionFilterAttribute优先级/选择 - 奇怪?

行动过滤器选择:上控制器

[MyActionFilter(Name = "Controller")] // same as Order = -1 
public class HomeController : Controller { 

    [MyActionFilter(Name = "Action")] // same as Order = -1 
    public ActionResult Index() { 
     return Content("Hello"); 
    } 

} 

过滤器选择:

[MyActionFilter(Name = "Controller", Order = 1)] 
    public class HomeController : Controller { 

     [MyActionFilter(Name = "Action")] // same as Order = -1 
     public ActionResult Index() { 
      return Content("Hello"); 
     } 

    } 

行动过滤器选择:

[MyActionFilter(Name = "Controller", Order = 1)] 
public class HomeController : Controller { 

    [MyActionFilter(Name = "Action", Order = 1)] 
    public ActionResult Index() { 
     return Content("Hello"); 
    } 

} 

控制器上的过滤器选择:

[MyActionFilter(Name = "Controller", Order = 20)] 
public class HomeController : Controller { 

    [MyActionFilter(Name = "Action", Order = 1)] 
    public ActionResult Index() { 
     return Content("Hello"); 
    } 

} 

这是一个错误或设计?自从版本1开始,我一直在使用MVC,并从未注意到这个过滤器选择优先级。它一直是这样吗?

感谢

回答

3

如果设置AllowMultiple = false并有控制器和动作控制器上的一个是从未执行都在同一个行为过滤器。如果您设置了AllowMultiple=true,则它是控制器上的过滤器,它会先假定相同的顺序执行。

,在ASP.NET MVC 3改变的事情是:

在ASP.NET MVC的早期版本中, 行动过滤器,每个请求 创建除了在少数情况下。此行为 从来没有保证的行为,但 只是一个实现细节和 过滤器的合同是 认为它们是无状态的。在ASP.NETMVC 3中,积极地缓存更多的过滤器。因此,任何不正确地存储 实例状态的自定义 操作筛选器可能会中断。

因此,要确保你正确测试此:

[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] 
public class MyActionFilterAttribute : ActionFilterAttribute 
{ 
    public string Name { get; set; } 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
Put a breakpoint here and inspect the value of the Name property ====> 
     var name = Name; 
     base.OnActionExecuting(filterContext); 
    } 
} 
+1

感谢达林,但我看到不同的结果比你说出什么。我正在设置AllowMultiple = false。如果在控制器的属性上,我设置了Order = 1,并且在具有相同属性的操作上,我没有设置Order,那么控制器上的属性被执行。我通过在属性的OnActionExecuting覆盖中执行System.Diagnostics.Debug.WriteLine(Name)来检查它。你可以试试在Controller的属性上使用更高的Order值来运行你的例子,并确认Controller上的属性确实从未运行过?谢谢。 – 2011-03-19 16:44:55