ASP.NET Core MVC 之过滤器(Filter)

  ASP.NET MVC 中的过滤器允许在执行管道中的特定阶段之前或之后运行代码。可以对全局,也可以对每个控制器或每个操作配置过滤器。

1.过滤器如何工作

  不同的过滤器类型在管道中的不同阶段执行,因此具有各自的与其场景。根据需要执行的任务以及需要执行的请求管道中的位置,选择要创建的过滤器类型。过滤器在 MVC 操作调用管道中运行,有时也称为过滤管道,在 MVC 中选择要执行的操作后,执行操作上的过滤器,如图:

  不同的过滤器在管道内的不同位置执行。像授权过滤器这样的过滤器只在管道中靠前的位置执行。其他过滤器,如操作(Action)过滤器,可以在管道执行的其他部分之前和之后执行,如图:

  

  1.选择过滤器

  授权过滤器用于确定当前请求用户是否被授权。

  资源过滤器是在授权之后第一个处理请求的过滤器,也是最后一个在请求离开过滤管道时接触请求的过滤器。在性能方面,对实现缓存或者对过滤管道进行短路 特别有用。

  操作过滤器包装对单个操作方法的调用,并且可以处理传递到操作的参数以及从操作返回的操作结果。

  异常过滤器用于对 MVC 应用程序中未处理的异常应用全局策略。

  结果过滤器包装单个操作结果的执行,并且尽在操作执行成功时运行。它们必须是围绕视图执行或格式化程序执行的逻辑的理想选择。

  

  2.实现过滤器

  所有过滤器均可通过不同的接口定义支持同步和异步的实现。根据需要执行的任务类型,选择同步或异步实现。从框架的角度看,它们是可以互换的。

  同步过滤器定义了 OnStageExecuting 和 OnStageExecuted 方法(也有例外)。OnStageExecuting 方法在事件管道阶段之前通过阶段名称来调用,而 OnStageExecuted 方法将在阶段名称命名的管道阶段之后调用。

    public class SampleActionFilter:IActionFilter{public void OnActionExecuting(ActionExecutingContext context){//操作执行前做的事情
        }public void OnActionExecuted(ActionExecutedContext context){//操作执行后做的事情
        }}

  异步过滤器定义了一个单一的 OnActionExecutionAsync  方法,可以在具体管道阶段的前后运行。 OnActionExecutionAsync 方法提供了一个 ActionExecutionDelegate 委托,调用时该委托会执行具体管道阶段的工作,然后等待完成。

public class SampleAsyncActionFilter: IAsyncActionFilter{public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next){//操作执行前做的事情await next();//操作执行后做的事情
        }}

  

  3.过滤器作用域

  过滤器有三种不同级别的作用域。你可以在特定的操作上用特性(Attribute)的方式使用特定的过滤器。也可以在控制器上用特性的方式使用过滤器,这样就可以将效果作用在控制器内的所有操作上。或者注册一个全局过滤器,它将作用于整个 MVC 应用程序的每一个操作。

  如果想要使用全局过滤器,可以在配置 MVC 时,在 Startup 的 ConfigureServices 方法中添加:

