前言
在增刪改查中的增和改操作中,我們經常需要更新資料流的建立人和修改人,無論我們專案是基於DDD,抑或是簡單僅有服務層,此時我們都需要獲取使用者資訊,那麼我們只能將使用者標識從控制器層層傳遞到服務或倉儲層?鑑於如上場景很常見,難道我們沒發覺這樣做很是繁瑣嗎?於是乎,我們想要解放生產力,下面我們們來聊聊我個人的想法
全域性獲取使用者資訊
既然是全域性獲取使用者資訊,難道是定義靜態變數?怎麼可能,當然是基於請求而獲取,基於靜態變數必然存在多個使用者請求覆蓋資訊的情況,那我們到底應該怎麼全域性獲取?首先我們想到的過濾器比如ActionFilter...等等,但要是我們需要進行非同步操作呢?貌似又不可行,根據我查詢官方文件,沒搞錯的話,應該是從1.0開始就給出了非同步過濾器,那就是IAsyncActionFilter,此方法不同於ActionFilter的是,它能夠處理非同步操作,同時它是在模型繫結完成之後執行,也就是隻有一個非同步方法
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { await next(); }
接下來我們定義全域性使用者會話類,如下:
public class Session { /// <summary> /// 使用者id /// </summary> public string UserId { get; set; } /// <summary> /// 使用者名稱 /// </summary> public string UserName { get; set; } }
緊接著,比如專案我們使用JWT,則拿到宣告中使用者標識和使用者賬號,那麼我們接下來我們只需要實現上述非同步action過濾器介面即可,如下:
public class AsyncSessionFilter : IAsyncActionFilter { private readonly Session _session; public AsyncSessionFilter(Session session) { _session = session; } public async Task OnActionExecutionAsync( ActionExecutingContext context, ActionExecutionDelegate next) { var user = context.HttpContext.User; _session.UserId = user.FindFirst(JwtRegisteredClaimNames.Sub)?.Value; _session.UserName = user.FindFirst(JwtRegisteredClaimNames.UniqueName)?.Value; await next(); } }
最後,則很簡單的進行上述介面實現和會話注入,如下:
//註冊使用者會話 services.AddScoped<Session>(); //註冊全域性過濾器 services.AddControllers(options => { options.Filters.Add<AsyncSessionFilter>(); })
在實際使用中,我們只需要在倉儲或服務層建構函式使用Session,即可拿到使用者名稱和使用者id,從而最終解決對於新增和更改操作處理操作人資訊
總結
? 在.NET Core中藉助實現非同步IAsyncActionFilter介面而實現全域性獲取使用者資訊