问题

如何在ASP.NET Core的MVC请求管道之前和之后运行代码。

在一个空的项目中,更新 Startup 类以添加MVC的服务和中间件。

  1. publicvoid ConfigureServices

  2. (IServiceCollection services)

  3. {

  4. services.AddMvc();

  5. }

  6. publicvoid Configure(

  7. IApplicationBuilder app,

  8. IHostingEnvironment env)

  9. {

  10. app.UseMvc(routes =>

  11. {

  12. routes.MapRoute(

  13. name: "default",

  14. template: "{controller=Home}/{action=Index}/{id?}");

  15. });

  16. }

添加类来实现过滤器。

  1. publicclass ParseParameterActionFilter : Attribute, IActionFilter

  2. {

  3. publicvoid OnActionExecuting(ActionExecutingContext context)

  4. {

  5. object param;

  6. if (context.ActionArguments.TryGetValue("param", out param))

  7. context.ActionArguments["param"] = param.ToString().ToUpper();

  8. else

  9. context.ActionArguments.Add("param", "I come from action filter");

  10. }

  11. publicvoid OnActionExecuted(ActionExecutedContext context)

  12. {

  13. }

  14. }

在Home控制器中添加一个使用Action过滤器的操作方法,

  1. [ParseParameterActionFilter]

  2. public IActionResult ParseParameter(string param)

  3. {

  4. return Content($"Hello ParseParameter. Parameter: {param}");

  5. }

浏览到 / Home / ParseParameter; 你会看到的 -

讨论

筛选器在选择执行操作方法后运行。MVC为授权和缓存等内容提供了内置的过滤器。自定义过滤器对于封装要在动作方法之前或之后运行的可重用代码非常有用。

过滤器可能导致结果短路,即停止运行中的代码,并将结果返回给客户端。他们也可以通过服务容器注入 服务,这使得他们非常灵活。

过滤器接口

创建自定义过滤器需要实现您所需的过滤器类型的接口。大多数过滤器类型有两种类型的接口 - 同步和异步。

  1. publicclass HelloActionFilter : IActionFilter

  2. {

  3. publicvoid OnActionExecuting(ActionExecutingContext context)

  4. {

  5. // runs before action method

  6. }

  7. publicvoid OnActionExecuted(ActionExecutedContext context)

  8. {

  9. // runs after action method

  10. }

  11. }

  12. publicclass HelloAsyncActionFilter : IAsyncActionFilter

  13. {

  14. public async Task OnActionExecutionAsync(

  15. ActionExecutingContext context,

  16. ActionExecutionDelegate next)

  17. {

  18. // runs before action method

  19. await next();

  20. // runs after action method

  21. }

  22. }

您可以通过在上下文参数(对于异步过滤器,不要调用下一个 委托)中设置Result (类型 IActionResult)属性 来短路过滤器管道 。

  1. publicclass SkipActionFilter : Attribute, IActionFilter

  2. {

  3. publicvoid OnActionExecuting(ActionExecutingContext context)

  4. {

  5. context.Result = new ContentResult

  6. {

  7. Content = "I'll skip the action execution"

  8. };

  9. }

  10. publicvoid OnActionExecuted(ActionExecutedContext context)

  11. { }

  12. }

  13. [SkipActionFilter]

  14. public IActionResult SkipAction()

  15. {

  16. return Content("Hello SkipAction");

  17. }

对于结果过滤器,可以通过 在上下文参数上设置取消属性并发送响应来进行短路 。

  1. public void OnResultExecuting(ResultExecutingContext context)

  2. {

  3. context.Cancel = true ;

  4. context.HttpContext.Response.WriteAsync(“我将跳过结果执行” );

  5. }

  6. [SkipResultFilter]

  7. public IActionResult SkipResult()

  8. {

  9. 返回 内容(“Hello SkipResult” );

  10. }

过滤器属性

MVC提供了可以继承的抽象基类来创建自定义过滤器。这些抽象类继承自 Attribute 类,因此可以用来装饰控制器和操作方法。

  • ActionFilterAttribute

  • ResultFilterAttribute

  • ExceptionFilterAttribute

  • ServiceFilterAttribute

  • TypeFilterAttribute

过滤器类型

在过滤器管道的不同阶段有各种类型的过滤器。下面,官方文件中的一个数字说明了顺序:

授权

这是运行的第一个过滤器,并将对未经授权的用户的请求短路。他们只有一个方法(不同于其他大多数具有执行 和 执行 方法的过滤器 )。通常情况下,您不会编写自己的授权过滤器,内置过滤器调用到框架的授权机制中。

