.Net Core MVC中过滤器简介

原文:
.Net Core MVC中过滤器简介

在.Net Framework MVC 中有四种过滤器,授权过滤器(Authorize)、Action 过滤器、结果过滤器(Result)、异常过滤器(Exception)四种过滤器。在.Net Core MVC中,有五种过滤器,授权过滤器、Action过滤器、异常过滤器、结果过滤器、资源过滤器,新增了资源过滤器。

.Net Core MVC和.Net Framework MVC在基本使用上差别不大,主要的还是框架的差别。其中路由是个很重要的东西,参考文章:https://www.cnblogs.com/durow/p/5992926.html

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); } }

View Code

定义完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); } } } }

 

相关文章