ASP.NET Core 2 学习笔记(十四)Filters
Filter是延续ASP.NET MVC的产物,同样保留了五种的Filter,分别是Authorization Filter、Resource Filter、Action Filter、Exception Filter及Result Filter。
通过不同的Filter可以有效处理封包进出的加工,本篇将介绍ASP.NET Core的五种Filter运作方式。
Filter 介绍
Filter的作用是在Action 执行前或执行后做一些加工处理。
某种程度来看,会跟Middleware很像,但执行的顺序略有不同,用对Filter不仅可以减少代码,还可以提高执行效率。
ASP.NET Core 有以下五种Filter 可以使用:
- Authorization Filter
Authorization是五种Filter中优先级最高的,通常用于验证Request合不合法,不合法后面就直接跳过。 - Resource Filter
Resource是第二优先,会在Authorization之后,Model Binding之前执行。通常会是需要对Model加工处理才用。 - Action Filter
最常使用的Filter,封包进出都会经过它,使用上没什么需要特别注意的。跟Resource Filter很类似,但并不会经过Model Binding。 - Exception Filter
异常处理的Filter。 - Result Filter
当Action完成后,最终会经过的Filter。
Filter 运作方式
ASP.NET Core的每个Request都会先经过已注册的Middleware接着才会执行Filter,除了会依照上述的顺序外,同类型的Filter预设都会以先进后出的方式处里封包。
Response在某些Filter并不会做处理,会直接被pass。Request及Response的运作流程如下图:
- 黄色箭头是正常情况流程
- 灰色箭头是异常处理流程
建立Filter
ASP.NET Core的Filter基本上跟ASP.NET MVC的差不多。
上述的五种Filter范例分别如下:
Authorization Filter
AuthorizationFilter.cs
- using Microsoft.AspNetCore.Http;
- using Microsoft.AspNetCore.Mvc.Filters;
- namespace MyWebsite.Filters
- {
- public class AuthorizationFilter : IAuthorizationFilter
- {
- public void OnAuthorization(AuthorizationFilterContext context)
- {
- context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");
- }
- }
- }
非同步的方式:
- // ...
- public class AuthorizationFilter : IAsyncAuthorizationFilter
- {
- public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
- {
- await context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");
- }
- }
Resource Filter
ResourceFilter.cs
- using Microsoft.AspNetCore.Http;
- using Microsoft.AspNetCore.Mvc.Filters;
- namespace MyWebsite.Filters
- {
- public class ResourceFilter : IResourceFilter
- {
- public void OnResourceExecuting(ResourceExecutingContext context)
- {
- context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");
- }
- public void OnResourceExecuted(ResourceExecutedContext context)
- {
- context.HttpContext.Response.WriteAsync($"{GetType().Name} out. \r\n");
- }
- }
- }
非同步的方式:
- // ...
- public class ResourceFilter : IAsyncResourceFilter
- {
- public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
- {
- await context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");
- await next();
- await context.HttpContext.Response.WriteAsync($"{GetType().Name} out. \r\n");
- }
- }
Action Filter
ActionFilter.cs
- using Microsoft.AspNetCore.Http;
- using Microsoft.AspNetCore.Mvc.Filters;
- namespace MyWebsite.Filters
- {
- public class ActionFilter : IActionFilter
- {
- public void OnActionExecuting(ActionExecutingContext context)
- {
- context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");
- }
- public void OnActionExecuted(ActionExecutedContext context)
- {
- context.HttpContext.Response.WriteAsync($"{GetType().Name} out. \r\n");
- }
- }
- }
非同步的方式:
- // ...
- public class ActionFilter : IAsyncActionFilter
- {
- public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
- {
- await context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");
- await next();
- await context.HttpContext.Response.WriteAsync($"{GetType().Name} out. \r\n");
- }
- }
Result Filter
ResultFilter.cs
- using Microsoft.AspNetCore.Http;
- using Microsoft.AspNetCore.Mvc.Filters;
- namespace MyWebsite.Filters
- {
- public class ResultFilter : IResultFilter
- {
- public void OnResultExecuting(ResultExecutingContext context)
- {
- context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");
- }
- public void OnResultExecuted(ResultExecutedContext context)
- {
- context.HttpContext.Response.WriteAsync($"{GetType().Name} out. \r\n");
- }
- }
- }
非同步的方式:
- // ...
- public class ResultFilter : IAsyncResultFilter
- {
- public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
- {
- await context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");
- await next();
- await context.HttpContext.Response.WriteAsync($"{GetType().Name} out. \r\n");
- }
- }
Exception Filter
ExceptionFilter.cs
- using Microsoft.AspNetCore.Http;
- using Microsoft.AspNetCore.Mvc.Filters;
- namespace MyWebsite.Filters
- {
- public class ExceptionFilter : IExceptionFilter
- {
- public void OnException(ExceptionContext context)
- {
- context.ExceptionHandled = true; // 表明异常已处理,客户端可得到正常返回
- context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");
- }
- }
- }
非同步的方式:
- // ...
- public class ExceptionFilter : IAsyncExceptionFilter
- {
- public Task OnExceptionAsync(ExceptionContext context)
- {
- context.ExceptionHandled = true;// 表明异常已处理,客户端可得到正常返回
- context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");
- return Task.CompletedTask;
- }
- }
注册Filter
Filter有两种注册方式,一种是全局注册,另一种是用[Attribute]局部
注册的方式,只套用在特定的Controller或Action。
全局注册
在Startup.ConfigureServices
的MVC服务中注册Filter,这样就可以套用到所有的Request。如下:
- // ...
- public class Startup
- {
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddMvc(config =>
- {
- config.Filters.Add(new ResultFilter());
- config.Filters.Add(new ExceptionFilter());
- config.Filters.Add(new ResourceFilter());
- });
- }
- }
局部注册
ASP.NET Core在局部注册Filter的方式跟ASP.NET MVC有一点不一样,要通过[TypeFilter(type)]
。
在Controller或Action上面加上[TypeFilter(type)]
就可以局部注册Filter。如下:
- // ...
- namespace MyWebsite.Controllers
- {
- [TypeFilter(typeof(AuthorizationFilter))]
- public class HomeController : Controller
- {
- [TypeFilter(typeof(ActionFilter))]
- public void Index()
- {
- Response.WriteAsync("Hello World! \r\n");
- }
- [TypeFilter(typeof(ActionFilter))]
- public void Error()
- {
- throw new System.Exception("Error");
- }
- }
- }
[TypeFilter(type)]
用起来有点冗长,想要像过去ASP.NET MVC用[Attribute]
注册Filter的话,只要将Filter继承Attribute
即可。如下:
- public class AuthorizationFilter : Attribute, IAuthorizationFilter
- {
- // ...
- }
- public class ActionFilter : Attribute, IActionFilter
- {
- // ...
- }
[Attribute]
注册就可以改成如下方式:
- // ...
- namespace MyWebsite.Controllers
- {
- [AuthorizationFilter]
- public class HomeController : Controller
- {
- [ActionFilter]
- public void Index()
- {
- Response.WriteAsync("Hello World! \r\n");
- }
- [ActionFilter]
- public void Error()
- {
- throw new System.Exception("Error");
- }
- }
- }
执行结果
http://localhost:5000/Home/Index
输出结果如下:
- AuthorizationFilter in.
- ResourceFilter in.
- ActionFilter in.
- Hello World!
- ActionFilter out.
- ResultFilter in.
- ResultFilter out.
- ResourceFilter out.
http://localhost:5000/Home/Error
输出结果如下:
- AuthorizationFilter in.
- ResourceFilter in.
- ActionFilter in.
- ActionFilter out.
- ExceptionFilter in.
- ResourceFilter out.
执行顺序
预设注册同类型的Filter 是以先进后出的方式处里封包,注册层级也会影响执行顺序。
但也可以通过实现 IOrderedFilter 更改执行顺序。例如:
- public class ActionFilter : Attribute, IActionFilter, IOrderedFilter
- {
- public string Name { get; set; }
- public int Order { get; set; } = 0;
- public void OnActionExecuting(ActionExecutingContext context)
- {
- context.HttpContext.Response.WriteAsync($"{GetType().Name}({Name}) in. \r\n");
- }
- public void OnActionExecuted(ActionExecutedContext context)
- {
- context.HttpContext.Response.WriteAsync($"{GetType().Name}({Name}) out. \r\n");
- }
- }
在注册Filter 时带上Order,数值越小优先权越高。
- // ...
- public class Startup
- {
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddMvc(config =>
- {
- config.Filters.Add(new ActionFilter() { Name = "Global", Order = 3 });
- });
- }
- }
- // ...
- namespace MyWebsite.Controllers
- {
- [ActionFilter(Name = "Controller", Order = 2)]
- public class HomeController : Controller
- {
- [ActionFilter(Name = "Action", Order = 1)]
- public void Index()
- {
- Response.WriteAsync("Hello World! \r\n");
- }
- }
- }
变更执行顺序后的输出内容:
- ActionFilter(Action) in.
- ActionFilter(Controller) in.
- ActionFilter(Global) in.
- Hello World!
- ActionFilter(Global) out.
- ActionFilter(Controller) out.
- ActionFilter(Action) out.
参考
老司机发车啦:https://github.com/SnailDev/SnailDev.NETCore2Learning
ASP.NET Core 2 学习笔记(十四)Filters的更多相关文章
- Asp.Net Core WebApi学习笔记(四)-- Middleware
Asp.Net Core WebApi学习笔记(四)-- Middleware 本文记录了Asp.Net管道模型和Asp.Net Core的Middleware模型的对比,并在上一篇的基础上增加Mid ...
- 使用Visual Studio Code开发Asp.Net Core WebApi学习笔记(四)-- Middleware
本文记录了Asp.Net管道模型和Asp.Net Core的Middleware模型的对比,并在上一篇的基础上增加Middleware功能支持. 在演示Middleware功能之前,先要了解一下Asp ...
- ASP.NET Core 2 学习笔记(四)依赖注入
ASP.NET Core使用了大量的依赖注入(Dependency Injection, DI),把控制反转(Inversion Of Control, IoC)运用的相当巧妙.DI可算是ASP.NE ...
- ASP.NET Core 2 学习笔记(十)视图
ASP.NET Core MVC中的Views是负责网页显示,将数据一并渲染至UI包含HTML.CSS等.并能痛过Razor语法在*.cshtml中写渲染画面的程序逻辑.本篇将介绍ASP.NET Co ...
- ASP.NET Core 2 学习笔记(十二)REST-Like API
Restful几乎已算是API设计的标准,通过HTTP Method区分新增(Create).查询(Read).修改(Update)和删除(Delete),简称CRUD四种数据存取方式,简约又直接的风 ...
- ASP.NET Core 2 学习笔记(十三)Swagger
Swagger也算是行之有年的API文件生成器,只要在API上使用C#的<summary />文件注解标签,就可以产生精美的线上文件,并且对RESTful API有良好的支持.不仅支持生成 ...
- sql server 关于表中只增标识问题 C# 实现自动化打开和关闭可执行文件(或 关闭停止与系统交互的可执行文件) ajaxfileupload插件上传图片功能,用MVC和aspx做后台各写了一个案例 将小写阿拉伯数字转换成大写的汉字, C# WinForm 中英文实现, 国际化实现的简单方法 ASP.NET Core 2 学习笔记(六)ASP.NET Core 2 学习笔记(三)
sql server 关于表中只增标识问题 由于我们系统时间用的过长,数据量大,设计是采用自增ID 我们插入数据的时候把ID也写进去,我们可以采用 关闭和开启自增标识 没有关闭的时候 ,提示一下错 ...
- python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例
python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例 新浪爱彩双色球开奖数据URL:http://zst.aicai.com/ssq/openInfo/ 最终输出结果格 ...
- ASP.NET Core 2 学习笔记(七)路由
ASP.NET Core通过路由(Routing)设定,将定义的URL规则找到相对应行为:当使用者Request的URL满足特定规则条件时,则自动对应到相符合的行为处理.从ASP.NET就已经存在的架 ...
- ASP.NET Core 2 学习笔记(一)开始
原文:ASP.NET Core 2 学习笔记(一)开始 来势汹汹的.NET Core似乎要取代.NET Framework,ASP.NET也随之发布.NET Core版本.虽然名称沿用ASP.NET, ...
随机推荐
- 汽车检测SIFT+BOW+SVM
项目来源于 <opencv 3计算机视觉 python语言实现> 整个执行过程如下: 1)获取一个训练数据集. 2)创建BOW训练器并获得视觉词汇. 3)采用词汇训练SVM. 4)尝试对测 ...
- java泛型---通配符,泛型嵌套
package generic; import java.util.ArrayList; import java.util.List; /** * ? -->通配符,类型不确定,用于声明 变量| ...
- 【数组】Jump Game
题目: Given an array of non-negative integers, you are initially positioned at the first index of the ...
- FoxitReader软件下载并安装(图文详解)
不多说,直接上干货! FoxitReader官方网址:https://www.foxitsoftware.com/downloads/ 结束 欢迎大家,加入我的微信公众号:大数据躺过的坑 ...
- VirtualBox虚拟机安装ubuntu系统(图文详解)
不多说,直接上干货! 想简单说下,想必大家有的喜欢玩一下linux操作系统,但是又不想实际安装在物理机上.那我们就需要用到虚拟机了,这里我们介绍一下如何用VirtualBox安装ubuntu的方法. ...
- vue2.0实现购物车功能
购物车功能是一件比较繁琐的事情,逻辑功能太多,今天就用vue2.0实现一个简单的购物车功能,数据都本地自己写的假数据 功能列表: 1.全选和单选结算 2.减少和增加数量 3.商品的删除 界面搭建以及布 ...
- android学习-IPC机制之ACtivity绑定Service通信
bindService获得Service的binder对象对服务进行操作 Binder通信过程类似于TCP/IP服务连接过程binder四大架构Server(服务器),Client(客户端),Serv ...
- C++11中右值引用和移动语义
目录 左值.右值.左值引用.右值引用 右值引用和统一引用 使用右值引用,避免深拷贝,优化程序性能 std::move()移动语义 std::forward()完美转发 容器中的emplace_back ...
- ASP.NET 多环境下配置文件web.config的灵活配置---转
注意:本功能在.Net Core中已经不可用,暂时需手动修改web.config中的信息,或者将其设置在appsettings.XXX.json中,然后再使用web.config中的环境变量来制定使用 ...
- Oracle驱动classes12.jar 与ojdbc14.jar的区别
简单的说,如果使用jdk1.2和jdk1.3就使用classes12.jar:如果使用的jdk1.4和jdk1.5的,就选用ojdbc14.jar. 驱动包classes12.jar用于JDK 1.2 ...