ASP.NET MVC 中的过滤器
这里用实例说明各种过滤器的用法,有不对的地方还请大神指出,共同探讨。
1. actionfilter 方法过滤器:
接口名为 iactionfilter ,在控制器方法调用前/后执行。
在新建的mvc程序中,添加一个类 myfilter1attribute 并继承actionfilterattribute抽象类
从上图可以看到 actionfilterattribute 中的所有方法,且有相应的介绍,我们可以通过继承 actionfilterattribute 类,并重写(override)它的方法,从而实现自定义filter
public class myfilter1attribute: actionfilterattribute { /// <summary> /// 该方法会在action方法执行之前调用 /// </summary> /// <param name="filtercontext"></param> public override void onactionexecuting(actionexecutingcontext filtercontext) { filtercontext.httpcontext.response.write("我是onactionexecuting,我在ation方法调用前执行<br/>"); base.onactionexecuting(filtercontext); } /// <summary> /// 该方法会在action方法执行之后调用 /// </summary> /// <param name="filtercontext"></param> public override void onactionexecuted(actionexecutedcontext filtercontext) { filtercontext.httpcontext.response.write("我是onactionexecuted,我在action方法调用后执行<br/>"); base.onactionexecuted(filtercontext); } }
然后创建一个homecontroller控制器,并添加filtertest的测试action
public class homecontroller : controller { public actionresult index() { return view(); } [myfilter1] public void filtertest() { response.write("我是action方法,我在这里执行了.....<br/>"); } }
运行程序并访问filtertest方法:
上图可看出它的一个执行顺序
但是有时候也有可能有这样的场景:当检查到action有标识某个attribute的时候,我们需要跳出,并不执行后续的方法的情况,我们可以通过filtercontext中actiondescriptior类中的isdefained方法进行判断检查
/// <summary> /// 该方法会在action方法执行之前调用 /// </summary> /// <param name="filtercontext"></param> public override void onactionexecuting(actionexecutingcontext filtercontext) { filtercontext.httpcontext.response.write("我是onactionexecuting,我在ation方法调用前执行<br/>"); //判断action方法时是否有贴上myfilter1attribute标签 if (filtercontext.actiondescriptor.isdefined(typeof(myfilter1attribute), false)) { //如果有,为该action方法直接返回contentresult,则该action方法在这里就有了返回值,相当于在这里就结束了,不会再去执行之后的方法,例如:onactionexecuted filtercontext.result = new contentresult(); } base.onactionexecuting(filtercontext); }
2.resultfilter 结果过滤器:
接口名为 iresultfilter,在控制器方法调用完,跳转至view页面前/后调用
同样在 myfilter1attribute 类中重写 onresultexecuting 方法和 onresultexecuted 方法
/// <summary> /// 该方法在action方法返回结果之前执行 /// </summary> /// <param name="filtercontext"></param> public override void onresultexecuting(resultexecutingcontext filtercontext) { filtercontext.httpcontext.response.write("我是onresultexecuting,我在action方法返回结果前执行<br/>"); base.onresultexecuting(filtercontext); } /// <summary> /// 该方法在action方法返回结果之后执行 /// </summary> /// <param name="filtercontext"></param> public override void onresultexecuted(resultexecutedcontext filtercontext) { filtercontext.httpcontext.response.write("我是onresultexecuted,我在action方法返回结果后执行<br/>"); base.onresultexecuted(filtercontext); }
然后在homecontroller控制器中添加 filtertest1
[myfilter1] public actionresult filtertest1() { response.write("我是测试action1方法,我在这里执行了.....<br/>"); return view(); }
运行程序,并访问 filtertest1 ,执行结果如下:
可以看出onresultexecuting 方法是在返回结果页面之前执行的,而onresultexecuted是返回结果页面之后执行的
3.exceptionfilter 异常操作过滤器:
接口名为 iexceptionfilter,在控制器的action方法抛出异常时执行
可以通过异常过滤器捕获controller中发生的异常,并记录到日志。
添加myexceptionattribute类,并继承handleerrorattribute,如下:
/// <summary> /// /// </summary> /// <param name="filtercontext"></param> public override void onexception(exceptioncontext filtercontext) { filtercontext.httpcontext.response.write("我是onexception,在controller中发生异常时进入<br/>"); //获取到异常对象 exception ex = filtercontext.exception; //获取请求的controller和action string controllername = filtercontext.routedata.values["controller"].tostring(); string actionname = filtercontext.routedata.values["action"].tostring(); //记录日志 string errmessage = string.format("异常消息:控制器为:{0},action为:{1},异常信息为:{2};", controllername, actionname, ex.message); outputlog(errmessage); //标记异常已做处理 filtercontext.exceptionhandled = true; base.onexception(filtercontext); } /// <summary> /// 输出日志 /// </summary> /// <param name="message"></param> public void outputlog(string message) { string path = appdomain.currentdomain.basedirectory + "/logs.txt"; using (streamwriter sw = new streamwriter(path, true, encoding.default)) { sw.flush(); sw.writeline("时间:" + datetime.now); sw.writeline("内容:" + message); sw.writeline("---------------------------------------------"); } }
在homecontroller中添加filtertest3
[myexception] public actionresult filtertest3() { response.write("我是测试action3方法,我在这里执行了.....<br/>"); string str = "131464ddddd"; int i = int.parse(str); return view(); }
运行程序并访问 filtertest3方法,将会在 str 转换成int类型时抛出异常,随后将进入onexception方法,并记录日志如下:
4.authorizationfilter 授权过滤器:
接口名为 iauthorizationfilter,在所有过滤器中最先执行
添加一个myfilter2attribute类,并继承authorizeattribute类,然后重写其onauthorization方法:
public class myfilter2attribute: authorizeattribute { /// <summary> /// 在所有的action方法过滤之前执行 /// </summary> /// <param name="filtercontext"></param> public override void onauthorization(authorizationcontext filtercontext) { filtercontext.httpcontext.response.write("我是onauthorization,在所有action方法过滤器之前执行<br/>");//base.onauthorization(filtercontext); } }
在honecontroller控制器中添加 filtertest2
[myfilter1] [myfilter2] public actionresult filtertest2() { response.write("我是测试action2方法,我在这里执行了.....<br/>"); return view(); }
运行程序并访问 filtertest2 结果如下:
从上图执行结果可以看出,onauthorization 权重是最高的,将会在其他所有过滤器之前执行。
注意:
actionfilter 和 resultfilter 不仅可以对单个方法进行操作,也能对整个controller进行操作,将过滤的头部属性移至控制名称上面即可。