ASP.NET MVC3 ActionFilterAttribute优先级/选择 - 奇怪?

时间:2011-03-19 07:09:21

标签: asp.net-mvc asp.net-mvc-3 actionfilterattribute

我刚刚注意到MVC3中ActionFilterAttribute优先级的一个奇怪行为。事实证明,如果Controller和Action都使用具有AllowMultiple = false(默认值)的相同ActionFilterAttribute进行修饰,则会选择具有HIGHER Order值的Controller。在平局的情况下(即两个Order值相同),则选择Action上的过滤器。我一直认为Action的过滤器总是被选中(如果有的话),无论Order值如何。例子:

选择过滤操作:

[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,从未注意到这个过滤器选择优先级。它总是这样吗?

由于

1 个答案:

答案 0 :(得分:3)

如果设置AllowMultiple = false并且在控制器和操作上都有相同的操作过滤器,则控制器上的操作过滤器从不执行。如果设置AllowMultiple=true,则控制器上的过滤器首先执行相同的顺序。

ASP.NET MVC 3中发生的变化如下:

  

在以前的ASP.NET MVC版本中,   每个请求都会创建操作过滤器   除了少数情况。这种行为   从来都不是保证行为但是   仅仅是一个实现细节和   过滤器的合同是   认为他们是无国籍的。在ASP.NET中   MVC 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);
    }
}