当前位置:首页 > C# > 正文

深入理解 ASP.NET Core 资源过滤器(ResourceFilter)

在 ASP.NET Core 开发中,资源过滤器(ResourceFilter) 是一种非常强大的过滤器类型,它允许我们在控制器方法执行之前或之后拦截请求。对于想要控制整个请求生命周期、实现缓存、权限验证等高级功能的开发者来说,掌握资源过滤器是必不可少的技能。

深入理解 ASP.NET Core 资源过滤器(ResourceFilter)  资源过滤器 ResourceFilter 中间件 第1张

什么是资源过滤器?

在 ASP.NET Core 的过滤器管道中,资源过滤器位于最外层,比授权过滤器、操作过滤器更早执行。它有两个关键方法:

  • OnResourceExecuting:在控制器方法执行前调用
  • OnResourceExecuted:在控制器方法执行后调用

这意味着你可以用它来完全短路(short-circuit)后续的处理流程,比如直接返回缓存结果而不进入控制器。

为什么使用资源过滤器?

相比其他过滤器(如 ActionFilter),资源过滤器具有以下优势:

  • 可以访问完整的 HttpContext
  • 能提前终止请求(例如返回缓存响应)
  • 适用于需要对整个资源(包括模型绑定、参数解析等)进行控制的场景

实战:创建一个简单的资源过滤器

下面我们将创建一个记录请求时间的日志型资源过滤器,帮助你理解其基本用法。

步骤 1:定义资源过滤器类

using Microsoft.AspNetCore.Mvc.Filters;using System.Diagnostics;public class TimingResourceFilter : IResourceFilter{    private readonly Stopwatch _stopwatch = new Stopwatch();    public void OnResourceExecuting(ResourceExecutingContext context)    {        // 请求开始时启动计时器        _stopwatch.Start();        Console.WriteLine($"[ResourceFilter] 请求开始: {context.HttpContext.Request.Path}");    }    public void OnResourceExecuted(ResourceExecutedContext context)    {        // 请求结束时停止计时器并输出耗时        _stopwatch.Stop();        Console.WriteLine($"[ResourceFilter] 请求结束,耗时: {_stopwatch.ElapsedMilliseconds} ms");    }}

步骤 2:注册过滤器

你可以在 Program.cs 中全局注册,也可以通过特性(Attribute)方式局部使用。

方式一:全局注册(适用于所有请求)

// Program.csvar builder = WebApplication.CreateBuilder(args);builder.Services.AddControllers(options =>{    options.Filters.Add<TimingResourceFilter>();});var app = builder.Build();app.MapControllers();app.Run();

方式二:作为特性使用(仅用于特定控制器或方法)

[ServiceFilter(typeof(TimingResourceFilter))][ApiController][Route("[controller]")]public class WeatherForecastController : ControllerBase{    // 控制器方法}

注意:如果使用 ServiceFilter,还需要在 DI 容器中注册该过滤器:

builder.Services.AddScoped<TimingResourceFilter>();

高级技巧:短路请求(Short-Circuiting)

资源过滤器的强大之处在于它可以完全跳过控制器的执行。例如,实现一个简单的缓存机制:

public class CacheResourceFilter : IResourceFilter{    private static readonly Dictionary<string, (byte[] content, DateTime expiry)> _cache = new();    public void OnResourceExecuting(ResourceExecutingContext context)    {        var key = context.HttpContext.Request.Path;        if (_cache.TryGetValue(key, out var cached) && DateTime.Now < cached.expiry)        {            // 直接返回缓存内容,不再执行控制器            context.Result = new FileContentResult(cached.content, "application/json");        }    }    public void OnResourceExecuted(ResourceExecutedContext context)    {        // 这里可以将新生成的内容写入缓存        if (context.Result is ObjectResult objectResult)        {            // 简化示例:实际应序列化为 JSON 字节数组            var jsonBytes = System.Text.Encoding.UTF8.GetBytes("{\"cached\":true}");            _cache[context.HttpContext.Request.Path] = (jsonBytes, DateTime.Now.AddMinutes(5));        }    }}

资源过滤器 vs 中间件

很多初学者会混淆 资源过滤器中间件(Middleware)。它们的关键区别在于:

特性 中间件 资源过滤器
作用范围 全局(整个应用) 可全局/控制器/方法级
依赖注入 构造函数注入 支持服务作用域(Scoped)
访问 MVC 上下文 不能直接访问 可访问 ActionDescriptor、路由数据等

总结

通过本教程,你应该已经掌握了 ASP.NET Core 资源过滤器(ResourceFilter) 的基本概念、创建方法和典型应用场景。无论是用于日志记录、性能监控还是请求缓存,资源过滤器都是你工具箱中不可或缺的一部分。

记住,合理使用 资源过滤器中间件 和其他过滤器类型,能让你的 ASP.NET Core 应用更加灵活、高效和可维护。

关键词:ASP.NET Core, 资源过滤器, ResourceFilter, 中间件