系列導航及源代碼
- 使用.NET 6開發TodoList應用文章索引
需求
Filter在.NET Web API專案開發中也是很重要的一個概念,它運行在執行MVC回應的Pipeline中執行,允許我們將一些可以在多個Action之間重用的邏輯抽取出來集中管理,雖然我們在上一篇使用.NET 6開發TodoList應用(11)——使用FluentValidation和MediatR實作介面請求驗證中演示了如何通過使用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輸出的回傳資料日志:
-
一點擴展
關于Filter的主題還包含關于其作用域,優先級順序以及如何調整優先級等,其他主題像如何改寫回應,如何進行性能統計和快取,我在這里暫時不做演示,可以參考微軟官方檔案:ASP.NET Core 中的篩選器,進行更多了解,
總結
在本文中我們通過一個很簡單的例子,演示了Action Filter的基本用法,至此我們關于請求中間件管道的討論先告一個段落,后面說到認證鑒權的時候我們還會回來討論這個主題,
從下一篇開始,我們集中來討論查詢操作中涉及的一些典型場景:包括分頁、排序、過濾、搜索等,
參考資料
- ASP.NET Core 中的篩選器
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/398362.html
標籤:.NET技术
