首页 > 学院 > 开发设计 > 正文

ASP.NET Web API 过滤器创建、执行过程(二)

2019-11-17 01:45:22
字体:
来源:转载
供稿:网友

asp.net Web API 过滤器创建、执行过程(二)

ASP.NET Web API 过滤器创建、执行过程(二)

前言

前面一篇中讲解了过滤器执行之前的创建,通过实现IFilterPRovider注册到当前的HttpConfiguration里的服务容器中,当然默认的基础服务也是有的,并且根据这些提供程序所获得的的过滤器信息集合进行排序。本篇就会对过滤器在创建完之后所做的一系列操作进行讲解。

ASP.NET Web API 过滤器创建、执行过程(二)

FilterGrouping过滤器分组类型

FilterGrouping类型是ApiController类型中的私有类型,它的作用就如同它的命名一样,用来对过滤器集合进行分组,在上一篇中我们看到,在经过调用HttpActionDescriptor类型的GetFilterPipeline()方法之后回去获取到排序过后的过滤器信息集合Collection<FilterInfo>。下面我们看一下FilterGrouping类型定义:

示例代码1-1

    private class FilterGrouping    {        // Fields        private List<IActionFilter> _actionFilters = new List<IActionFilter>();        private List<IAuthorizationFilter> _authorizationFilters = new List<IAuthorizationFilter>();        private List<IExceptionFilter> _exceptionFilters = new List<IExceptionFilter>();        // Methods        public FilterGrouping(IEnumerable<FilterInfo> filters)        {            foreach (FilterInfo info in filters)            {                IFilter instance = info.Instance;                Categorize<IActionFilter>(instance, this._actionFilters);                Categorize<IAuthorizationFilter>(instance, this._authorizationFilters);                Categorize<IExceptionFilter>(instance, this._exceptionFilters);            }        }        private static void Categorize<T>(IFilter filter, List<T> list) where T : class        {            T item = filter as T;            if (item != null)            {                list.Add(item);            }        }        // Properties        public IEnumerable<IActionFilter> ActionFilters        {            get            {                return this._actionFilters;            }        }        public IEnumerable<IAuthorizationFilter> AuthorizationFilters        {            get            {                return this._authorizationFilters;            }        }        public IEnumerable<IExceptionFilter> ExceptionFilters        {            get            {                return this._exceptionFilters;            }        }}

在代码1-1中我们看到在FilterGrouping类型的构造函数中便会对过滤器信息集合进行分组了,当然了分组的时候是调用FilterGrouping类型中的放吧,在Categorize()方法中就是根据实例的类型来进行判断的,最后由FilterGrouping类型中的三个公共属性来表示分组过后的不同类型的过滤器集合。

过滤器执行过程

在上个篇幅中我们通过示例了解到过滤器管道的生成过程以及结果,我们就来看一下执行的过程,顺带再看下过滤器管道的结果是不是如上篇上所说的那样。

先看服务器端(Selfhost)的代码:

代码1-2

using System.Web.Http.Controllers;using System.Web.Http.Filters;using NameSpaceControllerThree;namespace SelfHost{    class Program    {        static void Main(string[] args)        {                       HttpSelfHostConfiguration selfHostConfiguration =                new HttpSelfHostConfiguration("http://localhost/selfhost");            using (HttpSelfHostServer selfHostServer = new HttpSelfHostServer(selfHostConfiguration))            {                selfHostServer.Configuration.Routes.MapHttpRoute(                    "DefaultApi", "api/{controller}/{id}", new { id = RouteParameter.Optional });                selfHostServer.Configuration.Services.Replace(typeof(IAssembliesResolver),                    new CustomAssembliesResolver.LoadSpecifiedAssembliesResolver());                //添加全局过滤器                selfHostServer.Configuration.Filters.Add(new WebAPIController.Filter.CustomConfigurationActionFilterAttribute());                selfHostServer.OpenAsync();                Console.WriteLine("服务器端服务监听已开启");                Console.Read();            }        }    }} 

这里只有一个添加全局行为过滤器的这么一句代码,其余的部分就不解释了。

然后我们接着看控制器部分,如下示例代码:

代码1-3

namespace NameSpaceControllerThree{    [CustomControllerAuthorizationFilter]    [CustomControllerActionFilter]    public class WriterAndReadController : ApiController    {        [CustomActionFilter]        [CustomControllerActionAuthorizationFilter]        public string Get()        {            StringBuilder strBuilder = new StringBuilder();            HttpActionDescriptor actionDescriptor = this.Configuration.Services.GetActionSelector().SelectAction(this.ControllerContext);            System.Collections.ObjectModel.Collection<FilterInfo> filtersInfo = actionDescriptor.GetFilterPipeline();            foreach (var filter in filtersInfo)            {                strBuilder.AppendLine("【FilterName:"+filter.Instance.GetType().Name+",FilterScope:"+filter.Scope.ToString()+"】");            }            return strBuilder.ToString();        }    }}

对于上一篇,这里的修改只是在控制器类型和控制器方法上各自新增了一个授权过滤器,下面我们就来看一下过滤器的定义,如下示例代码:

代码1-4

/// <summary>    /// 全局的行为过滤器    /// </summary>    public class CustomConfigurationActionFilterAttribute : FilterAttribute, IActionFilter    {        public Task<System.Net.Http.HttpResponseMessage> ExecuteActionFilterAsync(System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken, Func<Task<System.Net.Http.HttpResponseMessage>> continuation)        {            Console.WriteLine(this.GetType().Name);            return continuation();        }    }    /// <summary>    /// 控制器级行为过滤器    /// </summary>    public class CustomControllerActionFilterAttribute : FilterAttribute, IActionFilter    {        public Task<System.Net.Http.HttpResponseMessage> ExecuteActionFilterAsync(System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken, Func<Task<System.Net.Http.HttpResponseMessage>> continuation)        {            Console.WriteLine(this.GetType().Name);            return continuation();        }    }    /// <summary>    /// 控制器方法级行为过滤器    /// </summary>    public class CustomActionFilterAttribute : FilterAttribute, IActionFilter    {        public Task<System.Net.Http.HttpResponseMessage> ExecuteActionFilterAsync(System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken, Func<Task<System.Net.Http.HttpResponseMessage>> continuation)        {            Console.WriteLine(this.GetType().Name);            return continuation();        }    }    /// <summary>    /// 控制器级授权访问过滤器    /// </summary>    public class CustomControllerAuthorizationFilterAttribute : FilterAttribute, IAuthorizationFilter    {        public Task<System.Net.Http.HttpResponseMessage> ExecuteAuthorizationFilterAsync(System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken, Func<Task<System.Net.Http.HttpResponseMessage>> continuation)        {            Console.WriteLine(this.GetType().Name);            return continuation();        }    }    /// <summary>    /// 控制器方法级授权访问过滤器    /// </summary>    public class CustomControllerActionAuthorizationFilterAttribute : FilterAttribute, IAuthorizationFilter    {        public Task<System.Net.Http.HttpResponseMessage> ExecuteAuthorizationFilterAsync(System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken, Func<Task<System.Net.Http.HttpResponseMessage>> continuation)        {            Console.WriteLine(this.GetType().Name);            return continuation();        }}

在代码1-4中,我们可以看到代码1-3中所有使用到的过滤器类型和代码1-2中添加全局过滤器类型。

现在我们看一下最后的结果

图1

黑色框的结果为SelfHost服务器端过滤器执行过程的输出,在代码1-4中我们可以看到,这个得出的一个结论是授权过滤器不管是什么应用范围的都是优于行为过滤器的,而在同一种类型的过滤器中是根据应用范围来确定执行顺序的,这个跟下面的浏览器里的内容有点关系,浏览器里显示的就是所有过滤器在排序后的管道里的样子,可以看到管道里单纯的就是按照应用范围的级别来排序的,至于这个过滤器是什么类型在处理排序的时候则是一点都不关心的。

过滤器执行过程-代码分析

首先看一下如下示意图,可以代表了在控制器执行的过程中过滤器的执行过程。

图2

上面通过示例来说明了过滤器的执行过程,现在我们来看一下在框架的源码中是什么样的,因为在过滤器执行过程中还包含了其它方面的知识点,所以这个是迟早都要看的,下面我们就来看一下吧。

代码1-5

     return InvokeAction
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表