本系列专栏基于杨中科老师的《ASP.NET Core技术内幕与项目实战》,本人记录梳理的学习笔记,有部分的增补和省略。更全面系统的讲解,请看杨老师的视频课:【.NET教程,.Net Core视频教程,杨中科主讲】。
一、Filter 概述
1. 概念
Filter(筛选器 / 过滤器)是 ASP.NET Core 内置的 AOP(面向切面编程)机制,允许我们在请求处理管道的特定阶段,插入自定义逻辑,而无需修改控制器、Action 的原有代码。
特点:
- 横切关注点统一处理(异常、日志、权限、缓存、事务、限流)
- 代码解耦、复用、易维护
- 不侵入业务核心逻辑
2. Filter 五大类型
ASP.NET Core 提供 5 种内置筛选器,按固定顺序执行:
3. 同步与异步 Filter
Filter 都提供同步和异步两套接口,推荐优先使用异步,避免阻塞线程。
| 行为筛选 | IActionFilter | IAsyncActionFilter |
| 异常筛选 | IExceptionFilter | IAsyncExceptionFilter |
| 资源筛选 | IResourceFilter | IAsyncResourceFilter |
| 结果筛选 | IResultFilter | IAsyncResultFilter |
二、Filter 实战
1. 异常筛选器 Exception Filter
作用:全局捕获控制器 / Action 抛出的未处理异常,统一返回格式、记录日志,避免程序崩溃。
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
/// <summary>
/// 全局异步异常筛选器
/// </summary>
public class MyExceptionFilter : IAsyncExceptionFilter
{
private readonly ILogger<MyExceptionFilter> _logger;
private readonly IHostEnvironment _env;
// 依赖注入(Filter 支持构造函数注入)
public MyExceptionFilter(ILogger<MyExceptionFilter> logger, IHostEnvironment env)
{
_logger = logger;
_env = env;
}
public Task OnExceptionAsync(ExceptionContext context)
{
// 1. 获取异常对象
Exception exception = context.Exception;
// 2. 记录错误日志(包含异常堆栈)
_logger.LogError(exception, "全局捕获到未处理异常");
// 3. 根据环境返回不同提示信息
string errorMsg = _env.IsDevelopment()
? exception.ToString()
: "服务器繁忙,请稍后重试";
// 4. 构造统一响应结果
var result = new ObjectResult(new
{
Code = 500,
Message = errorMsg,
Success = false
})
{
StatusCode = StatusCodes.Status500InternalServerError
};
// 5. 赋值给上下文,表示异常已处理
context.Result = result;
context.ExceptionHandled = true;
return Task.CompletedTask;
}
}
注册使用(Program.cs)
// 全局注册异常筛选器(所有控制器生效)
builder.Services.Configure<MvcOptions>(options =>
{
options.Filters.Add<MyExceptionFilter>();
});
2. 行为筛选器 Action Filter
作用:在 Action 方法执行前和执行后运行自定义代码。
- 执行前:参数校验、权限、限流、事务开启
- 执行后:结果包装、日志记录、事务提交
// 异步 Action 筛选器核心方法
public async Task OnActionExecutionAsync(
ActionExecutingContext context, // 执行前上下文
ActionExecutionDelegate next) // 执行 Action 的委托
{
// 1. Action 执行前逻辑
// 2. 执行 Action 方法
var executedContext = await next();
// 3. Action 执行后逻辑
}
三、Filter 执行顺序
1. 优先级
Action 上的 Filter > 控制器上的 Filter > 全局注册的 Filter
2. 多层 Filter 执行流程
以 ActionFilter 为例:
先进后出,类似栈结构 / 嵌套包裹执行
四、案例 1:自动事务 Filter(TransactionScopeFilter)
需求
对数据库操作自动开启事务,Action 无异常则提交,出现异常自动回滚,无需手动写 TransactionScope。
实现代码
步骤 1:定义忽略事务标记
/// <summary>
/// 标记 Action 不使用自动事务
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
public class NotTransactionalAttribute : Attribute
{
}
步骤 2:实现事务筛选器
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Transactions;
/// <summary>
/// 自动事务管理 Filter
/// </summary>
public class TransactionScopeFilter : IAsyncActionFilter
{
public async Task OnActionExecutionAsync(
ActionExecutingContext context,
ActionExecutionDelegate next)
{
// 1. 判断是否标记 [NotTransactional],是则跳过事务
bool isSkip = false;
if (context.ActionDescriptor is ControllerActionDescriptor actionDesc)
{
isSkip = actionDesc.MethodInfo.IsDefined(typeof(NotTransactionalAttribute), true);
}
if (isSkip)
{
await next();
return;
}
// 2. 创建异步事务范围(支持 async/await)
using var txScope = new TransactionScope(
TransactionScopeOption.Required,
TransactionScopeAsyncFlowOption.Enabled);
try
{
// 3. 执行 Action
var executedContext = await next();
// 4. 无异常则提交事务
if (executedContext.Exception == null)
{
txScope.Complete();
}
}
catch
{
// 事务会自动回滚(无需代码)
throw;
}
}
}
步骤 3:注册(Program.cs)
builder.Services.Configure<MvcOptions>(options =>
{
options.Filters.Add<TransactionScopeFilter>();
});
步骤 4:使用(控制器代码)
[HttpPost]
public async Task<string> TestTransaction(BookStoreDbContext ctx)
{
// 无需手动写 TransactionScope
// Filter 自动开启 + 提交/回滚
ctx.Books.Add(new Book { Name = "ASP.NET Core 实战", Price = 59 });
await ctx.SaveChangesAsync();
ctx.Persons.Add(new Person { Name = "张三", Age = 20 });
await ctx.SaveChangesAsync();
return "操作成功,事务已提交";
}
// 不需要事务的 Action
[HttpPost]
[NotTransactional]
public async Task<string> TestNoTransaction()
{
return "跳过自动事务";
}
五、案例 2:IP 请求限流 Filter(RateLimitFilter)
需求
同一个 IP 1 秒内最多只能请求 1 次,防止恶意刷接口。
实现代码
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Caching.Memory;
/// <summary>
/// IP 请求限流筛选器(1秒1次)
/// </summary>
public class RateLimitFilter : IAsyncActionFilter
{
private readonly IMemoryCache _memCache;
public RateLimitFilter(IMemoryCache memCache)
{
_memCache = memCache;
}
public async Task OnActionExecutionAsync(
ActionExecutingContext context,
ActionExecutionDelegate next)
{
// 1. 获取客户端 IP
string ip = context.HttpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown";
string cacheKey = $"RateLimit_{ip}";
// 2. 判断是否在冷却时间内
if (_memCache.TryGetValue(cacheKey, out _))
{
// 直接终止 Action 执行,返回 429
context.Result = new ContentResult
{
StatusCode = StatusCodes.Status429TooManyRequests,
Content = "请求过于频繁,请1秒后重试"
};
return;
}
// 3. 记录访问时间,缓存 1 秒
_memCache.Set(cacheKey, DateTime.UtcNow, TimeSpan.FromSeconds(1));
// 4. 正常执行 Action
await next();
}
}
注册使用
// 注册内存缓存
builder.Services.AddMemoryCache();
// 注册限流过滤器
builder.Services.Configure<MvcOptions>(options =>
{
options.Filters.Add<RateLimitFilter>();
});
六、Filter 三种注册方式
public class HomeController : Controller
public IActionResult Index()


