博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ASP.NET Core 2 学习笔记(十四)Filters
阅读量:6516 次
发布时间:2019-06-24

本文共 8280 字,大约阅读时间需要 27 分钟。

原文:

Filter是延续ASP.NET MVC的产物,同样保留了五种的Filter,分别是Authorization FilterResource FilterAction FilterException FilterResult Filter

通过不同的Filter可以有效处理封包进出的加工,本篇将介绍ASP.NET Core的五种Filter运作方式。

Filter 介绍

Filter的作用是在Action 执行前或执行后做一些加工处理。

某种程度来看,会跟Middleware很像,但执行的顺序略有不同,用对Filter不仅可以减少代码,还可以提高执行效率。

ASP.NET Core 有以下五种Filter 可以使用:

  • Authorization Filter
    Authorization是五种Filter中优先级最高的,通常用于验证Request合不合法,不合法后面就直接跳过。
  • Resource Filter
    Resource是第二优先,会在Authorization之后,Model Binding之前执行。通常会是需要对Model加工处理才用。
  • Action Filter
    最常使用的Filter,封包进出都会经过它,使用上没什么需要特别注意的。跟Resource Filter很类似,但并不会经过Model Binding。
  • Exception Filter
    异常处理的Filter。
  • Result Filter
    当Action完成后,最终会经过的Filter。

Filter 运作方式

ASP.NET Core的每个Request都会先经过已注册的Middleware接着才会执行Filter,除了会依照上述的顺序外,同类型的Filter预设都会以先进后出的方式处里封包。

Response在某些Filter并不会做处理,会直接被pass。Request及Response的运作流程如下图:

  • 黄色箭头是正常情况流程
  • 灰色箭头是异常处理流程

建立Filter

ASP.NET Core的Filter基本上跟ASP.NET MVC的差不多。

上述的五种Filter范例分别如下:

Authorization Filter

AuthorizationFilter.cs