资源

它们在模型绑定之前运行,可以用来改变它的行为。而且,它们在结果生成后运行,可用于缓存等。

行动

它们在动作方法之前和之后运行,因此对操作动作参数或其结果非常有用。提供给这些过滤器的上下文让您可以操作动作参数,控制器和结果。

例外

它们可以在写入响应之前用于未处理的异常。异常处理中间件适用于大多数场景,但是如果您想根据调用的操作以不同方式处理错误,则可以使用此过滤器。

结果

如果结果成功,它们在执行操作方法的结果之前和之后运行。他们可以用来操纵结果的格式。

过滤范围

可以在不同级别的范围添加过滤器:Action,Controller和Global。属性用于动作和控制器级作用域。对于全局范围的过滤器,您需要添加它们以 在启动时配置服务时 过滤MvcOptions的集合 ,

  1. services.AddMvc(options =>

  2. {

  3. // by instance

  4. options.Filters.Add(new AddDeveloperResultFilter("Tahir Naushad"));

  5. // by type

  6. options.Filters.Add(typeof(GreetDeveloperResultFilter));

  7. });

过滤器按顺序执行

  1. 的 执行 方法是首先呼吁全球>控制器>动作过滤器。

  2. 然后 为Action> Controller> Global过滤器调用已执行的方法。

过滤依赖注入

为了使用需要在运行时注入依赖关系的过滤器,您需要通过Type添加它们。您可以将它们全局添加(如上所述),但是,如果要将它们应用于操作或控制器(作为属性),则有两个选项:

ServiceFilterAttribute

此属性使用服务容器检索过滤器。要使用它,

创建一个使用依赖注入的过滤器 ,

  1. publicclass GreetingServiceFilter : IActionFilter

  2. {

  3. private readonly IGreetingService greetingService;

  4. public GreetingServiceFilter(IGreetingService greetingService)

  5. {

  6. this.greetingService = greetingService;

  7. }

  8. publicvoid OnActionExecuting(ActionExecutingContext context)

  9. {

  10. context.ActionArguments["param"] =

  11. this.greetingService.Greet("James Bond");

  12. }

  13. publicvoid OnActionExecuted(ActionExecutedContext context)

  14. { }

  15. }

将过滤器添加到服务容器

  1. services.AddScoped<GreetingServiceFilter>();

使用ServiceFilterAttribute应用它

  1. [ServiceFilter(typeof(GreetingServiceFilter))]

  2. public IActionResult GreetService(string param)

TypeFilterAttribute

该属性不需要在服务容器中注册过滤器,并使用ObjectFactory 委托启动类型 。使用它

创建一个使用依赖注入的过滤器

  1. publicclass GreetingTypeFilter : IActionFilter

  2. {

  3. private readonly IGreetingService greetingService;

  4. public GreetingTypeFilter(IGreetingService greetingService)

  5. {

  6. this.greetingService = greetingService;

  7. }

  8. publicvoid OnActionExecuting(ActionExecutingContext context)

  9. {

  10. context.ActionArguments["param"] = this.greetingService.Greet("Dr. No");

  11. }

  12. publicvoid OnActionExecuted(ActionExecutedContext context)

  13. { }

  14. }

应用它使用 TypeFilterAttribute。

  1. [TypeFilter(typeof(GreetingTypeFilter))]

  2. public IActionResult GreetType1(string param)

你也可以从TypeFilterAttribute继承 ,然后在没有TypeFilter的情况下 使用,

  1. publicclass GreetingTypeFilterWrapper : TypeFilterAttribute

  2. {

  3. public GreetingTypeFilterWrapper() : base(typeof(GreetingTypeFilter))

  4. { }

  5. }

  6. [GreetingTypeFilterWrapper]

  7. public IActionResult GreetType2(string param)

更多精彩文章请关注我们的微信公众号FocusDotCore

