Asp.net web Api源码分析-Filter
紧接着上文Asp.net web Api源码分析-HttpActionDescriptor的创建 HttpActionDescriptor现在已经创建好了,在这里个人再次提醒一下,建议大家在路由的时候写上Action参数,如
api/{controller}/{action}/{id}而不要忽略Action参数写成api/{controller}/{id}。现在我们回到ApiController的ExecuteAsync方法中来,接下来就是利用新建的HttpActionDescriptor来创建一个HttpActionContext实例,然后通过 IEnumerable<FilterInfo> filters = actionDescriptor.GetFilterPipeline();来获取FilterInfo的集合。那么我们来看看FilterInfo是如何获取的,在HttpActionDescriptor中有一个InitializeFilterPipeline方法,相关代码如下:
public abstract class HttpActionDescriptor
{
protected HttpActionDescriptor()
{
_filterPipeline = new Lazy<Collection<FilterInfo>>(InitializeFilterPipeline);
}
public virtual Collection<FilterInfo> GetFilterPipeline()
{
return _filterPipeline.Value;
}
private Collection<FilterInfo> InitializeFilterPipeline()
{
IEnumerable<IFilterProvider> filterProviders = _configuration.Services.GetFilterProviders();
IEnumerable<FilterInfo> filters = filterProviders.SelectMany(fp => fp.GetFilters(_configuration, this)).OrderBy(f => f,
FilterInfoComparer.Instance);
// Need to discard duplicate filters from the end, so that most specific ones get kept (Action scope) and
// less specific ones get removed (Global)
filters = RemoveDuplicates(filters.Reverse()).Reverse();
return new Collection<FilterInfo>(filters.ToList());
}
}
在DefaultServices中有如下一句代码:SetMultiple<IFilterProvider>(new ConfigurationFilterProvider(),new ActionDescriptorFilterProvider());所以我们知道filterProviders这里其实是ConfigurationFilterProvider、ActionDescriptorFilterProvider组成的一个集合。然后依次调用他们的GetFilters方法,其中ConfigurationFilterProvider中的GetFilters方法非常简单就是调用configuration.Filters属性,可见这个是一个全局的Filter,默认的configuration.Filters是没有成员的,如果我们需要注册一个自定义的全局的Filter,我们可以在WebApiConfig的Register方法中添加 config.Filters.Add(new XXX());现在我们来看看ActionDescriptorFilterProvider的GetFilters是如何实现的:
public IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
{
IEnumerable<FilterInfo>
controllerFilters =
actionDescriptor.ControllerDescriptor.GetFilters().Select(instance =>
new FilterInfo(instance, FilterScope.Controller));
IEnumerable<FilterInfo> actionFilters =
actionDescriptor.GetFilters().Select(instance => new
FilterInfo(instance, FilterScope.Action));
return controllerFilters.Concat(actionFilters);
}
这里主要是获取Controller和Action的Filter然后把他们合并成一个filter集合,Controller和Action的 filter的获取方式都一样,主要是获取他们的IFilter特性,然后通过该特性实例创建一个新的FilterInfo实例。这里的 FilterScope仍然是Global>Controller>Action,默认直接实现或者继承IFilter的有 IActionFilter、IAuthorizationFilter、IExceptionFilter\、FilterAttribute,实际开 发中主要的FilterAttribute有以下几个,
public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter
public abstract class AuthorizationFilterAttribute : FilterAttribute, IAuthorizationFilter
public class AuthorizeAttribute : AuthorizationFilterAttribute
public abstract class ExceptionFilterAttribute : FilterAttribute, IExceptionFilter
public abstract class ExceptionFilterAttribute : FilterAttribute, IExceptionFilter
现在回到HttpActionDescriptor的InitializeFilterPipeline方法中来,这里已经获取到
FilterInfo的集合,同时也调用了一个RemoveDuplicates方法来去掉重复的FilterInfo,去掉重复的原则是调用
FilterInfo的AllowMultiple属性。
现在我们回到ApiController的ExecuteAsync方法中来,已经获取到了FilterInfo集合,然后利用他们来创建一个 FilterGrouping实例,说白了就是把这些FilterInfo分成三个组,按照他们的类型分别分为IActionFilter、 IAuthorizationFilter、IExceptionFilter组。接下俩主要就是执行这些Filter,首先执行的是 authorizationFilters组中的filter,调用每个filter的ExecuteAuthorizationFilterAsync 方法,在调用完后在调用这里的continuation方法。在continuation主要负责是绑定Action参数,然后再依次 actionFilters数组中每个filter的ExecuteActionFilterAsync方法,这里的调用代码技巧句不说了,和mvc代码 一致。
总之web api的filter调用和mvc中filter调用一致。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构