APS.NETMVC中(以下简称“MVC”)的每一个请求,都会分配给相应的控制器和对应的行为方法去处理,而在这些处理的前前后后如果想再加一些额外的逻辑处理。这时候就用到了过滤器。
过滤器类型
接口
描述
Authorization
IAuthorizationFilter
此类型(或过滤器)用于限制进入控制器或控制器的某个行为方法
Exception
IExceptionFilter
用于指定一个行为,这个被指定的行为处理某个行为方法或某个控制器里面抛出的异常
Action
IActionFilter
用于进入行为之前或之后的处理
Result
IResultFilter
用于返回结果的之前或之后的处理
过滤器
类名
实现接口
ActionFilter
AuthorizeAttribute
HandleError
HandleErrorAttribute
自定义
ActionFilterAttribute
IActionFilter和IResultFilter
用于进入行为之前或之后的处理或返回结果的之前或之后的处理
下面介绍的过滤器中,除了上面这几种外,还多加一种过滤器OutputCache
1.1默认Authorize使用
[MyAuthorize]publicActionResultShowDetail(){returnView();}每当偶数分钟的时候就可以访问得到这个ShowDetail的视图,否则就会跳到了登陆页面了。
2处理错误过滤器HandleError
2.1默认HandleError使用
在往常的开发中,想到异常处理的马上就会想到try/catch/finally语句块。在MVC里面,万一在行为方法里面抛出了什么异常的,而那个行为方法或者控制器有用上HandleError过滤器的,异常的信息都会在某一个视图显示出来,这个显示异常信息的视图默认是在Views/Shared/Error
这个HandleError的属性如下
属性名称
类型
ExceptionType
Type
要处理的异常的类型,相当于Try/Catch语句块里Catch捕捉的类型,如果这里不填的话则表明处理所有异常
View
String
指定需要展示异常信息的视图,只需要视图名称就可以了,这个视图文件要放在Views/Shared文件夹里面
Master
指定要使用的母版视图的名称
Order
Int
指定过滤器被应用的顺序,默认是-1,而且优先级最高的是-1
这个Order属性其实不只这个HandleError过滤器有,其优先级规则跟其他过滤器的都是一样。
下面则故意弄一个会抛异常的行为方法
[HandleError(ExceptionType=typeof(Exception))]publicActionResultThrowErrorLogin(){thrownewException("thisisThrowErrorLoginActionThrow");}
光是这样还不够,还要到web.config文件中的
因为默认的开发模式中它是关闭的,要等到部署到服务器上面才会开启,让异常信息比较友好的用一个视图展现。
像这里访问ThrowErrorLogin视图时,由于抛出了一次,就转到了一个特定的视图
在这里看到的异常视图是这样的,除了用这个建项目时默认生成的异常视图之外,我们还可以自己定义异常视图,视图里面要用到的异常信息,可以通过@Model获取,它是一个ExceptionInfo类型的实例,例如这里建了一个异常视图如下
它存放的路径是~/Views/Shared里面,像上面的行为方法如果要用异常信息渲染到这个视图上面,在控制器的处改成这样就可以了
[HandleError(ExceptionType=typeof(Exception),View="MyErrorPage")]
2.2自定义错误异常处理
这里的错误处理过滤器也可以自己来定义,做法是继承HandleErrorAttribute类,重写voidOnException(ExceptionContextfilterContext)方法,这个方法调用是为了处理未处理的异常,例如
这里的ExceptionHandler属性要提一下的是,如果这个异常处理完的话,就把它设为true,那么即使有其他的错误处理器捕获到这个异常,也可以通过ExceptionHandler属性判断这个异常是否经过了处理,以免重复处理一个异常错误而引发新的问题。
3OutputCache过滤器
Duration
int
VaryByParam
string
以哪个字段为标识来缓存数据,比如当“ID”字段变化时,需要改变缓存(仍可保留原来的缓存),那么应该设VaryByParam为"ID"。这里你可以设置以下几个值:*=任何参数变化时,都改变缓存。none=不改变缓存。以分号“;”为间隔的字段名列表=列表中的字段发生变化,则改变缓存。
Location
OutputCacheLocation
缓存数据放在何处。默认是Any,其他值分别是Client,Downstream,Server,None,ServerAndClient
NoStore
bool
用于决定是否阻止敏感信息的二级存储。
例如一个OutputCache过滤器可以这样使用
[OutputCache(Location=System.Web.UI.OutputCacheLocation.Client,Duration=60)]publicActionResultLogin(){returnView();}
或者有另外一种使用方式——使用配置文件,在
[OutputCache(CacheProfile="testCache")]publicActionResultLogin(){returnView();}4自定义过滤器
万一前面介绍的过滤器也满足不了需求,要在行为方法执行返回的前前后后定义自己的处理逻辑的话,这个自定义过滤器就应该能派上用场了。若要自定义一个过滤器,则要继承ActionFilterAttribute类,这个类是一个抽象类,实现了IActionFilter和IResultFilter接口,主要通过重写四个虚方法来达到在行为方法执行和返回的前后注入逻辑
方法
参数
OnActionExecuting
ActionExecutingContext
在行为方法执行前执行
OnActionExecuted
ActionExecutedContext
在行为方法执行后执行
OnResultExecuting
ResultExecutingContext
在行为方法返回前执行
OnResultExecuted
ResultExecutedContext
在行为方法返回后执行
四个方法执行顺序是OnActionExecuting——>OnActionExecuted——>OnResultExecuting——>OnResultExecuted。上面四个方法的参数都是继承基ContollorContext类。例如下面定义了一个自定义的过滤器
使用它的行为方法定义如下
[MyCustomerFilter]publicActionResultCustomerFilterTest(){Response.Write("
InvkingCustomerFilterTestAction");returnView();}
执行结果如下
这个就证明了上面说的顺序。
当控制器也使用上这过滤器时,而行为方法不使用时,结果如下
如果控制器和行为方法都使用了过滤器,理论上是显示上面两个结果的有机结合。但实际不然,因为在定义过滤器的时候还少了一个特性:[AttributeUsage(AttributeTargets.All,AllowMultiple=true)],把这个加在MyCustomerFilterAttribute就行了。
[AttributeUsage(AttributeTargets.All,AllowMultiple=true)]//多次调用publicclassMyCustomerFilterAttribute:ActionFilterAttribute{……}
由这幅图可以看出,同一个过滤器分别用在了控制器和行为方法中,执行同一个方法时都会有先后顺序,如果按默认值(不设Order的情况下),一般的顺序是由最外层到最里层,就是“全局”——>“控制器”——>“行为方法”;而特别的就是错误处理的过滤器,由于异常是由里往外抛的,所以它的顺序刚好也反过来:“行为方法”——>“控制器”——>“全局”。
既然这里有提到全局的过滤器,那么全局的过滤器是在Global.asax文件里面的RegisterGlobalFilters(GlobalFilterCollectionfilters)中设置的
publicstaticvoidRegisterGlobalFilters(GlobalFilterCollectionfilters){filters.Add(newHandleErrorAttribute());filters.Add(newMyFilters.MyCustomerFilterAttribute(){Message="Global"});//全局过滤器}
这里它默认也添加了一个错误处理的过滤器来处理整个MVC应用程序所抛出的异常。