ASP.NET Core中的行动过滤器是过滤器管道的重要组成部分,它能够在控制器中的行动方法执行前后运行自定义逻辑,适合处理与具体业务动作相关的通用需求,比如接口权限校验、请求参数预处理、操作日志记录等场景。

行动过滤器的核心概念
行动过滤器需要实现IActionFilter接口或者IAsyncActionFilter接口,前者用于同步场景,后者用于异步场景。两个接口的核心方法如下:
OnActionExecuting:在行动方法执行之前调用,可以修改传入参数、短路请求返回自定义结果OnActionExecuted:在行动方法执行之后调用,可以获取行动方法的返回值、处理执行过程中的异常OnActionExecutionAsync:异步版本的过滤器入口,通过ActionExecutionDelegate控制后续流程的执行
同步行动过滤器实现示例
下面实现一个记录行动方法执行耗时的同步过滤器:
using Microsoft.AspNetCore.Mvc.Filters;
using System.Diagnostics;
// 定义同步行动过滤器
public class ExecutionTimeActionFilter : IActionFilter
{
private Stopwatch _stopwatch;
// 行动方法执行前触发
public void OnActionExecuting(ActionExecutingContext context)
{
_stopwatch = Stopwatch.StartNew();
// 可以在这里校验参数,比如判断必填参数是否存在
if (!context.ActionArguments.ContainsKey("id"))
{
context.Result = new Microsoft.AspNetCore.Mvc.BadRequestObjectResult("缺少必填参数id");
}
}
// 行动方法执行后触发
public void OnActionExecuted(ActionExecutedContext context)
{
_stopwatch.Stop();
var controllerName = context.Controller.GetType().Name;
var actionName = context.ActionDescriptor.DisplayName;
var executionTime = _stopwatch.ElapsedMilliseconds;
// 这里可以将日志写入文件或者日志系统
System.Console.WriteLine($"控制器{controllerName}的行动{actionName}执行耗时:{executionTime}毫秒");
}
}
异步行动过滤器实现示例
如果需要在过滤器中执行异步操作(比如调用异步的权限校验接口),可以使用IAsyncActionFilter接口:
using Microsoft.AspNetCore.Mvc.Filters;
using System.Threading.Tasks;
// 定义异步行动过滤器
public class AsyncPermissionActionFilter : IAsyncActionFilter
{
// 异步执行入口
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
// 执行前的逻辑:校验用户权限
var userId = context.HttpContext.User.FindFirst("UserId")?.Value;
if (string.IsNullOrEmpty(userId))
{
context.Result = new Microsoft.AspNetCore.Mvc.UnauthorizedObjectResult("用户未登录");
return;
}
// 调用next执行后续过滤器管道和行动方法
var executedContext = await next();
// 执行后的逻辑:处理行动方法返回的结果
if (executedContext.Exception != null)
{
// 记录异常信息,不抛出避免影响上层处理
System.Console.WriteLine($"行动执行异常:{executedContext.Exception.Message}");
}
}
}
行动过滤器的注册方式
定义好过滤器之后,需要将其注册到ASP.NET Core的管道中才能生效,常见的注册方式有三种:
1. 全局注册
在Program.cs中全局注册,所有控制器的行动方法都会生效:
var builder = WebApplication.CreateBuilder(args);
// 全局注册行动过滤器
builder.Services.AddControllers(options =>
{
options.Filters.Add<ExecutionTimeActionFilter>();
options.Filters.Add<AsyncPermissionActionFilter>();
});
var app = builder.Build();
app.MapControllers();
app.Run();
2. 控制器级别注册
在控制器类上添加ServiceFilter或者TypeFilter特性,该控制器下的所有行动方法都会生效:
using Microsoft.AspNetCore.Mvc;
// 控制器级别注册,该控制器下所有行动都会应用过滤器
[ServiceFilter(typeof(ExecutionTimeActionFilter))]
[ApiController]
[Route("api/[controller]")]
public class UserController : ControllerBase
{
[HttpGet("{id}")]
public string GetUser(int id)
{
return $"用户ID:{id}";
}
}
注意使用ServiceFilter需要先确保过滤器已经在依赖注入容器中注册,也可以在Program.cs中添加:
// 注册过滤器到依赖注入容器 builder.Services.AddScoped<ExecutionTimeActionFilter>(); builder.Services.AddScoped<AsyncPermissionActionFilter>();
3. 行动方法级别注册
直接在具体的行动方法上添加特性,只有该方法会生效:
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class OrderController : ControllerBase
{
// 仅该方法应用过滤器
[ServiceFilter(typeof(ExecutionTimeActionFilter))]
[HttpPost]
public string CreateOrder([FromBody] object orderInfo)
{
return "订单创建成功";
}
[HttpGet]
public string GetOrderList()
{
return "订单列表";
}
}
行动过滤器与中间件的区别
很多开发者会混淆行动过滤器和中间件的作用,两者的核心区别如下:
| 对比项 | 行动过滤器 | 中间件 |
|---|---|---|
| 作用范围 | 仅作用于MVC/Web API的行动方法层面 | 作用于所有进入应用的请求 |
| 上下文信息 | 可以获取控制器、行动方法、参数、路由等MVC相关信息 | 只能获取HttpContext的基础信息,无法感知MVC相关细节 |
| 适用场景 | 业务相关的通用逻辑,比如参数校验、接口权限、操作日志 | 通用请求处理,比如跨域、静态文件、全局异常处理 |
依赖注入在过滤器中的使用
行动过滤器支持依赖注入,可以在构造函数中注入需要的服务,比如日志服务、配置服务等:
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
public class LogActionFilter : IActionFilter
{
private readonly ILogger<LogActionFilter> _logger;
// 注入日志服务
public LogActionFilter(ILogger<LogActionFilter> logger)
{
_logger = logger;
}
public void OnActionExecuting(ActionExecutingContext context)
{
_logger.LogInformation("行动方法开始执行,参数:{Arguments}", context.ActionArguments);
}
public void OnActionExecuted(ActionExecutedContext context)
{
_logger.LogInformation("行动方法执行结束,结果:{Result}", context.Result);
}
}
注册该过滤器时同样需要将其添加到依赖注入容器:
builder.Services.AddScoped<LogActionFilter>();
ASP.NET_CoreAction_Filter依赖注入过滤器管道中间件修改时间:2026-07-24 11:30:33