问题

如何在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. mysql慢查询分析工具 mysqlsla 安装

    概述 mysqlsla 是一款很不错的mysql慢查询日志分析工具,而且简单易用.mysqlsla 是用perl编写的脚本,运行需要perl-DBI和per-DBD-Mysql两模块的支持.mysql ...

  2. Centos7安装Percona5.7

    OS: Centos7.0 DB: Percona5.7 1. 通过yum安装 ## 删除之前的mysql数据库, 我用的是centos7.再安装虚拟机的时候,预装了很多软件.所以mysql和mari ...

  3. JavaScript 版数据结构与算法(四)集合

    今天,我们要讲的是数据结构与算法中的集合. 集合简介 什么是集合?与栈.队列.链表这些顺序数据结构不同,集合是一种无序且唯一的数据结构.集合有什么用?在 Python 中,我经常使用集合来给数组去重: ...

  4. SQL SERVER 根据地图经纬度计算距离函数

    前些天客户提出一个这样的要求:一个手机订餐网,查询当前所在位置的5公里范围的酒店,然后客户好去吃饭. 拿到这个请求后,不知道如何下手,静静地想了一下,在酒店的表中增加两个字段,用来存储酒店所在的经度和 ...

  5. python pip安装方法

    1.python安装,最好是按照32位的版本,64位版本有的时候出现奇怪问题. 2.python安装完成后,需要在系统的环境变量"path"中增加路径设置. 3.一般情况下,使用p ...

  6. 我的第一个python web开发框架(9)——目录与配置说明

    和老大聊完后,小白回家接收到相关工具函数包后,就按要求开始干活,首先要做的是熟悉配置参数和了解工具函数有哪些实用的工具. 由于这个项目比较简单,所以不用创建那么多分类,只需要api.common.co ...

  7. 【Windows 10 应用开发】使用x:Bind标记动态获得计算结果

    UWP 在传统(WPF)的Binding标记上引入了 Bind 标记,Bind 基于编译阶段生成,因而具有较高的性能.但是,你得注意,这个性能上的优化是免去了运行阶段动态绑定的开销,这是不包括数据源的 ...

  8. [ACdream]小晴天老师系列——竖式乘

    题目链接:http://acdream.info/contest?cid=1269#problem-C Problem Description 小晴天是ACdream团队中最牛的老师之一,他最擅长数学 ...

  9. 树莓派.使用Node.js控制GPIO

    树莓派上的40个GPIO是最好玩的东西 它们可以被C,/C++, Python, Java等语言直接控制 现在就来看看怎么用Node.js做到同样的事情 在试验之前, 请先安装好Node.js, 具体 ...

  10. LeetCode 78. Subsets(子集合)

    Given a set of distinct integers, nums, return all possible subsets. Note: The solution set must not ...