基础教程:ASP.NET Core 2.0 MVC筛选器的更多相关文章

  1. ASP.NET Core 2.0 MVC项目实战

    一.前言 毕业后入职现在的公司快有一个月了,公司主要的产品用的是C/S架构,再加上自己现在还在学习维护很老的delphi项目,还是有很多不情愿的.之前实习时主要是做.NET的B/S架构的项目,主要还是 ...

  2. ASP.NET CORE 1.0 MVC API 文档用 SWASHBUCKLE SWAGGER实现

    from:https://damienbod.com/2015/12/13/asp-net-5-mvc-6-api-documentation-using-swagger/ 代码生成工具: https ...

  3. ASP.NET Core 基础教程 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core 基础教程 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 是对 ASP.NET 有重大意义的一次重新设计.本章节我们将介绍 A ...

  4. asp.net core 3.0 MVC JSON 全局配置

    asp.net core 3.0 MVC JSON 全局配置 System.Text.Json(default) startup配置代码如下: using System.Text.Encodings. ...

  5. ASP.NET Core 3.0 gRPC 拦截器

    目录 ASP.NET Core 3.0 使用gRPC ASP.NET Core 3.0 gRPC 双向流 ASP.NET Core 3.0 gRPC 拦截器 一. 前言 前面两篇文章给大家介绍了使用g ...

  6. asp.net Core 2.0 MVC为Controller或Action添加定制特性实现登录验证

    前言:最近在倒腾 微软的新平台 asp.net Core 2.0,在这个过程中有些东西还是存在差异.下面是我在学习过程的一点笔记.有不妥之处,望各位大虾指正! 一.先创建一个控制器继承于Control ...

  7. 基础教程:视图中的ASP.NET Core 2.0 MVC依赖注入

    问题 如何在ASP.NET Core MVC Views中注入和使用服务. 解 更新 启动 类来为MVC添加服务和中间件. 添加一项服务 添加一个Controller,返回 ViewResult. 添 ...

  8. ASP.NET Core 5.0 MVC中的 Razor 页面 介绍

    Razor 是一个用于将基于服务器的代码嵌入到网页中的标记语法. Razor语法由 Razor 标记.c # 和 HTML 组成. 通常包含 Razor 的文件的扩展名 cshtml Razor 语法 ...

  9. ASP.Net Core 5.0 MVC 配置文件读取,Startup 类中ConfigureServices 方法、Configure 方法的使用

    配置文件读取 1. 新建FirstController控制器 在appsettings文件内容替换成以下代码 { "Position": { "Title": ...

随机推荐

  1. Request.QueryString("id")与Request("id")区别

    Request从几个集合取数据是有顺序的,从前到后的顺序依次是 QueryString,Form,最后是ServerVariables.Request对象按照这样的顺序依次搜索这几个集合中的变量,如果 ...

  2. python读取命令行参数的方法

    1.sys模块 需要模块:sys参数个数:len(sys.argv)脚本名:    sys.argv[0]参数1:     sys.argv[1]参数2:     sys.argv[2] test.p ...

  3. Python系列之模块、和字符串格式化

    Python 模块 模块让你能够有逻辑地组织你的Python代码段. 把相关的代码分配到一个 模块里能让你的代码更好用,更易懂. 模块也是Python对象,具有随机的名字属性用来绑定或引用. 模块分为 ...

  4. zoj 1108 FatMouse's Speed 基础dp

    FatMouse's Speed Time Limit: 2 Seconds      Memory Limit:65536 KB     Special Judge FatMouse believe ...

  5. css百分比参照大总结

    最近做PC端项目,由于要自适应到800*600,所以免不了要使用百分比的布局方式,但是一开始有点搞不清楚百分比的参照,于是页面的布局怎么调也调不好. 事后我进行了一下总结,希望能够帮到大家: 参照父元 ...

  6. NodeJS 初学之安装配置环境

    [TOC] 1.环境安装 操作系统: Ubuntu 16.04.2 LTS 1.1安装nvm ryan@ryan-900X5L:~/temp$ curl https://raw.githubuserc ...

  7. JAVAEE企业级应用开发浅谈第一辑

    不积跬步无以至千里,不积小流无以成江海 Step1.情景概要 作为一个JAVA WEB 开发人员,在开发web 项目时项目大家都有自己的一些新的体会,对于web 开发出现的一些比较经典的名词大家都会有 ...

  8. 通过nginx的fastcgi_param来设置环境变量

    在nginx配置文件中,可以在nginx总体的配置文件nginx.conf中,也可以在单独的网站配置环境中进行设置,如:www.tomener.com.conf 在配置环境server段locatio ...

  9. Fatal error in launcher:Unable to create process using '"'

    Windows下同时存在Python2和Python3使用pip时系统报错:Fatal error in launcher: Unable to create process using '" ...

  10. Java实用知识记录 —— 截止到Java8

    记录Java实用知识点,截止(包括)到Java8,只作概要的描述,不涉及到具体细节.变量:int.long的包装类支持无符号位操作,即其在内存中的位可以用来全部表示正数."_"可以 ...