本章將和大家分享 ASP.NET Core SignalR 中的中心篩選器。 本文大部分內容摘自微軟官網:https://learn.microsoft.com/zh-cn/aspnet/core/signalr/hub-filters?view=aspnetcore-7.0 廢話不多說,下麵我們直 ...
本章將和大家分享 ASP.NET Core SignalR 中的中心篩選器。
本文大部分內容摘自微軟官網:https://learn.microsoft.com/zh-cn/aspnet/core/signalr/hub-filters?view=aspnetcore-7.0
廢話不多說,下麵我們直接進入本章主題。
中心篩選器:
- 在 ASP.NET Core 5.0 或更高版本中可用。
- 允許在客戶端調用中心方法之前和之後運行邏輯。
1、創建中心篩選器
通過聲明從 IHubFilter
繼承的類來創建篩選器,並添加 InvokeMethodAsync
方法。 還可以選擇實現 OnConnectedAsync
和 OnDisconnectedAsync
,以分別包裝 OnConnectedAsync
和 OnDisconnectedAsync
中心方法。
using Microsoft.AspNetCore.SignalR; namespace SignalRChat.HubFilter { public class CustomFilter : IHubFilter { public async ValueTask<object> InvokeMethodAsync( HubInvocationContext invocationContext, Func<HubInvocationContext, ValueTask<object>> next) { System.Diagnostics.Debug.WriteLine($"Calling hub method '{invocationContext.HubMethodName}'"); try { var result = await next(invocationContext); //調用下一個篩選器,最終篩選器將調用中心方法 System.Diagnostics.Debug.WriteLine($"Called hub method '{invocationContext.HubMethodName}'"); return result; } catch (Exception ex) { Console.WriteLine($"Exception calling '{invocationContext.HubMethodName}': {ex}"); throw; } } // Optional method public Task OnConnectedAsync(HubLifetimeContext context, Func<HubLifetimeContext, Task> next) { return next(context); } // Optional method public Task OnDisconnectedAsync( HubLifetimeContext context, Exception exception, Func<HubLifetimeContext, Exception, Task> next) { return next(context, exception); } } }
篩選器與中間件非常相似。 next
方法調用下一個篩選器。 最終篩選器將調用中心方法。 篩選器還可以存儲等待 next
的結果,併在調用中心方法之後、從 next
返回結果之前運行邏輯。
若要跳過篩選器中的中心方法調用,請引發 HubException
類型的異常,而不是調用 next
。 如果客戶端需要結果,則會收到錯誤。
2、配置中心篩選器
中心篩選器可以全局應用或按中心類型應用。 篩選器的添加順序就是其運行順序。 全局中心篩選器在本地中心篩選器之前運行。
public void ConfigureServices(IServiceCollection services) { services.AddSignalR(options => { // Global filters will run first options.AddFilter<CustomFilter>(); }).AddHubOptions<ChatHub>(options => { // Local filters will run second options.AddFilter<CustomFilter2>(); }); }
可以通過以下方式之一添加中心篩選器:
1)按具體類型添加篩選器:
hubOptions.AddFilter<TFilter>();
將通過依賴項註入 (DI) 或激活的類型來解析。
2)按運行時類型添加篩選器:
hubOptions.AddFilter(typeof(TFilter));
將通過 DI 或激活的類型來解析。
3)按實例添加篩選器:
hubOptions.AddFilter(new MyFilter());
將像單一實例一樣使用此實例。 所有中心方法調用都將使用相同的實例。
系統根據中心調用來創建和釋放中心篩選器。 如果要在篩選器中存儲全局狀態,或者不存儲狀態,請將中心篩選器類型作為單一實例添加到 DI,以獲得更好的性能。 或者,如果可以,將篩選器添加為實例。
3、使用中心篩選器
編寫篩選器邏輯時,請嘗試通過在中心方法上使用特性而不是檢查中心方法名稱,使其成為泛型邏輯。
以某個篩選器為例,該篩選器將檢查中心方法參數中是否有被禁短語,並將找到的任何短語替換為 ***
。 對於此示例,假設定義了 LanguageFilterAttribute
特性類。 該類有一個名為 FilterArgument
的屬性,可以在使用該屬性時對其進行設置。
1)將該特性標簽打在需要清理字元串參數的中心方法上:
public class ChatHub { [LanguageFilter(filterArgument = 0)] public async Task SendMessage(string message, string username) { await Clients.All.SendAsync("SendMessage", $"{username} says: {message}"); } }
2)定義一個中心篩選器,以檢查該特性並將中心方法參數中的被禁短語替換為 ***:
public class LanguageFilter : IHubFilter { // populated from a file or inline private List<string> bannedPhrases = new List<string> { "async void", ".Result" }; public async ValueTask<object> InvokeMethodAsync(HubInvocationContext invocationContext, Func<HubInvocationContext, ValueTask<object>> next) { var languageFilter = (LanguageFilterAttribute)Attribute.GetCustomAttribute( invocationContext.HubMethod, typeof(LanguageFilterAttribute)); if (languageFilter != null && invocationContext.HubMethodArguments.Count > languageFilter.FilterArgument && invocationContext.HubMethodArguments[languageFilter.FilterArgument] is string str) { foreach (var bannedPhrase in bannedPhrases) { str = str.Replace(bannedPhrase, "***"); } var arguments = invocationContext.HubMethodArguments.ToArray(); arguments[languageFilter.FilterArgument] = str; invocationContext = new HubInvocationContext(invocationContext.Context, invocationContext.ServiceProvider, invocationContext.Hub, invocationContext.HubMethod, arguments); } return await next(invocationContext); } }
3)在 Startup.ConfigureServices 方法中註冊中心篩選器。 為了避免每次調用都重新初始化被禁短語列表,中心篩選器將註冊為單一實例:
public void ConfigureServices(IServiceCollection services) { services.AddSignalR(hubOptions => { hubOptions.AddFilter<LanguageFilter>(); }); services.AddSingleton<LanguageFilter>(); }
4、HubInvocationContext 對象
HubInvocationContext
包含當前中心方法調用的信息。
屬性 | 說明 | 類型 |
Context | HubCallerContext 包含有關連接的信息。 |
HubCallerContext |
Hub | 用於此中心方法調用的中心實例。 | Hub |
HubMethodName | 正在調用的中心方法的名稱。 | string |
HubMethodArguments | 傳遞給中心方法的參數列表。 | IReadOnlyList<string> |
ServiceProvider | 用於此中心方法調用的已限定範圍的服務提供程式。 | IServiceProvider |
HubMethod | 中心方法信息。 | MethodInfo |
5、HubLifetimeContext 對象
HubLifetimeContext
包含 OnConnectedAsync
和 OnDisconnectedAsync
中心方法的信息。
屬性 | 說明 | 類型 |
Context | HubCallerContext 包含有關連接的信息。 |
HubCallerContext |
Hub | 用於此中心方法調用的中心實例。 | Hub |
ServiceProvider | 用於此中心方法調用的已限定範圍的服務提供程式。 | IServiceProvider |
6、授權和篩選器
中心方法上的 Authorize 屬性在中心篩選器之前運行。
至此本文就全部介紹完了,想要瞭解更多內容可參考微軟官網。
Demo源碼:
鏈接:https://pan.baidu.com/s/1la_AnXNqsXWRG0bslh5dFg 提取碼:54kz