这个筛选器的特殊之处在于他控制的是筛选器,既不是控制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递归链。继承自身是为了控制其它筛选器。
先就这么多吧,过几天再写解决方法。