ASP.NET MVC筛选器之特殊筛选器IOverrideFilter

这个筛选器的特殊之处在于他控制的是筛选器,既不是控制Controller,也不是Action,更不是全局或者权限之类的。

IOverrideFilter 有5个继承的封闭类

分别为:OverrideActionFiltersAttribute,OverrideAuthenticationAttribute,OverrideAuthorizationAttribute,OverrideExceptionFiltersAttribute,OverrideResultFiltersAttribute他们都是继承自 Attribute, IOverrideFilter。

惊奇的发现,这些密封类既不能作为特性放在Controller和Action上,也不能作为全局筛选器添加到GlobalFilter。

经过研究发现,假如把OverrideActionFiltersAttribute作为特性放到Action 上面

   比如:
    [OverrideActionFilters]
    public ActionResult Index()
    {
        return View();
    }

这样写,丝毫不起作用,且在获取ActionAttribute的时候,直接被过滤掉了。究起原因,Get Action Attribute 的时候,他会判断是否当前Action的特性是否继承自FilterAttribute,很明显OverrideActionFiltersAttribute等五个密封类只是继承自 Attribute, IOverrideFilter。直接被过滤掉了,无论你把这个特性添加到Controller或者Action上,丝毫不起作用。

那么放在全局GlobalFilter上呢?

   比如这样写:

    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
            OverrideActionFiltersAttribute OE = new OverrideActionFiltersAttribute();
            filters.Add(OE);
        }
    }

这样写,程序运行直接报错。错误是 throw new InvalidOperationException(Properties.MvcResources.GlobalFilterCollection_UnsupportedFilterInstance);
这是什么错误?

研究发现,在GlobalFilters.Add 方法的时候,他会调用 ValidateFilterInstance(filter);

       private static void ValidateFilterInstance(object instance)
       {
            if (instance != null && !(instance is IActionFilter || instance is IAuthorizationFilter || instance is IExceptionFilter || instance is IResultFilter))
                     {
                          throw new InvalidOperationException(Properties.MvcResources.GlobalFilterCollection_UnsupportedFilterInstance);
                     }
        }

OE是传递到ValidateFilterInstance的 Instance参数,首先会判断OE是否等于NULL,然后OE必须是IActionFilter,AuthorizationFilter,IExceptionFilter,IResultFilter这四个筛选器其中之一,很明显上面说了OverrideActionFiltersAttribute等五大密封类并没有实现这些筛选器,他只是继承了 Attribute, IOverrideFilter。

那么问题很明显了,程序直接跳到 throw new InvalidOperationException 报错了。

既然全局GlobalFilter 和特性并不能让IOverrideFilter起作用,那么筛选器提供组件有三个,还有一个是ControllerInstanceFilterProvider可不可以呢?

        public class ControllerInstanceFilterProvider : IFilterProvider
        {
            public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
           {
                if (controllerContext.Controller != null)
                {
                // Use FilterScope.First and Order of Int32.MinValue to ensure controller instance methods always run first
                   yield return new Filter(controllerContext.Controller, FilterScope.First, Int32.MinValue);
               }
          }
        }

很可惜啊,这个所谓ControllerInstanceFilterProvider并没有提供添加筛选器组件的接口或者类。

那么IOverrideFilter该怎么实现呢?

上面用OverrideActionFiltersAttribute做了两个例子,一个是全局,一个是特性,都不行,都会出现问题,解决第一个问题,可以让实现的 IOverrideFilter继承自FilterAttribute接口。

    public abstract class OverrideAttribute:FilterAttribute,IOverrideFilter
    {
        public Type FiltersToOverride
        {
            get { return typeof(IActionFilter); }
        }
    }


    public class Over : OverrideAttribute { }

首先写一个类OverrideAttribute,让他继承自FilterAttribute,IOverrideFilter,继承自FilterAttribute是为了解决上面出现的第一个问题,继承自IOverrideFilter是我们要实现的筛选器控制筛选器。

然后在Index Action上面应用拥有IOverrideFilter特性的Over
[Over]
public ActionResult Index()
{
return View();
}
这样,在Index 前面的所有筛选器,比如Controller的筛选器,Global的筛选器,全部无效。

定义两个Action筛选器

     public abstract class FilterBaseAttribute:FilterAttribute,IActionFilter
     {
        public void OnActionExecuted(ActionExecutedContext filterContext)
        { }


        public void OnActionExecuting(ActionExecutingContext filterContext)
        { }
     }
    public class FooAttribute : FilterBaseAttribute { }         
    public class BarAttribute : FilterBaseAttribute { }

在Index Action上面同时应用Action和OverrideFilter筛选器,在Controller上应用一个Action筛选器

   [Foo]
   public class HomeController : Controller
   {
     [Over]   
     [Bar]
     [OverrideActionFilters]
     public ActionResult Index()
     {
        return View();
     }
  }

执行之后,你会发现,在Controller上面的Foo并没有被执行,而是被Over特性给过滤掉了,而Index Action上的Bar特性则被执行了。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

第二个问题怎么解决呢?

可以让 OverriderFilter筛选器同时继承自 IActionFilter和FilterAttribute以及他自身IOverrideFilter ,继承Action是为了执行目的,继承FilterAttribute是为了在全局添加的时候避开异常,达到Action递归链。继承自身是为了控制其它筛选器。

先就这么多吧,过几天再写解决方法。

猜你喜欢

转载自blog.csdn.net/tangyanzhi1111/article/details/78632754