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.

参考

ASP.NET Core Filters

老司机发车啦:https://github.com/SnailDev/SnailDev.NETCore2Learning

ASP.NET Core 2 学习笔记(十四)Filters的更多相关文章

  1. Asp.Net Core WebApi学习笔记(四)-- Middleware

    Asp.Net Core WebApi学习笔记(四)-- Middleware 本文记录了Asp.Net管道模型和Asp.Net Core的Middleware模型的对比,并在上一篇的基础上增加Mid ...

  2. 使用Visual Studio Code开发Asp.Net Core WebApi学习笔记(四)-- Middleware

    本文记录了Asp.Net管道模型和Asp.Net Core的Middleware模型的对比,并在上一篇的基础上增加Middleware功能支持. 在演示Middleware功能之前,先要了解一下Asp ...

  3. ASP.NET Core 2 学习笔记(四)依赖注入

    ASP.NET Core使用了大量的依赖注入(Dependency Injection, DI),把控制反转(Inversion Of Control, IoC)运用的相当巧妙.DI可算是ASP.NE ...

  4. ASP.NET Core 2 学习笔记(十)视图

    ASP.NET Core MVC中的Views是负责网页显示,将数据一并渲染至UI包含HTML.CSS等.并能痛过Razor语法在*.cshtml中写渲染画面的程序逻辑.本篇将介绍ASP.NET Co ...

  5. ASP.NET Core 2 学习笔记(十二)REST-Like API

    Restful几乎已算是API设计的标准,通过HTTP Method区分新增(Create).查询(Read).修改(Update)和删除(Delete),简称CRUD四种数据存取方式,简约又直接的风 ...

  6. ASP.NET Core 2 学习笔记(十三)Swagger

    Swagger也算是行之有年的API文件生成器,只要在API上使用C#的<summary />文件注解标签,就可以产生精美的线上文件,并且对RESTful API有良好的支持.不仅支持生成 ...

  7. sql server 关于表中只增标识问题 C# 实现自动化打开和关闭可执行文件(或 关闭停止与系统交互的可执行文件) ajaxfileupload插件上传图片功能,用MVC和aspx做后台各写了一个案例 将小写阿拉伯数字转换成大写的汉字, C# WinForm 中英文实现, 国际化实现的简单方法 ASP.NET Core 2 学习笔记(六)ASP.NET Core 2 学习笔记(三)

    sql server 关于表中只增标识问题   由于我们系统时间用的过长,数据量大,设计是采用自增ID 我们插入数据的时候把ID也写进去,我们可以采用 关闭和开启自增标识 没有关闭的时候 ,提示一下错 ...

  8. python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例

    python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例 新浪爱彩双色球开奖数据URL:http://zst.aicai.com/ssq/openInfo/ 最终输出结果格 ...

  9. ASP.NET Core 2 学习笔记(七)路由

    ASP.NET Core通过路由(Routing)设定,将定义的URL规则找到相对应行为:当使用者Request的URL满足特定规则条件时,则自动对应到相符合的行为处理.从ASP.NET就已经存在的架 ...

  10. ASP.NET Core 2 学习笔记(一)开始

    原文:ASP.NET Core 2 学习笔记(一)开始 来势汹汹的.NET Core似乎要取代.NET Framework,ASP.NET也随之发布.NET Core版本.虽然名称沿用ASP.NET, ...

随机推荐

  1. 629. K Inverse Pairs Array

    Given two integers n and k, find how many different arrays consist of numbers from 1 to n such that ...

  2. ZZNU 1719(最长上升子序列+最长下降子序列)

    先吐血一发,噗! 再吐血一次,啊啊啊啊! 好吧,做了那么多次最长上升子序列,看这题看了半天才发现还有最长下降子序列,呵呵哒! AC代码: #include<stdio.h>//老恶心#in ...

  3. day 49 数据分析, 数据聚合 F 查询 Q 查询

    6.聚合查询和分组查询 1.聚合查询aggregate 我们先通过一个例子来感受一下吧. 1 2 3 # 计算所有图书的平均价格 books = models.Book.objects.aggrega ...

  4. Eclipse启动和手动启动tomcat访问localhost:8080显示404问题总结

    前言:建议对tomcat的文件结构和相关属性有较多了解.本文以eclipse的DynamicWebProject为讲解对象. 目录: eclipse添加tomcat关联注意点 tomcat404问题归 ...

  5. Ubuntu软件更新时出错问题解决

    apt-get instal update 提示:错误,无法解析域名等等之类的 网上解决办法一大堆,先别急着用网上的方法,来检查检查系统是否有网络连接 网络图标显示网络连接,等等,别被表面迷惑了,命令 ...

  6. Swift 基本数据类型与运算符表达式

    // // main.swift // LessonSwift01 // // Created by lanouhn on 16/1/25. // Copyright © 2016年 齐彦坤. All ...

  7. 科学经得起实践检验-python3.6通过决策树实战精准准确预测今日大盘走势(含代码)

    科学经得起实践检验-python3.6通过决策树实战精准准确预测今日大盘走势(含代码) 春有百花秋有月,夏有凉风冬有雪: 若无闲事挂心头,便是人间好时节. --宋.无门慧开 不废话了,以下训练模型数据 ...

  8. 下拉菜单;手风琴;九宫格的Jquery的使用实例

    下拉菜单;手风琴;九宫格的Jquery的使用实例 1.下拉菜单 效果如图: 代码如下: <!DOCTYPE html> <html lang="en"> & ...

  9. 快速初步了解Neo4j与使用

    快速初步了解Neo4j与使用 Neo4j是一个高性能的,NOSQL图形数据库,它将结构化数据存储在网络上而不是表中.它是一个嵌入式的.基于磁盘的.具备完全的事务特性的Java持久化引擎,但是它将结构化 ...

  10. 如何在虚拟机安装的Win10系统里快速打开【此电脑】图标?(图文详解)

    不多说,直接上干货! 为什么要写写这篇博客? 技多不压身,很多小技巧很重要,方便自己. 比如,对于这样的工具,个人来讲,玩过试用期,意味着你若不找点法子,是不行的.否则你没得玩了. 全网最详细的Tab ...