.Net Core MVC中过滤器简介
在.net framework mvc 中有四种过滤器,授权过滤器(authorize)、action 过滤器、结果过滤器(result)、异常过滤器(exception)四种过滤器。在.net core mvc中,有五种过滤器,授权过滤器、action过滤器、异常过滤器、结果过滤器、资源过滤器,新增了资源过滤器。
.net core mvc和.net framework mvc在基本使用上差别不大,主要的还是框架的差别。其中路由是个很重要的东西,参考文章:
action过滤器、结果过滤器、exception,三个特性,没有什么变化。在exceptionfilter多了个order参数,就是用来排序的。
结果过滤器,包装了单个action result的执行,当且晋档action方法成功执行完毕后才运行。它们是理想的围绕视图执行或格式处理的逻辑(所在之处)。继承attribute,iresultfilter
/// <summary> /// result的filter /// </summary> public class customresultfilterattribute : attribute, iresultfilter { //private logger logger = logger.createlogger(typeof(customresultfilterattribute)); public void onresultexecuted(resultexecutedcontext context) { console.writeline("onresultexecuted executed!"); //logger.info("onresultexecuted executed!"); } public void onresultexecuting(resultexecutingcontext context) { console.writeline("onresultexecuting executing!"); //logger.info("onresultexecuting executing!"); } }
异常过滤器,为mvc隐藏程序为处理异常应用全局策略。继承exceptionfilterattribute
/// <summary> /// 异常处理的filter /// </summary> public class customexceptionfilterattribute : exceptionfilterattribute { private readonly ihostingenvironment _hostingenvironment; private readonly imodelmetadataprovider _modelmetadataprovider; //private logger logger = logger.createlogger(typeof(customexceptionfilterattribute)); /// <summary> /// ioc来的 /// </summary> /// <param name="hostingenvironment"></param> /// <param name="modelmetadataprovider"></param> public customexceptionfilterattribute( ihostingenvironment hostingenvironment, imodelmetadataprovider modelmetadataprovider) { _hostingenvironment = hostingenvironment; _modelmetadataprovider = modelmetadataprovider; } /// <summary> /// 没有处理的异常,就会进来 /// </summary> /// <param name="filtercontext"></param> public override void onexception(exceptioncontext filtercontext) { if (!filtercontext.exceptionhandled)//异常有没有被处理过 { string controllername = (string)filtercontext.routedata.values["controller"]; string actionname = (string)filtercontext.routedata.values["action"]; string msgtemplate = "在执行 controller[{0}] 的 action[{1}] 时产生异常"; //logger.error(string.format(msgtemplate, controllername, actionname), filtercontext.exception); if (this.isajaxrequest(filtercontext.httpcontext.request))//检查请求头 { filtercontext.result = new jsonresult( new { result = false, promptmsg = "系统出现异常,请联系管理员", debugmessage = filtercontext.exception.message }//这个就是返回的结果 ); } else { var result = new viewresult { viewname = "~/views/shared/error.cshtml" }; result.viewdata = new viewdatadictionary(_modelmetadataprovider, filtercontext.modelstate); result.viewdata.add("exception", filtercontext.exception); filtercontext.result = result; } filtercontext.exceptionhandled = true; } } private bool isajaxrequest(httprequest request) { string header = request.headers["x-requested-with"]; return "xmlhttprequest".equals(header); } }
定义完exceptionfilter,该怎么注册到全局呢?在stratup.cs中configureserver中,进行注册
services.addmvc(o => { o.filters.add(typeof(customexceptionfilterattribute));// 这里就是全局注册filter }).setcompatibilityversion(compatibilityversion.version_2_2);
action 过滤器,包装了对单个action方法的调用,可以将参数传递给action并从中获得action result。继承iactionfilter
/// <summary> /// action的filter` /// </summary> public class customactionfilterattribute : attribute, iactionfilter { private ilogger<customactionfilterattribute> _logger = null; public customactionfilterattribute(ilogger<customactionfilterattribute> logger) { this._logger = logger; } public void onactionexecuted(actionexecutedcontext context) { //context.httpcontext.response.writeasync("actionfilter executed!"); console.writeline("actionfilter executed!"); //this._logger.logdebug("actionfilter executed!"); } public void onactionexecuting(actionexecutingcontext context) { //context.httpcontext.response.writeasync("actionfilter executing!"); console.writeline("actionfilter executing!"); //this._logger.logdebug("actionfilter executing!"); } }
在startup.cs中configureservices进行注册
//允许使用servicefilter 标记特性 services.addscoped<customactionfilterattribute>();
标记到controller的actionfilter
/// <summary> /// 标记到controller /// </summary> public class customcontrolleractionfilterattribute : attribute, iactionfilter { private ilogger<customcontrolleractionfilterattribute> _logger = null; public customcontrolleractionfilterattribute(ilogger<customcontrolleractionfilterattribute> logger) { this._logger = logger; } public void onactionexecuted(actionexecutedcontext context) { //context.httpcontext.response.writeasync("actionfilter executed!"); console.writeline("actionfilter executed!"); //this._logger.logdebug("actionfilter executed!"); } public void onactionexecuting(actionexecutingcontext context) { //context.httpcontext.response.writeasync("actionfilter executing!"); console.writeline("actionfilter executing!"); //this._logger.logdebug("actionfilter executing!"); } }
[typefilter(typeof(customcontrolleractionfilterattribute),order =-1)] public class thirdcontroller : controller { }
注册到全局的actionfilter
public class customglobalactionfilterattribute : attribute, iactionfilter { private ilogger<customglobalactionfilterattribute> _logger = null; public customglobalactionfilterattribute(ilogger<customglobalactionfilterattribute> logger) { this._logger = logger; } public void onactionexecuted(actionexecutedcontext context) { //context.httpcontext.response.writeasync("actionfilter executed!"); console.writeline("actionfilter executed!"); //this._logger.logdebug("actionfilter executed!"); } public void onactionexecuting(actionexecutingcontext context) { //context.httpcontext.response.writeasync("actionfilter executing!"); console.writeline("actionfilter executing!"); //this._logger.logdebug("actionfilter executing!"); } }
还是要在startup中进行全局的注册
services.addmvc(o => { o.filters.add(typeof(customglobalactionfilterattribute));// 这里就是全局注册filter }).setcompatibilityversion(compatibilityversion.version_2_2);
分别对全局、控制器、action注册了actionfilter默认执行顺序:
全局onactionexecuting===》控制器的onactionexecuting====》action的onactionexecuting====》执行action ====》action的onactionexecuted====》控制器的onactionexecuted====》全局的onactionexecuted。类似于一个俄罗斯套娃,也可以说是一个洋葱模型。
资源过滤器,是授权之后第一个用来处理请求的过滤器,也是最后一个接触到请求的过滤器(因为之后就会离开过滤器管道)。在性能方面,资源过滤器在实现缓存或短路过滤器管道尤其有用。继承iresourcefilter
/// <summary> /// 自定义的资源filter /// </summary> public class customresourcefilterattribute : attribute, iresourcefilter { private static readonly dictionary<string, object> _cache = new dictionary<string, object>(); private string _cachekey; /// <summary> /// 控制器实例化之前 /// </summary> /// <param name="context"></param> public void onresourceexecuting(resourceexecutingcontext context) { _cachekey = context.httpcontext.request.path.tostring(); if (_cache.containskey(_cachekey)) { var cachedvalue = _cache[_cachekey] as viewresult; if (cachedvalue != null) { context.result = cachedvalue; } } } /// <summary> /// 把请求都处理完的 /// </summary> /// <param name="context"></param> public void onresourceexecuted(resourceexecutedcontext context) { if (!string.isnullorempty(_cachekey) && !_cache.containskey(_cachekey)) { var result = context.result as viewresult; if (result != null) { _cache.add(_cachekey, result); } } } }
推荐阅读
-
详解ASP.NET MVC 常用扩展点:过滤器、模型绑定
-
灵活掌握Asp.net MVC中GridView的使用方法
-
asp.net core mvc实现伪静态功能
-
asp.net core3.0 mvc 用 autofac
-
ASP.NET Core MVC/WebApi基础系列1
-
ASP.NET Core 2.2中的Endpoint路由详解
-
详解.NET Core 3.0中的新变化
-
ASP.NET Core中自定义路由约束的实现
-
详解ASP.Net Core 中如何借助CSRedis实现一个安全高效的分布式锁
-
浅谈.net core 注入中的三种模式:Singleton、Scoped 和 Transient