zoukankan      html  css  js  c++  java
  • 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调用一致。

  • 相关阅读:
    第4章 ZK基本特性与基于Linux的ZK客户端命令行学习 4-2 session的基本原理与create命令的使用
    第4章 ZK基本特性与基于Linux的ZK客户端命令行学习 4-1 zookeeper常用命令行操作
    3-3 zookeeper的作用体现
    3-2 zk客户端连接关闭服务端,查看znode
    Python(2.7.6) glob
    SonarQube(5.0.1) 环境的安装配置
    Maven(3.0.5) 环境的安装配置
    Linux 命令
    Linux
    Python(2.7.6) copy
  • 原文地址:https://www.cnblogs.com/majiang/p/2802782.html
Copyright © 2011-2022 走看看