services.AddMvc(options =>{options.Filters.Add(typeof(SampleActionFilter));//通过类型options.Filters.Add(new SampleActionFilter());//注册实例}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

  过滤器既可以通过类型添加,也可以通过实例添加。如果通过实例添加,则该实例会被使用于每一个请求。如果通过类型添加,则在每次请求后都会创建一个实例,其所有构造函数依赖项都将通过 DI 来填充。

  把过滤器接口的实现当作特性使用也非常方便。过滤器特性可应用于控制器和操作方法。框架包含了内置的基于特性的过滤器,可以继承他们或者另外定制。例如,下面的过滤器继承了 ResultFilterAttribute,并重写 OnResultExecuting 方法(在响应中增加一个信息头):

  

public class AddHeaderAttribute: ResultFilterAttribute{private readonly string _name;private readonly string _value;public AddHeaderAttribute(string name, string value){_name = name;_value = value;}public override void OnResultExecuting(ResultExecutingContext context){context.HttpContext.Response.Headers.Add(_name,new string[] { _value });base.OnResultExecuting(context);}}

  特性允许过滤器接受参数,如下,可将此特性添加到控制器或操作中,并为其指定所需 HTTP 头的名称和值:

[AddHeader("Author", "Ruby Lu")]public class HomeController : Controller
{
}

  以下几种过滤器接口可以自定义为相应特性的实现:

    ActionFilterAttribute

    ExceptionFilterAttribute

    ResultFilterAttribute

    FormatFilterAttribute

    ServiceFilterAttribute

    TypeFilterAttribute

 

  4.取消和短路

  通过设置传入过滤器方法的上下文参数中的 Result 属性,可以在过滤器管道的任意一点短路管道。比如,下面的 ShortCircuitingResourceFilter 将阻止它之后管道内的所有过滤器,包括所有操作过滤器:

public class ShortCircuitingResourceFilter:Attribute,IResourceFilter{public void OnResourceExecuting(ResourceExecutingContext context){context.Result = new ContentResult() {Content = "短路"};}public void OnResourceExecuted(ResourceExecutedContext context){}}

 

2.配置过滤器

  全局过滤器在 Startup 中配置。基于特性的过滤器如果不需要任何依赖,可以简单地继承一个已存在地过滤器相对应地特性类型。如果要创建一个非全局作用域,但需要从依赖注入中获得依赖项的过滤器,那么在它们上面加上 ServiceFilterAttribute 或 TypeFilterAttribute 特性,这样就可用于控制器或操作了。

  1.依赖注入

  以特性形式实现的,直接添加到控制器或操作的过滤器,其构造函数不得由依赖注入提供依赖项。其原因在于,特性所需的构造函数参数必须由使用处直接提供。这是特性原型机理的限制。

  如果过滤器需要从 DI 中获得依赖项,那么可以用以下几种方法在类或操作方法使用:

    ServiceFilterAttribute

    TypeFilterAttribute

    IFilterFactory 实现特性

  TypeFilter 将为其依赖项从 DI 中使用服务来实例化一个实例。 ServiceFilter 则从 DI 中获取一个过滤器实例。下面演示 ServiceFilter:

  先在 ConfigureServices 中注册 AddHeaderFilterWithDI 类型:services.AddScoped<AddHeaderFilterWithDI>(); 

  然后使用:

    [ServiceFilter(typeof(AddHeaderFilterWithDI))]

    public IActionResult Index()

    {  

    }

  ServiceFilterAttribute 实现了IFilterFactory 接口,它公开了一个创建 IFilter 实例的方法。在 ServiceFilterAttribute 中,IFilterFactory 接口的 CreateInstance 方法被实现为从服务容器加载指定的类型。

  TypeFilterAttribute 非常类似 ServiceFilterAttribute (也实现 IFilterFactory 接口),但它的类型不是直接从 DI 容器中解析,相反,它使用 Microsoft.Extensions.DependencyInjection.ObjectFactory 实例化类型。

  由于这种差异,使用 TypeFilterAttribute 引用的类型不需要在使用前向容器注册,但它们仍由容器来填充其依赖项。此外,TypeFilterAttribute 可以可选的接受该类型的构造函数参数。下面是 TypeFilterAttribute 演示:

        [TypeFilter(typeof(AddHeaderAttribute),Arguments =new object[] { "Author","Ruby" })]public IActionResult Index(){return View();}

   如果有一个简单的过滤器,不需要任何参数,但有构造函数需要通过 DI 填充依赖项,那么可以继承 TypeFilterAttribute,允许使用自己命名的特性类和方法(而不是 [TypeFilterAttribute(typeof(FilterType))])。下面的过滤器显示了如何实现此功能:

 public class SampleActionFilterAttribute:TypeFilterAttribute{public SampleActionFilterAttribute() : base(typeof(SampleActionFilterImpl)){}private class SampleActionFilterImpl:IActionFilter{public void OnActionExecuting(ActionExecutingContext context){//操作执行前做的事情
            }public void OnActionExecuted(ActionExecutedContext context){//操作执行后做的事情
            }}}

  该过滤器可通过使用 [SampleActionFilter] 这样的语法应用于类或方法,而不必使用 [TypeFilter] 或 [ServiceFilter] 。

  IFilterFactory 实现 IFilter ,因此在过滤器管道中,任何位置的  IFilterFactory 实例都可当作 Filter 实例来使用。当框架准备调用过滤器时,将尝试将其转换为 IFilterFactory 。如果转换成功, 则调用 CreateInstance 方法来创建将被调用的 IFilter 实例。这是一种非常灵活的设计,因为当应用程序启动时,不需要明确地设置精确地过滤器。

  你可以在自己地特性中实现 IFilterFactory 几口,作为另一种创建过滤器的方法:

public class AddHeadWithFactoryAttribute:Attribute, IFilterFactory{public bool IsReusable { get; }//实现IFilterFactorypublic IFilterMetadata CreateInstance(IServiceProvider serviceProvider){return new InternalAddHeaderFilter();}}public class InternalAddHeaderFilter : IResultFilter{public  void OnResultExecuting(ResultExecutingContext context){context.HttpContext.Response.Headers.Add("Internal", new string[] { "Header Add" });}public void OnResultExecuted(ResultExecutedContext context){}}

 

  2.排序

   过滤器可以应用于操作方法或控制器(通过特性)或添加到全局过滤器集合中。作用域通常也决定了排序,最接近操作的过滤器首先运行。

  除了作用域,过滤器还可以通过实现 IOrderedFilter 来重写它们的执行顺序。此接口简单的暴露了一个 int Order 属性,并且过滤器基于该属性以数字升序执行。所有内置的过滤器,包括 TypeFilterAttribute 和 ServiceFilterAttribute ,都实现 IOrderedFilter  接口。,因此当将过滤器特性应用于类或方法时,可以指定过滤器执行顺序。默认情况下,所有内置过滤器的 Order 属性都为0,因此范围用作分隔符,并且是决定性因素(除非 Order 设置为 0)。

  每个从 Controller 基类继承的控制器都包含 OnActionExecuting 和 OnActionExecuted 方法。这些方法为给定操作包装了过滤器,它们分别最先运行和最后运行。假设没有为任何过滤器设置 Order 舒总,那么单纯基于范围的顺序为:

  控制器的 OnActionExecuting

  全局过滤器的OnActionExecuting

  类过滤器的OnActionExecuting

  方法过滤器的OnActionExecuting

  方法过滤器的OnActionExecuted 

  类过滤器的OnActionExecuted 

  全局过滤器的OnActionExecuted 

  控制器过滤器的OnActionExecuted 

   

  要修改默认的基于范围的顺序,则应显示设置类级别或者方法级别过滤器的 Order 属性。例如,将 Order = -1 添加到方法级属性:

  [MyFilter (Name = "...",Order = -1)]

  在这种情况下,小于零的值将确保此过滤器在全局和类级过滤器之前运行:

  控制器的 OnActionExecuting

  方法过滤器的OnActionExecuting

  全局过滤器的OnActionExecuting

  类过滤器的OnActionExecuting

  类过滤器的OnActionExecuted 

  全局过滤器的OnActionExecuted 

  控制器过滤器的OnActionExecuted 

  方法过滤器的OnActionExecuted 

  Controller 类的方法总是在所有过滤器之前和之后运行。这些方法不作为IFilter实例实现。也不参与IFilter排序算法。

 

  3.对比中间件

  一般来说,过滤器用于处理业务与应用程序的横切关注点,用法和功能很像中间件,但过滤器允许你将作用范围缩小,并将其插入到应用程序中有意义的位置,例如视图之前或模型绑定之后。过滤器是 MVC 的一部分,可以访问其上下文和构造函数。例如,中间件很难检测到请求的模型验证是否产生错误,并且做出相应的响应。

 

转载于:https://www.cnblogs.com/afei-24/p/11334100.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/349673.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.sh文件是什么语言_FastDFS分布式文件系统的搭建安装

FastDFS很久之前&#xff0c;对上传的文件可能是存储在数据库&#xff0c;在数据库中存储路径&#xff0c;保存文件的二进制数据&#xff0c;随着用户上传的文件增加&#xff0c;数据库数据越来越多。这时&#xff0c;可以使用分布式文件系统&#xff0c;将用户上传的文件例如图…

ASP.NET Core MVC 之依赖注入 View

ASP.NET Core 支持在试图中使用依赖注入。这将有助于提供视图专用的服务&#xff0c;比如本地化或者仅用于填充视图元素的数据。应尽量保持控制器和视图之间的关注点分离。视图所显示的大部分数据应该从控制器传入。 使用 inject 指令将服务注入到视图&#xff0c;语法 inject …

matlab全安装多大_不理会其他,我只中意T20天正V2.0软件,激活安装教程在这里...

大家好&#xff0c;我是本文的小编 软妹&#xff0c;前几篇为大家分享了Proe系列软件的安装步骤&#xff0c;在设计三维设计领域Pro/E是现今主流的CAD/CAM/CAE软件一款软件&#xff0c;特别是在国内产品设计领域占据重要位置。在数控加工编程软件领域&#xff0c;哪款软件才是王…

couchbase_Couchbase 2.0归类视图简介

couchbase大多数应用程序必须处理“主/详细”类型的数据&#xff1a; 啤酒厂和啤酒 部门和员工 发票和项目 … 例如&#xff0c;创建如下所示的应用程序视图是必需的&#xff1a; 借助Couchbase和许多面向文档的数据库&#xff0c;您可以使用不同的方式来处理此问题&…

NOIP模拟测试20「周·任·飞」

liu_runda出的题再次$\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%$ 任 题解 题目中为什么反复强调简单路径,没有环 没有环的图中点数-边数联通块数 前缀和维护边的前缀和,和点的前缀和, 在维护边的前缀和不好维护转化为横着边前缀和,竖着边前缀和 注意边的边界问题 看边如何维护 就拿…

如何脚踏实地构建Java Agent

在构建Plumbr的多年中&#xff0c;我们遇到了许多具有挑战性的问题。 在其他方面&#xff0c;使Plumbr Java Agent可靠地执行而又不危害客户的应用程序&#xff0c;是一个特别棘手的任务。 从实时系统中安全地收集所有需要的遥测会带来很多问题。 其中一些非常简单&#xff0c;…

ASP.NET Core MVC 之依赖注入 Controller

ASP.NET Core MVC 控制器应通过构造函数明确地请求它们地依赖关系&#xff0c;在某些情况下&#xff0c;单个控制器地操作可能需要一个服务&#xff0c;在控制器级别上的请求可能没有意义。在这种情况下&#xff0c;也可以将服务作为 Action 的参数。 依赖注入是一种如 Depend…

16g内存 32g内存游戏区别_电脑内存8G和16G的差别大吗?打游戏需要多大内存?

Hello大家好&#xff0c;我是兼容机之家的小牛。电脑内存是除了CPU之外最重要的元件之一&#xff0c;电脑内存的多少直接影响着运行大型软件、多任务时电脑的流畅程度&#xff0c;很多玩家在第一次购买电脑的时候并不知道应该购买内存多大的电脑&#xff0c;今天小牛就来和大家…

用友U9执行JS代码。

UFSoft.UBF.UI.AtlasHelper.RegisterAtlasStartupScript(part.Page, part.Page.GetType(), "JavaScriptExecQueue", "alert(地球即将毁灭&#xff0c;进入倒计时&#xff1a;5&#xff0c;4&#xff0c;3&#xff0c;2&#xff0c;1…嘣&#xff01;嘣&#xff…

java培训学费_北京Java培训班学费很贵吗,包含了哪些收费项目

北京的Java培训班有很多&#xff0c;价格却是相差不多的&#xff0c;但培训的课程就参差不齐了&#xff0c;有的培训班就是为了赚钱而存在的&#xff0c;想要系统的学习Java&#xff0c;确保学习效果&#xff0c;那么你一定要挑选正规的Java培训班&#xff0c;挑选适合自己的Ja…

typora.io使用教程

引言&#xff1a;对于开发人员大部分都接触过.md文件&#xff0c;而typora.io就是专门编辑.md文件的工具&#xff0c;该工具对于编写接口文档特别方便&#xff0c;它提供了word类似的大纲视图&#xff0c;同时也提供了很多的功能&#xff0c;但是改软件本身却非常的小&#xff…

c#编译时提高兼容性_幻像类型提高了编译时的安全性

c#编译时提高兼容性介绍 使用幻像类型是一种非常简单的技术&#xff0c;可用于提高代码的编译时安全性。 有很多潜在的用例&#xff0c;其复杂性程度各不相同&#xff0c;但是即使幻像类型的轻量级使用也可以显着提高编译时的安全性。 幻像类型只是带有未使用类型参数的参数化类…

如何查看电脑显卡配置_3080显卡电脑配置清单(3700X/10700)

3080显卡昨天就解禁评测了&#xff0c;因为最近的老铁都很期待装3080的机器&#xff0c;我这边做了一些整理&#xff0c;方便各位老铁3080配置有综合的了解。3080显卡售价更加详尽的3080厂家整理可以参考&#xff1a;3080公版哪里买&#xff1f;&#xff08;所有厂家整理&#…

问题 1074: 数字整除

题目描述定理&#xff1a;把一个至少两位的正整数的个位数字去掉&#xff0c;再从余下的数中减去个位数的5倍。当且仅当差是17的倍数时&#xff0c;原数也是17的倍数 。 例如&#xff0c;34是17的倍数&#xff0c;因为3-20-17是17的倍数&#xff1b;201不是17的倍数&#xff0c…

GWT HTTP请求替代

由于多种原因 &#xff0c;许多GWT用户放弃了RPC机制&#xff0c;这是GWT提供的调用后端的标准方法。 他们发现&#xff0c;在GWT RequestBuilder与其他可能不适合其应用程序模型的外部库之间迷失了许多 。 这篇文章的目的是通过GWT中众所周知的HTTP / Rest库&#xff0c;以使情…

极限中0除以常数_基本不等式中常用公式百度作业帮

1. 基本不等式中常用公式基本不等式中常用公式&#xff1a;(1)√((ab)/2)≥(ab)/2≥√ab≥2/(1/a1/b)。(当且仅当ab时&#xff0c;等号成立)(2)√(ab)≤(ab)/2。(当且仅当ab时&#xff0c;等号成立)(3)ab≥2ab。(当且仅当ab时&#xff0c;等号成立)(4)ab≤(ab)/4。(当且仅当ab时…

NOIP模拟测试24「star way to hevaen·lost my music」

star way to heaven 题解 大致尝试了一下并查集,记忆化搜索,最小生成树 最小生成树是正解,跑最小生成树然后找到最大的值 欧几里德距离最小生成树学习 prim楞跑 至于为什么跑最小生成树不是跑最大生成树,你跑最大生成树连的边可能会^%$&$%!# 感性理解手膜吧,我理解但说不清…

NOIP模拟测试25「字符串·乌鸦喝水·所陀门王的宝藏(陀螺王)」

字符串 题解 没看出catalan怎么办 dp打表啊! 考虑大力dp拿到30分好成绩!顺便收获一张表 打表发现$C_{nm}^{m}-C_{nm}^{m-1}$ 仔细观察然后发现其实就是之前的网格那个题 那么我们回顾一下网格那个题 先看最简单的nm情况 求左下角走到右上角方案数,不能经过中间那条线 考虑大力容…

stackexchange_通过Spring Social推特StackExchange –第1部分

stackexchange本文将介绍一个快速的附带项目-一个自动从各种Q&#xff06;A StackExchange网站上发布热门问题的机器人&#xff0c;例如StackOverflow &#xff0c; ServerFault &#xff0c; SuperUser等。我们将为StackExchange API构建一个简单的客户端&#xff0c;然后进行…