Web APi之过滤器执行过程原理解析【二】(十一)
前言
上一节我们详细讲解了过滤器的创建过程以及粗略的介绍了五种过滤器,用此五种过滤器对实现对执行Action方法各个时期的拦截非常重要。这一节我们简单将讲述在Action方法上、控制器上、全局上以及授权上的自定义特性的执行过程。
APiController
之前有讲到该APiController,也就稍微介绍了,这节我们来详细此Web API控制器的基类:
1 public abstract class ApiController : IHttpController, IDisposable 2 { 3 // Fields 4 private HttpConfiguration _configuration; 5 private HttpControllerContext _controllerContext; 6 private bool _disposed; 7 private ModelStateDictionary _modelState; 8 private HttpRequestMessage _request; 9 private UrlHelper _urlHelper; 10 11 // Methods 12 protected ApiController(); 13 public void Dispose(); 14 protected virtual void Dispose(bool disposing); 15 public virtual Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken); 16 protected virtual void Initialize(HttpControllerContext controllerContext); 17 internal static Func<Task<HttpResponseMessage>> InvokeActionWithActionFilters(HttpActionContext actionContext, CancellationToken cancellationToken, IEnumerable<IActionFilter> filters, Func<Task<HttpResponseMessage>> innerAction); 18 internal static Func<Task<HttpResponseMessage>> InvokeActionWithAuthorizationFilters(HttpActionContext actionContext, CancellationToken cancellationToken, IEnumerable<IAuthorizationFilter> filters, Func<Task<HttpResponseMessage>> innerAction); 19 internal static Task<HttpResponseMessage> InvokeActionWithExceptionFilters(Task<HttpResponseMessage> actionTask, HttpActionContext actionContext, CancellationToken cancellationToken, IEnumerable<IExceptionFilter> filters); 20 21 // Properties 22 public HttpConfiguration Configuration { get; set; } 23 public HttpControllerContext ControllerContext { get; set; } 24 public ModelStateDictionary ModelState { get; } 25 public HttpRequestMessage Request { get; set; } 26 public UrlHelper Url { get; set; } 27 public IPrincipal User { get; } 28 29 // Nested Types 30 private class FilterGrouping 31 { 32 // Fields 33 private List<IActionFilter> _actionFilters; 34 private List<IAuthorizationFilter> _authorizationFilters; 35 private List<IExceptionFilter> _exceptionFilters; 36 37 // Methods 38 public FilterGrouping(IEnumerable<FilterInfo> filters); 39 private static void Categorize<T>(IFilter filter, List<T> list) where T: class; 40 41 // Properties 42 public IEnumerable<IActionFilter> ActionFilters { get; } 43 public IEnumerable<IAuthorizationFilter> AuthorizationFilters { get; } 44 public IEnumerable<IExceptionFilter> ExceptionFilters { get; } 45 } 46 }
我们首先来看看此类中的一个私有类 FilterGrouping ,顾名思义是对过滤器分组,我们查看其构造函数看看:
public FilterGrouping(IEnumerable<FilterInfo> filters)
{this._actionFilters = new List<IActionFilter>();this._authorizationFilters = new List<IAuthorizationFilter>();this._exceptionFilters = new List<IExceptionFilter>();foreach (FilterInfo info in filters){IFilter instance = info.Instance;Categorize<IActionFilter>(instance, this._actionFilters);Categorize<IAuthorizationFilter>(instance, this._authorizationFilters);Categorize<IExceptionFilter>(instance, this._exceptionFilters);}
}
我们仅仅只需 _actionFilters 为例,其余一样,我们再来看看 Categorize 方法:
1 private static void Categorize<T>(IFilter filter, List<T> list) where T: class 2 { 3 T item = filter as T; 4 if (item != null) 5 { 6 list.Add(item); 7 } 8 }
从这里我们可以得知:
当我们在HttpActionDescriptor初始化创建了封装了Filter对象的FilterInfo的集合列表,此时然后利用此类中的三个属性类型:IActionFilter、IAuthorizationFilter、以及IExceptionFilter进行过滤器分组得到对应过滤器集合列表
执行过程原理解析
下面我们通过例子来看看之执行过程,我们自定义以下五个过滤器
/// <summary>/// 全局的行为过滤器/// </summary>public class CustomConfigurationActionFilterAttribute : FilterAttribute, IActionFilter{public Task<HttpResponseMessage> ExecuteActionFilterAsync(System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation){Console.WriteLine(this.GetType().Name);return continuation();}}/// <summary>/// 控制器级行为过滤器/// </summary>public class CustomControllerActionFilterAttribute : FilterAttribute, IActionFilter{public Task<HttpResponseMessage> ExecuteActionFilterAsync(System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation){Console.WriteLine(this.GetType().Name);return continuation();}}/// <summary>/// 控制器方法级行为过滤器/// </summary>public class CustomActionFilterAttribute : FilterAttribute, IActionFilter{public Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation){Console.WriteLine(this.GetType().Name);return continuation();}}/// <summary>/// 控制器级授权访问过滤器/// </summary>public class CustomControllerAuthorizationFilterAttribute : FilterAttribute, IAuthorizationFilter{public Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation){Console.WriteLine(this.GetType().Name);return continuation();}}/// <summary>/// 控制器方法级授权访问过滤器/// </summary>public class CustomControllerActionAuthorizationFilterAttribute : FilterAttribute, IAuthorizationFilter{public Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation){Console.WriteLine(this.GetType().Name);return continuation();}}
接下来就是实现过滤器,配置文件中配置全局过滤器
config.Filters.Add(new CustomConfigurationActionFilterAttribute());
控制器及方法上过滤器
[CustomControllerAuthorizationFilter][CustomControllerActionFilter]public class ProductController : ApiController{[CustomActionFilter][CustomControllerActionAuthorizationFilter]public string GetFilter(){var sb = new StringBuilder();var actionSelector = this.Configuration.Services.GetActionSelector();var actionDesciptor = actionSelector.SelectAction(this.ControllerContext);foreach (var filterInfo in actionDesciptor.GetFilterPipeline()){sb.AppendLine("【FilterName:" + filterInfo.Instance.GetType().Name + ",FilterScope:" + filterInfo.Scope.ToString() + "】");}return sb.ToString();}}
最后来查看其结果:
看到这里是不是有点疑惑怎么按照Global->Controller->Action来进行排序,如果你看过前面文章就会知道这是过滤器管道按照FilterScope来生成的,实际上在服务器端生成的顺序为 CustomControllerAuthorizationFilterAttribute 、 CustomControllerActionAuthorizationFilterAttribute 、 CustomConfigurationActionFilterAttribute 、 CustomControllerActionFilterAttribute 以及 CustomActionFilterAttribute 由此我们得出结论:
授权过滤器不管任何的FilterScope都是优于行为过滤器,而在同一种类型的过滤器中是根据FilterScope来确定执行顺序的。
总结
有关更多深入的内容就不再探讨,本想多写一点,但是状态不佳加上更多内容比较复杂以免说不太明白云里雾里,想想还是算了,就这样了,下面还是给出其一张执行的详细示意图,来源【过滤器执行过程】
接下来将通过实例详细讲解Web API中的认证(Authentication)以及授权(Authorization),敬请期待。。。。。。
Web APi之过滤器执行过程原理解析【二】(十一)相关推荐
- maven scala plugin 实现jvmArgs,执行过程原理解析笔记
scala-maven-plugin 构建scala,springboot工程 我们在使用maven构建scala工程的时候, 要使用scala-maven-plugin插件,常规配置如下 : < ...
- Web APi之控制器创建过程及原理解析(八)
前言 中秋歇了歇,途中也时不时去看看有关创建控制器的原理以及解析,时间拖得比较长,实在是有点心有余而力不足,但又想着既然诺下了要写完原理一系列,还需有始有终.废话少说,直入主题. HttpContro ...
- ASP.NET Web API 2 过滤器
Ø 前言 我们知道 ASP.NET Web API 过滤器,也是属于消息处理机制中的一部分.正因如此,我们经常使用它来完成对请求的授权验证.参数验证,以及请求的 Log 记录,程序异常捕获等. 1. ...
- react 界面渲染完成 立即执行_React原理解析fiber、diff
资源 1. React中文网:https://react.docschina.org 2. React源码:https://github.com/facebook/react 学习目标 1. 掌握虚拟 ...
- C# web api 中过滤器的使用
一.开篇 Fiter在Web API中经常会用到,主要用于记录日志,安全验证,全局错误处理等:Web API提供两种过滤器的基本类型:actionfilterattribute,exceptionfi ...
- python语言是编译型语言-Python程序的执行过程原理(解释型语言和编译型语言)...
Python是一门解释型语言? 我初学Python时,听到的关于Python的第一句话就是Python是一门解释型语言,我就这样一直相信下去,直到发现.pyc文件的存在,如果真是解释型语言,那么生成的 ...
- mysql sql执行过程_MySQL探秘(二):SQL语句执行过程详解
昔日庖丁解牛,未见全牛,所赖者是其对牛内部骨架结构的了解,对于MySQL亦是如此,只有更加全面地了解SQL语句执行的每个过程,才能更好的进行SQL的设计和优化. 当希望MySQL能够以更高的性能运行查 ...
- OkHttp原理解析(二)
前言 上一篇我们学习了OKHttp的请求执行流程,知道了最终请求流程都会交给getResponseWithInterceptorChain方法来执行,接下来我们就详细分析执行getResponseWi ...
- Spring MVC 执行过程原理(请求映射原理、参数处理原理、返回值处理器)
Spring MVC 执行过程分析 文章目录 Spring MVC 执行过程分析 请求映射原理 适配器Adapter 执行目标方法 参数处理器解析器HandlerMethodArgumentResol ...
最新文章
- Intro to Parallel Programming CUDA-第一单元
- SpringBoot + Elasticsearch7.6实现简单查询及高亮分词查询
- Android中的context
- 搜狗听写,现在是录音笔硬件的“操作系统”了
- 代理模式、动态代理和面向方面
- leetcode83 删除排序链表中的重复元素
- python flask restful api_python之restful api(flask)获取数据
- java程序设置软件界面(jFrame)的最小大小
- 解决vue视图不渲染
- Java通过FFMPEG获取视频时长
- 思维导图ubuntu_适用于Linux用户的10款出色的免费思维导图软件
- python怎么求圆柱表面积半径和高由键盘输入_编写程序,从键盘输入圆的半径,求圆的周长和面积并输出。_学小易找答案...
- js中join的用法
- 《数据结构(c++语言版)》 清华大学邓俊辉
- 如何破解Win7的电脑登录密码?
- Linux 系统进程管理
- uni-app嵌入其他页面(阿里邮箱为例)
- arduino 红外遥控器控制LED灯
- 程序员与软件工程师的区别
- 物联网python开发实战pdf_智能物联网项目开发实战 PDF 下载
热门文章
- Silverlight教程第四部分:使用 Style 元素更好地封装观感 (木野狐译)
- nodejs事务使用总结
- 内排序及时间复杂度分析-插入排序选择排序交换排序归并排序分配和索引排序对比...
- elementUI的table组件实现setCurrentRow的滚动条定位效果
- CLOUD 04:zookeeper,kafka,hadoop高可用
- redis4.0之基于LFU的热点key发现机制
- ReactNative windows下打包生成安卓apk
- 二分图最大匹配 -- 匈牙利算法
- 关系运算符、逻辑 运算符与三元运算符
- Exchanger的使用