在ASP.NET Core中,筛选器(Filter)是一种强大的机制,用于在请求处理管道的特定阶段之前或之后执行代码,通过使用筛选器,开发者可以在不修改控制器代码的情况下,添加诸如授权、日志记录、缓存和异常处理等横切关注点的功能,下面将详细介绍ASP.NET Core中的筛选器及其使用方法。
筛选器在ASP.NET Core操作调用管道(有时称为筛选器管道)内运行,这个管道在选择要执行的操作之后开始运行,筛选器分为不同的类型,每种类型在管道的不同阶段执行。
1、授权筛选器(AuthorizationFilter):最先运行,用于确定是否已针对请求为用户授权,如果请求未获授权,授权筛选器可以让管道短路。
2、资源筛选器(ResourceFilter):在授权后运行。OnResourceExecuting
在筛选器管道的其余阶段之前运行代码,例如在模型绑定之前;OnResourceExecuted
在管道的其余阶段完成之后运行代码。
3、操作筛选器(ActionFilter):在调用操作方法之前和之后立即运行代码,可以更改传递到操作中的参数,也可以更改从操作返回的结果,不可在Razor Pages中使用。
4、异常筛选器(ExceptionFilter):在向响应正文写入任何内容之前,对未经处理的异常应用全局策略。
5、结果筛选器(ResultFilter):在执行操作结果之前和之后立即运行代码,仅当操作方法成功执行时,它们才会运行,对于必须围绕视图或格式化程序的执行的逻辑,它们很有用。
筛选器通过实现不同的接口来定义,支持同步和异步实现,同步筛选器在其管道阶段之前和之后运行代码,而异步筛选器则定义了OnStageExecutionAsync
方法。
同步筛选器:实现如IActionFilter
、IResultFilter
等接口。
异步筛选器:实现如IAsyncActionFilter
、IAsyncResultFilter
等接口。
ASP.NET Core包含许多可子类化和自定义的基于属性的内置筛选器,以下结果筛选器会向响应添加标头:
public class AddHeaderAttribute : ResultFilterAttribute { private readonly string _name; private readonly string _value; public AddHeaderAttribute(string name, string value) { _name = name; _value = value; } public override void OnResultExecuting(ResultExecutingContext context) { context.HttpContext.Response.Headers.Add(_name, new string[] { _value }); base.OnResultExecuting(context); } }
通过使用属性,筛选器可接收参数,如前面的示例所示,将AddHeaderAttribute
添加到控制器或操作方法,并指定HTTP标头的名称和值。
以下是一个简单的示例,展示如何在ASP.NET Core中使用操作筛选器:
public class FcbActionFilterAttribute : ActionFilterAttribute { private string _msg { get; set; } public FcbActionFilterAttribute(string msg) { _msg = msg; } public override void OnActionExecuting(ActionExecutingContext context) { Console.WriteLine("方法过滤之前"); } public override void OnActionExecuted(ActionExecutedContext context) { Console.WriteLine("方法过滤之后"); } public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { IConfiguration configuration = context.HttpContext.RequestServices.GetService(typeof(IConfiguration)) as IConfiguration; context.HttpContext.Request.Headers.Add(configuration.GetSection("admin").Value, _msg); Console.WriteLine("异步方法过滤之前"); var resultContext = await next(); Console.WriteLine("异步方法过滤之后"); } public override void OnResultExecuting(ResultExecutingContext context) { Console.WriteLine("结果过滤之前"); } public override void OnResultExecuted(ResultExecutedContext context) { Console.WriteLine("结果过滤之后"); } public override async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next) { Console.WriteLine("异步结果过滤之前"); var resultContext = await next(); Console.WriteLine("异步结果过滤之后"); } }
使用该筛选器:
[FcbActionFilter("hello")] [HttpGet("api/{controller}/{action}/{id?}")] public IActionResult test() { Console.WriteLine("执行方法体"); return Ok(HttpContext.Request.Headers.FirstOrDefault(x => x.Key == _configuration.GetSection("admin").Value).Value); }
执行顺序为:OnActionExecuting
->OnActionExecuted
->Controller(构造函数)
->OnActionExecutionAsync
->test
方法体 ->OnResultExecutionAsync
->OnResultExecuted
。
Q1: 筛选器能否在Razor Pages中使用?
A1: 不可以,筛选器无法直接与Razor组件一起使用,但可以通过间接方式影响组件,比如组件嵌入在页面或视图中,且页面或控制器和视图使用了此筛选器。
Q2: 如何注册自定义筛选器?
A2: 可以通过在Startup.cs
或Program.cs
文件中配置MVC选项来注册全局筛选器。
builder.Services.Configure<MvcOptions>(options => { options.Filters.Add<MyCustomFilter>(); });
这将注册一个名为MyCustomFilter
的全局筛选器。