Web APi之过滤器执行过程原理解析【二】(十一)
前言
上一节我们详细讲解了过滤器的创建过程以及粗略的介绍了五种过滤器,用此五种过滤器对实现对执行Action方法各个时期的拦截非常重要。这一节我们简单将讲述在Action方法上、控制器上、全局上以及授权上的自定义特性的执行过程。
APiController
之前有讲到该APiController,也就稍微介绍了,这节我们来详细此Web API控制器的基类:
public abstract class ApiController : IHttpController, IDisposable
{
// Fields
private HttpConfiguration _configuration;
private HttpControllerContext _controllerContext;
private bool _disposed;
private ModelStateDictionary _modelState;
private HttpRequestMessage _request;
private UrlHelper _urlHelper; // Methods
protected ApiController();
public void Dispose();
protected virtual void Dispose(bool disposing);
public virtual Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken);
protected virtual void Initialize(HttpControllerContext controllerContext);
internal static Func<Task<HttpResponseMessage>> InvokeActionWithActionFilters(HttpActionContext actionContext, CancellationToken cancellationToken, IEnumerable<IActionFilter> filters, Func<Task<HttpResponseMessage>> innerAction);
internal static Func<Task<HttpResponseMessage>> InvokeActionWithAuthorizationFilters(HttpActionContext actionContext, CancellationToken cancellationToken, IEnumerable<IAuthorizationFilter> filters, Func<Task<HttpResponseMessage>> innerAction);
internal static Task<HttpResponseMessage> InvokeActionWithExceptionFilters(Task<HttpResponseMessage> actionTask, HttpActionContext actionContext, CancellationToken cancellationToken, IEnumerable<IExceptionFilter> filters); // Properties
public HttpConfiguration Configuration { get; set; }
public HttpControllerContext ControllerContext { get; set; }
public ModelStateDictionary ModelState { get; }
public HttpRequestMessage Request { get; set; }
public UrlHelper Url { get; set; }
public IPrincipal User { get; } // Nested Types
private class FilterGrouping
{
// Fields
private List<IActionFilter> _actionFilters;
private List<IAuthorizationFilter> _authorizationFilters;
private List<IExceptionFilter> _exceptionFilters; // Methods
public FilterGrouping(IEnumerable<FilterInfo> filters);
private static void Categorize<T>(IFilter filter, List<T> list) where T: class; // Properties
public IEnumerable<IActionFilter> ActionFilters { get; }
public IEnumerable<IAuthorizationFilter> AuthorizationFilters { get; }
public IEnumerable<IExceptionFilter> ExceptionFilters { get; }
}
}
我们首先来看看此类中的一个私有类 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 方法:
private static void Categorize<T>(IFilter filter, List<T> list) where T: class
{
T item = filter as T;
if (item != null)
{
list.Add(item);
}
}
从这里我们可以得知:
当我们在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之过滤器执行过程原理解析【二】(十一)的更多相关文章
- Web APi之过滤器创建过程原理解析【一】(十)
前言 Web API的简单流程就是从请求到执行到Action并最终作出响应,但是在这个过程有一把[筛子],那就是过滤器Filter,在从请求到Action这整个流程中使用Filter来进行相应的处理从 ...
- Web APi之控制器创建过程及原理解析(八)
前言 中秋歇了歇,途中也时不时去看看有关创建控制器的原理以及解析,时间拖得比较长,实在是有点心有余而力不足,但又想着既然诺下了要写完原理一系列,还需有始有终.废话少说,直入主题. HttpContro ...
- Java Web每天学之Servlet的原理解析
Java Web每天学之Servlet的工作原理解析,上海尚学堂Java技术文章Java Web系列之二上一篇文章Java Web每天学之Servlet的工作原理解析是之一,欢迎点击阅读. Servl ...
- ASP.NET Web API 2 过滤器
Ø 前言 我们知道 ASP.NET Web API 过滤器,也是属于消息处理机制中的一部分.正因如此,我们经常使用它来完成对请求的授权验证.参数验证,以及请求的 Log 记录,程序异常捕获等. 1. ...
- koa执行过程原理分析
本文原创,转载请注明出处https://i.cnblogs.com/EditPosts.aspx?postid=5710639 我们大家都知道,当koa接到请求经过中间件时,当执行到 yield ne ...
- C# web api 中过滤器的使用
一.开篇 Fiter在Web API中经常会用到,主要用于记录日志,安全验证,全局错误处理等:Web API提供两种过滤器的基本类型:actionfilterattribute,exceptionfi ...
- Python程序的执行过程原理(解释型语言和编译型语言)
Python是一门解释型语言?我初学Python时,听到的关于Python的第一句话就是Python是一门解释型语言,我就这样一直相信下去,直到发现.pyc文件的存在,如果真是解释型语言,那么生成的. ...
- Request 接收参数乱码原理解析二:浏览器端编码原理
上一篇<Request 接收参数乱码原理解析一:服务器端解码原理>,分析了服务器端解码的过程,那么浏览器是根据什么编码的呢? 1. 浏览器解码 浏览器根据服务器页面响应Header中的“C ...
- Java多线程系列 JUC线程池03 线程池原理解析(二)
转载 http://www.cnblogs.com/skywang12345/p/3509954.html http://www.cnblogs.com/skywang12345/p/351294 ...
随机推荐
- 【系统篇】从int 3探索Windows应用程序调试原理
探索调试器下断点的原理 在Windows上做开发的程序猿们都知道,x86架构处理器有一条特殊的指令——int 3,也就是机器码0xCC,用于调试所用,当程序执行到int 3的时候会中断到调试器,如果程 ...
- Ant环境变量配置
Ant环境变量配置 1.新建系统变量ANT_HOME 变量名: ANT_HOME 变量值: D:\biancheng\apache-ant-1.7.1 2.修改PATH 变量值最后面 ...
- .Net程序员之不学Java做安卓开发:奇怪的Java语法
1.final关键字:用以修饰类时,表示类不可以被继承,指向基本数据类型或者引用类型时,该类只可以在声明的时候初始化 2.@Override 类似C# 中override关键字,表示对父类的重写.网上 ...
- C++风格的回调对象方法. 采用template实现
今天看了一篇文章,收藏一下代码.读一读很有激情 #include <iostream> #include <string> #include <vector> us ...
- ubuntu 安装与开始学习
下载地址 http://cn.ubuntu.com/download/ 经验: 1.遇到安装问题,首先尝试解读错误,再使用 ./configure --help 不行再上Stack overflo ...
- SQLServer中的数据库备份和还原
更多资源:http://denghejun.github.io 备份 SQLServer中的备份,这里是T-SQL的用法,具体示例代码如下,使用也相对简单,其中TestDatabase 是指所需备份的 ...
- web api Route属性定义
ASP.NET Web API路由,简单来说,就是把客户端请求映射到对应的Action上的过程.在"ASP.NET Web API实践系列03,路由模版, 路由惯例, 路由设置"一 ...
- CSS基础篇之了解CSS和它的基本属性
CSS是什么? CSS英文全名是Cascading Style Sheets翻译过来就是层叠样式表,它主是把网页表现与内容分离的一种样式设计语言.这种语言能优化我们编程,把东西简化和优化写法,而且不同 ...
- 用DataGridView导入TXT文件,并导出为XLS文件
使用 DataGridView 控件,可以显示和编辑来自多种不同类型的数据源的表格数据.也可以导出.txt,.xls等格式的文件.今天我们就先介绍一下用DataGridView把导入txt文件,导出x ...
- 免费图片存储和图话【提供demo下载】
我们不管是做博客系统还是其他网站,图片是免不了要使用到的.但是,我们都知道图片的访问是很耗资源的,同时也是很占磁盘空间的,且还特别占带宽. 所以,我们一般都会用到特定的图片服务器.不过,像我等屌丝平时 ...