在C#的ASP.NET Core应用开发中,过滤器Filter是处理请求横切关注点的核心组件,它可以在请求处理的不同阶段插入自定义逻辑,比如权限校验、日志记录、异常处理等,不需要把这些逻辑分散到各个业务接口中。
C#过滤器Filter的基础使用
过滤器的常见类型
ASP.NET Core中内置了多种类型的过滤器,每种过滤器的执行时机和作用不同,常见的类型如下:
- 授权过滤器(Authorization Filter):在请求处理的最早阶段执行,用于判断请求是否具备访问权限,未通过授权会直接返回错误响应。
- 资源过滤器(Resource Filter):在授权过滤器之后、模型绑定之前执行,也可以短路请求直接返回结果,适合做缓存处理。
- 操作过滤器(Action Filter):在模型绑定完成之后、执行控制器方法前后执行,可以修改传入的参数或者返回的结果。
- 异常过滤器(Exception Filter):在请求处理过程中出现异常时执行,用于统一捕获和处理异常,返回友好的错误响应。
- 结果过滤器(Result Filter):在执行控制器方法返回结果之后、结果写入响应之前执行,可以修改最终返回给客户端的内容。
自定义过滤器示例
我们可以通过实现对应的接口来自定义过滤器,下面以操作过滤器为例,实现一个记录接口执行耗时的过滤器:
using Microsoft.AspNetCore.Mvc.Filters;
using System.Diagnostics;
public class ExecutionTimeFilter : IActionFilter
{
private Stopwatch _stopwatch;
// 在控制器方法执行前调用
public void OnActionExecuting(ActionExecutingContext context)
{
_stopwatch = Stopwatch.StartNew();
}
// 在控制器方法执行后调用
public void OnActionExecuted(ActionExecutedContext context)
{
_stopwatch.Stop();
var controllerName = context.RouteData.Values["controller"];
var actionName = context.RouteData.Values["action"];
// 记录接口执行耗时,实际开发中可替换为日志写入逻辑
Console.WriteLine($"控制器{controllerName}的{actionName}方法执行耗时:{_stopwatch.ElapsedMilliseconds}毫秒");
}
}
过滤器的注册方式
自定义好过滤器之后,需要注册到应用中才能生效,常见的注册方式有两种:
- 全局注册:在Program.cs中通过
AddControllers的配置添加,会对所有接口生效:
var builder = WebApplication.CreateBuilder(args);
// 全局注册ExecutionTimeFilter
builder.Services.AddControllers(options =>
{
options.Filters.Add<ExecutionTimeFilter>();
});
var app = builder.Build();
app.MapControllers();
app.Run();
- 局部注册:通过特性标注在控制器或者具体的接口方法上,仅对标注的目标生效:
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class TestController : ControllerBase
{
// 仅这个接口会生效ExecutionTimeFilter
[HttpGet("test")]
[TypeFilter(typeof(ExecutionTimeFilter))]
public string Test()
{
return "测试接口";
}
[HttpGet("other")]
public string Other()
{
return "其他接口";
}
}
C#过滤器Filter的底层原理
过滤器在请求管道中的位置
要理解Filter的底层原理,首先要明确它在ASP.NET Core请求管道中的执行位置。请求管道是由一系列中间件组成的,当请求到达应用后,会依次经过各个中间件处理。Filter并不属于中间件层,而是在中间件将请求路由到对应的控制器之后,由ASP.NET Core的过滤器管道来触发执行。
完整的请求执行顺序大致如下:
- 请求进入中间件管道,依次经过各个中间件处理。
- 路由中间件匹配到对应的控制器和接口方法。
- 授权过滤器执行,校验请求权限。
- 资源过滤器执行,可进行缓存等前置处理。
- 模型绑定完成,操作过滤器的
OnActionExecuting方法执行。 - 控制器方法执行,返回结果。
- 操作过滤器的
OnActionExecuted方法执行。 - 结果过滤器执行,处理返回结果。
- 资源过滤器的后置方法执行。
- 响应经过中间件管道返回给客户端。
- 如果过程中出现未处理的异常,异常过滤器会捕获并处理。
过滤器的执行机制
ASP.NET Core在启动时,会扫描所有注册的过滤器,将它们按照类型和执行顺序排序,形成一个过滤器管道。当请求匹配到对应的接口时,框架会依次实例化过滤器,并按照排序顺序执行对应的方法。
过滤器的实例化默认是由依赖注入容器管理的,所以如果过滤器需要依赖其他服务,只需要在构造函数中声明即可,比如下面的过滤器依赖了日志服务:
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
public class LogFilter : IActionFilter
{
private readonly ILogger<LogFilter> _logger;
// 通过依赖注入获取日志服务
public LogFilter(ILogger<LogFilter> logger)
{
_logger = logger;
}
public void OnActionExecuting(ActionExecutingContext context)
{
_logger.LogInformation("接口开始执行");
}
public void OnActionExecuted(ActionExecutedContext context)
{
_logger.LogInformation("接口执行结束");
}
}
过滤器与中间件的区别
很多开发者会混淆过滤器和中间件的作用,两者的核心区别如下:
| 对比项 | 中间件 | 过滤器Filter |
|---|---|---|
| 作用范围 | 全局所有请求,不管是否匹配到路由 | 仅匹配到控制器/接口的请求 |
| 执行时机 | 请求处理的最外层管道 | 路由匹配之后,控制器执行前后 |
| 依赖注入支持 | 构造函数注入,生命周期由容器管理 | 支持依赖注入,生命周期由容器管理 |
| 适用场景 | 跨请求的横切逻辑,比如请求日志、跨域处理、静态文件处理 | 和业务相关的横切逻辑,比如接口权限、接口参数校验、接口结果处理 |
过滤器的常见问题与注意事项
在使用过滤器时,需要注意几个常见问题:
- 过滤器如果抛出了未处理的异常,会被异常过滤器捕获,如果没有配置异常过滤器,会导致请求返回500错误。
- 全局注册的过滤器和局部注册的过滤器都会生效,执行顺序默认是全局过滤器先执行,局部过滤器后执行,也可以通过设置
Order属性调整顺序。 - 使用
TypeFilter特性注册过滤器时,框架会自动通过依赖注入创建过滤器实例,如果使用ServiceFilter特性,需要先将过滤器注册到依赖注入容器,否则会报错。
通过上面的内容,我们不仅掌握了C#中过滤器Filter的基础使用方法,也理解了它的底层执行逻辑和设计思路,在实际开发中可以根据需求选择合适的过滤器类型,合理配置过滤器的执行顺序和注册方式,让代码更加简洁易维护。
C#_FilterASP.NET_Core中间件请求管道依赖注入修改时间:2026-06-22 14:13:10