using Microsoft.AspNetCore.Http;using Microsoft.AspNetCore.Mvc.Filters;namespace MyWebsite.Filters{    public class AuthorizationFilter : IAuthorizationFilter    {        public void OnAuthorization(AuthorizationFilterContext context)        {            context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");        }    }}

非同步的方式:

// ...public class AuthorizationFilter : IAsyncAuthorizationFilter{    public async Task OnAuthorizationAsync(AuthorizationFilterContext context)    {        await context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");    }}

Resource Filter

ResourceFilter.cs

using Microsoft.AspNetCore.Http;using Microsoft.AspNetCore.Mvc.Filters;namespace MyWebsite.Filters{    public class ResourceFilter : IResourceFilter    {        public void OnResourceExecuting(ResourceExecutingContext context)        {            context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");        }        public void OnResourceExecuted(ResourceExecutedContext context)        {            context.HttpContext.Response.WriteAsync($"{GetType().Name} out. \r\n");        }    }}

非同步的方式:

// ...public class ResourceFilter : IAsyncResourceFilter{    public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)    {        await context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");        await next();        await context.HttpContext.Response.WriteAsync($"{GetType().Name} out. \r\n");    }}

Action Filter

ActionFilter.cs

using Microsoft.AspNetCore.Http;using Microsoft.AspNetCore.Mvc.Filters;namespace MyWebsite.Filters{    public class ActionFilter : IActionFilter    {        public void OnActionExecuting(ActionExecutingContext context)        {            context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");        }        public void OnActionExecuted(ActionExecutedContext context)        {            context.HttpContext.Response.WriteAsync($"{GetType().Name} out. \r\n");        }    }}

非同步的方式:

// ...public class ActionFilter : IAsyncActionFilter{    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)    {        await context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");        await next();        await context.HttpContext.Response.WriteAsync($"{GetType().Name} out. \r\n");    }}

Result Filter

ResultFilter.cs

using Microsoft.AspNetCore.Http;using Microsoft.AspNetCore.Mvc.Filters;namespace MyWebsite.Filters{    public class ResultFilter : IResultFilter    {        public void OnResultExecuting(ResultExecutingContext context)        {            context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");        }        public void OnResultExecuted(ResultExecutedContext context)        {            context.HttpContext.Response.WriteAsync($"{GetType().Name} out. \r\n");        }    }}

非同步的方式:

// ...public class ResultFilter : IAsyncResultFilter{    public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)    {        await context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");        await next();        await context.HttpContext.Response.WriteAsync($"{GetType().Name} out. \r\n");    }}

Exception Filter

ExceptionFilter.cs

using Microsoft.AspNetCore.Http;using Microsoft.AspNetCore.Mvc.Filters;namespace MyWebsite.Filters{    public class ExceptionFilter : IExceptionFilter    {        public void OnException(ExceptionContext context)        {            context.ExceptionHandled = true; // 表明异常已处理,客户端可得到正常返回            context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");        }    }}

非同步的方式:

// ...public class ExceptionFilter : IAsyncExceptionFilter{        public Task OnExceptionAsync(ExceptionContext context)        {            context.ExceptionHandled = true;// 表明异常已处理,客户端可得到正常返回            context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");            return Task.CompletedTask;        }}

注册Filter

Filter有两种注册方式,一种是全局注册,另一种是用[Attribute]局部注册的方式,只套用在特定的Controller或Action。

全局注册

Startup.ConfigureServices的MVC服务中注册Filter,这样就可以套用到所有的Request。如下:

// ...public class Startup{    public void ConfigureServices(IServiceCollection services)    {        services.AddMvc(config =>        {            config.Filters.Add(new ResultFilter());            config.Filters.Add(new ExceptionFilter());            config.Filters.Add(new ResourceFilter());        });    }}

局部注册

ASP.NET Core在局部注册Filter的方式跟ASP.NET MVC有一点不一样,要通过[TypeFilter(type)]

在Controller或Action上面加上[TypeFilter(type)]就可以局部注册Filter。如下:

// ...namespace MyWebsite.Controllers{    [TypeFilter(typeof(AuthorizationFilter))]    public class HomeController : Controller    {        [TypeFilter(typeof(ActionFilter))]        public void Index()        {            Response.WriteAsync("Hello World! \r\n");        }                [TypeFilter(typeof(ActionFilter))]        public void Error()        {            throw new System.Exception("Error");        }    }}

[TypeFilter(type)]用起来有点冗长,想要像过去ASP.NET MVC用[Attribute]注册Filter的话,只要将Filter继承Attribute即可。如下:

public class AuthorizationFilter : Attribute, IAuthorizationFilter{    // ...}public class ActionFilter : Attribute, IActionFilter{    // ...}

[Attribute] 注册就可以改成如下方式:

// ...namespace MyWebsite.Controllers{    [AuthorizationFilter]    public class HomeController : Controller    {        [ActionFilter]        public void Index()        {            Response.WriteAsync("Hello World! \r\n");        }                [ActionFilter]        public void Error()        {            throw new System.Exception("Error");        }    }}

执行结果

http://localhost:5000/Home/Index 输出结果如下:

AuthorizationFilter in.ResourceFilter in.ActionFilter in.Hello World!ActionFilter out.ResultFilter in.ResultFilter out.ResourceFilter out.

http://localhost:5000/Home/Error 输出结果如下:

AuthorizationFilter in.ResourceFilter in.ActionFilter in.ActionFilter out.ExceptionFilter in.ResourceFilter out.

执行顺序

预设注册同类型的Filter 是以先进后出的方式处里封包,注册层级也会影响执行顺序。

但也可以通过实现 IOrderedFilter 更改执行顺序。例如:

public class ActionFilter : Attribute, IActionFilter, IOrderedFilter{    public string Name { get; set; }    public int Order { get; set; } = 0;    public void OnActionExecuting(ActionExecutingContext context)    {        context.HttpContext.Response.WriteAsync($"{GetType().Name}({Name}) in. \r\n");    }    public void OnActionExecuted(ActionExecutedContext context)    {        context.HttpContext.Response.WriteAsync($"{GetType().Name}({Name}) out. \r\n");    }}

在注册Filter 时带上Order,数值越小优先权越高。

// ...public class Startup{    public void ConfigureServices(IServiceCollection services)    {        services.AddMvc(config =>        {            config.Filters.Add(new ActionFilter() { Name = "Global", Order = 3 });        });    }}
// ...namespace MyWebsite.Controllers{    [ActionFilter(Name = "Controller", Order = 2)]    public class HomeController : Controller    {        [ActionFilter(Name = "Action", Order = 1)]        public void Index()        {            Response.WriteAsync("Hello World! \r\n");        }    }}

变更执行顺序后的输出内容:

ActionFilter(Action) in. ActionFilter(Controller) in. ActionFilter(Global) in. Hello World! ActionFilter(Global) out. ActionFilter(Controller) out. ActionFilter(Action) out.

参考

 

老司机发车啦:  

转载地址:http://wdofo.baihongyu.com/

你可能感兴趣的文章
数据库设计 Step by Step (6) —— 提取业务规则
查看>>
Redis客户端redisson实战
查看>>
连接到 JasperReports Server
查看>>
java处理高并发高负载类网站问题
查看>>
使用C#生成随机密码(纯数字或字母)和随机卡号(数字与字母组合)
查看>>
CAS服务器端集群
查看>>
JAVA Collections框架
查看>>
进制转换
查看>>
ASCII码
查看>>
java常用四种排序源代码
查看>>
win7 下硬盘安装Redhat7
查看>>
Redis 分布式锁的正确实现方式
查看>>
mysqldump 备份命令使用中的一些经验总结
查看>>
程序猿知道英语词汇
查看>>
数据存储(两)--SAX发动机XML记忆(附Demo)
查看>>
谈谈SQL 语句的优化技术
查看>>
ecshop如何判断缓存文件是否能更新
查看>>
javascript于boolean类型转换,运营商&&和|| 返回值
查看>>
深入分析面向对象中的封装作用
查看>>
深刻理解Python中的元类(metaclass)
查看>>