.NET 6开发TodoList应用之实现ActionFilter
目录
- 需求
- 目标
- 原理与思路
- 实现
- 验证
- 总结
需求
Filter在.NET Web API项目开发中也是很重要的一个概念,它运行在执行MVC响应的Pipeline中执行,允许我们将一些可以在多个Action之间重用的逻辑抽取出来集中管理。虽然我们在上一篇使用.NET 6开发TodoList应用之实现接口请求验证中演示了如何通过使用MediatR提供的IPipelineBehavior接口在CQRS的Handle方法执行前后插入可重用代码,而本文所演示的Filters作用在Controller的Action执行或Action返回结果前后。
可以创建自定义Filters,用于处理应用程序中的横切片关注点。 横切片关注点的包括错误处理、缓存、配置、授权和日志记录。 Filters可以避免重复代码。
Filter的类型分为以下几种:
Authorization Filters
:最先运行,用于确定是否已针对请求为用户授权。 如果请求未获授权,Authorization Filters可以让管道短路。
Resource Filters
:授权后运行。OnResourceExecuting在Filter Pipeline的其余阶段之前运行代码。OnResourceExecuted在管道的其余阶段完成之后运行代码。可以用这个类型的Filter进行缓存和性能统计。
Action Filters
:在调用操作方法之前和之后立即运行代码。它可以更改传递到操作中的参数,也可以更改从操作返回的结果,当然如果什么都不更改仅作记录也是可以的。
Exception Filters
:在向响应正文写入任何内容之前,对未经处理的异常应用全局策略。
Result Filters
:在执行操作结果返回之前和之后运行代码。 仅当操作方法成功执行时,它们才会被运行。
这五种Filters在Filter Pipeline中直观的展现是这样的:
而整个FIlter Pipeline在完整的Middleware Pipeline中的阶段是这样的:
在本文中,我们将演示Action Filters是如何在Controller的Action执行前后记录请求和响应日志的。
目标
使用Action Filters进行接口日志记录。
原理与思路
创建一个自定义的Action Filter,用于实现Controller的接口日志逻辑。
实现
在Api新建文件夹Filters并创建类LogFilterAttribute:
LogFilterAttribute.cs
using System.Text.Json; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; namespace TodoList.Api.Filters; public class LogFilterAttribute : IActionFilter { private readonly ILogger<LogFilterAttribute> _logger; public LogFilterAttribute(ILogger<LogFilterAttribute> logger) => _logger = logger; public void OnActionExecuting(ActionExecutingContext context) { var action = context.RouteData.Values["action"]; var controller = context.RouteData.Values["controller"]; // 获取名称包含Command的参数值 var param = context.ActionArguments.SingleOrDefault(x => x.Value.ToString().Contains("Command")).Value; _logger.LogInformation($"Controller:{controller}, action: {action}, Incoming request: {JsonSerializer.Serialize(param)}"); } public void OnActionExecuted(ActionExecutedContext context) { var action = context.RouteData.Values["action"]; var controller = context.RouteData.Values["controller"]; // 需要先将Result转换为ObjectResult类型才能拿到Value值 var result = (ObjectResult)context.Result!; _logger.LogInformation($"Controller:{controller}, action: {action}, Executing response: {JsonSerializer.Serialize(result.Value)}"); } }
依赖注入:
Program.cs
builder.Services.AddScoped<LogFilterAttribute>();
在需要应用该Filter的Controller Action上添加属性:
TodoListController.cs
[HttpPost] [ServiceFilter(typeof(LogFilterAttribute))] public async Task<ApiResponse<Domain.Entities.TodoList>> Create([FromBody] CreateTodoListCommand command) { return ApiResponse<Domain.Entities.TodoList>.Success(await _mediator.Send(command)); }
验证
启动Api项目,执行创建TodoList的请求:
请求
响应
来自于OnActionExecuting的请求数据日志:
注意在我们上一篇文章中的Handling CreateTodoListCommand之前输出的内容。
以及来自于OnActionExecuted输出的返回数据日志:
总结
在本文中我们通过一个很简单的例子,演示了Action Filter的基本用法。至此我们关于请求中间件管道的讨论先告一个段落,后面说到认证鉴权的时候我们还会回来讨论这个主题。
到此这篇关于.NET 6开发TodoList应用之实现ActionFilter的文章就介绍到这了,更多相关.NET 6实现ActionFilter内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!