在ASP.NET Core 中,操作过滤器(Action Filters)用于在控制器的操作方法执行之前或之后执行自定义逻辑。操作过滤器主要用于在请求到达控制器方法之前进行处理(例如:验证请求参数、设置数据)、在操作执行后处理响应(例如:记录日志、修改响应结果)等。
操作过滤器的工作原理
操作过滤器可以通过实现IActionFilter
接口或继承ActionFilterAttribute
来创建。它们可以用于对操作方法的输入和输出进行拦截,在执行请求之前或之后进行特定操作。
操作过滤器的执行时机是:
- 执行前:在控制器操作方法执行之前。
- 执行后:在控制器操作方法执行之后,但在返回结果给客户端之前。
操作过滤器的实现方式
1. 使用IActionFilter
接口
你可以通过实现IActionFilter
接口来创建一个自定义的操作过滤器。IActionFilter
接口包含两个方法:
OnActionExecuting(ActionExecutingContext context)
:在操作方法执行之前调用。OnActionExecuted(ActionExecutedContext context)
:在操作方法执行之后调用。
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
publicclassMyActionFilter : IActionFilter
{
privatereadonly ILogger<MyActionFilter> _logger;
public MyActionFilter(ILogger<MyActionFilter> logger)
{
_logger = logger;
}
// 在操作执行之前调用
public void OnActionExecuting(ActionExecutingContext context)
{
_logger.LogInformation("OnActionExecuting: {ActionName}", context.ActionDescriptor.DisplayName);
// 你可以在这里进行请求参数的验证或其他预处理操作
}
// 在操作执行之后调用
public void OnActionExecuted(ActionExecutedContext context)
{
_logger.LogInformation("OnActionExecuted: {ActionName}", context.ActionDescriptor.DisplayName);
// 在这里进行操作后的处理(例如:修改结果、记录日志等)
}
}
2. 使用ActionFilterAttribute
特性类
ASP.NET Core 还提供了一个基类ActionFilterAttribute
,它实现了IActionFilter
接口。你可以通过继承这个类来创建自定义的操作过滤器。这样,你就可以通过特性标记来应用过滤器。
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
publicclassMyActionFilterAttribute : ActionFilterAttribute
{
privatereadonly ILogger<MyActionFilterAttribute> _logger;
public MyActionFilterAttribute(ILogger<MyActionFilterAttribute> logger)
{
_logger = logger;
}
public override void OnActionExecuting(ActionExecutingContext context)
{
_logger.LogInformation("OnActionExecuting: {ActionName}", context.ActionDescriptor.DisplayName);
base.OnActionExecuting(context);
}
public override void OnActionExecuted(ActionExecutedContext context)
{
_logger.LogInformation("OnActionExecuted: {ActionName}", context.ActionDescriptor.DisplayName);
base.OnActionExecuted(context);
}
}
3. 应用操作过滤器
-
应用于控制器或操作方法:你可以通过
[ServiceFilter]
或[TypeFilter]
特性将自定义的操作过滤器应用于特定的控制器或方法。 -
使用
ActionFilterAttribute
的方式:[MyActionFilterAttribute]
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
} -
使用
ServiceFilter
或TypeFilter
特性来注入服务:[ServiceFilter(typeof(MyActionFilter))]
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}ServiceFilter
用于注入已注册的服务类型;TypeFilter
允许指定一个类型,可以通过构造函数来创建。
4. 在Startup.cs
中注册操作过滤器
如果你想全局使用自定义的操作过滤器,可以在Startup.cs
文件中的ConfigureServices
方法中进行注册:
public void ConfigureServices(IServiceCollection services)
{
// 注册自定义过滤器
services.AddScoped<MyActionFilter>(); // 如果你使用了 ServiceFilter 特性,记得注册依赖注入
// 全局添加过滤器
services.AddControllersWithViews(options =>
{
options.Filters.Add<MyActionFilter>(); // 这会将 MyActionFilter 应用到所有控制器和操作
});
}
操作过滤器的使用场景
操作过滤器的使用场景非常广泛,通常用来处理以下任务:
-
日志记录:记录每个请求的相关信息。
public override void OnActionExecuting(ActionExecutingContext context)
{
_logger.LogInformation($"Executing action {context.ActionDescriptor.DisplayName}");
} -
验证请求数据:例如,验证请求的参数是否符合预期。
public override void OnActionExecuting(ActionExecutingContext context)
{
var parameter = context.ActionArguments["id"];
if (parameter == null || (int)parameter <= 0)
{
context.Result = new BadRequestObjectResult("Invalid ID");
}
} -
修改响应结果:操作方法执行后,可以对返回的结果进行修改。
public override void OnActionExecuted(ActionExecutedContext context)
{
if (context.Result is ViewResult viewResult)
{
viewResult.ViewData["CustomData"] = "This is added by the filter.";
}
} -
缓存处理:为请求添加缓存逻辑。
public override void OnActionExecuting(ActionExecutingContext context)
{
var cacheKey = GenerateCacheKey(context);
var cachedData = _cache.Get(cacheKey);
if (cachedData != null)
{
context.Result = new JsonResult(cachedData);
}
} -
权限检查:例如检查当前用户是否具有访问某些资源的权限。
public override void OnActionExecuting(ActionExecutingContext context)
{
if (!_userHasPermission)
{
context.Result = new ForbidResult();
}
}
异步操作过滤器
如果你需要在操作执行前或后执行异步操作(如访问数据库或外部 API),你可以实现IAsyncActionFilter
接口。它有两个方法:
OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
:该方法是异步的,允许你在执行操作前或后进行异步操作。
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;
publicclassMyAsyncActionFilter : IAsyncActionFilter
{
privatereadonly ILogger<MyAsyncActionFilter> _logger;
public MyAsyncActionFilter(ILogger<MyAsyncActionFilter> logger)
{
_logger = logger;
}
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
_logger.LogInformation("OnActionExecutionAsync: Before Action Execution");
// 执行操作之前的逻辑(如果需要)
var resultContext = await next(); // 调用控制器操作方法
_logger.LogInformation("OnActionExecutionAsync: After Action Execution");
// 执行操作之后的逻辑(如果需要)
}
}
小结
- 操作过滤器 是在控制器方法执行之前或之后执行自定义逻辑的强大工具。
- 你可以通过实现
IActionFilter
或继承ActionFilterAttribute
类来创建操作过滤器。 - 操作过滤器可以用于多种场景,如日志记录、参数验证、响应修改、权限检查等。
- 它们可以通过
[ServiceFilter]
、[TypeFilter]
、[ActionFilter]
特性应用到单个控制器或操作,也可以在Startup.cs
中配置为全局过滤器。 - 异步操作过滤器(
IAsyncActionFilter
)适用于需要执行异步操作的场景。
使用操作过滤器可以将额外的逻辑从控制器中抽离出来,使得代码更加清晰和易于维护。