本章將和大家分享 ASP.NET Core SignalR 中的中心篩選器。
本文大部分內(nèi)容摘自微軟官網(wǎng):https://learn.microsoft.com/zh-cn/aspnet/core/signalr/hub-filters?view=aspnetcore-7.0
廢話不多說(shuō),下面我們直接進(jìn)入本章主題。
中心篩選器:
- 在 ASP.NET Core 5.0 或更高版本中可用。
- 允許在客戶端調(diào)用中心方法之前和之后運(yùn)行邏輯。
1、創(chuàng)建中心篩選器
通過(guò)聲明從?IHubFilter
?繼承的類來(lái)創(chuàng)建篩選器,并添加?InvokeMethodAsync
?方法。 還可以選擇實(shí)現(xiàn)?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); //調(diào)用下一個(gè)篩選器,最終篩選器將調(diào)用中心方法 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
?方法調(diào)用下一個(gè)篩選器。 最終篩選器將調(diào)用中心方法。 篩選器還可以存儲(chǔ)等待?next
?的結(jié)果,并在調(diào)用中心方法之后、從?next
?返回結(jié)果之前運(yùn)行邏輯。
若要跳過(guò)篩選器中的中心方法調(diào)用,請(qǐng)引發(fā)?HubException
?類型的異常,而不是調(diào)用?next
。 如果客戶端需要結(jié)果,則會(huì)收到錯(cuò)誤。
2、配置中心篩選器
中心篩選器可以全局應(yīng)用或按中心類型應(yīng)用。 篩選器的添加順序就是其運(yùn)行順序。 全局中心篩選器在本地中心篩選器之前運(yùn)行。
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>(); }); }
可以通過(guò)以下方式之一添加中心篩選器:
1)按具體類型添加篩選器:
hubOptions.AddFilter<TFilter>();
將通過(guò)依賴項(xiàng)注入 (DI) 或激活的類型來(lái)解析。
2)按運(yùn)行時(shí)類型添加篩選器:
hubOptions.AddFilter(typeof(TFilter));
將通過(guò) DI 或激活的類型來(lái)解析。
3)按實(shí)例添加篩選器:
hubOptions.AddFilter(new MyFilter());
將像單一實(shí)例一樣使用此實(shí)例。 所有中心方法調(diào)用都將使用相同的實(shí)例。
系統(tǒng)根據(jù)中心調(diào)用來(lái)創(chuàng)建和釋放中心篩選器。 如果要在篩選器中存儲(chǔ)全局狀態(tài),或者不存儲(chǔ)狀態(tài),請(qǐng)將中心篩選器類型作為單一實(shí)例添加到 DI,以獲得更好的性能。 或者,如果可以,將篩選器添加為實(shí)例。
3、使用中心篩選器
編寫(xiě)篩選器邏輯時(shí),請(qǐng)嘗試通過(guò)在中心方法上使用特性而不是檢查中心方法名稱,使其成為泛型邏輯。
以某個(gè)篩選器為例,該篩選器將檢查中心方法參數(shù)中是否有被禁短語(yǔ),并將找到的任何短語(yǔ)替換為?***
。 對(duì)于此示例,假設(shè)定義了?LanguageFilterAttribute
?特性類。 該類有一個(gè)名為?FilterArgument
?的屬性,可以在使用該屬性時(shí)對(duì)其進(jìn)行設(shè)置。
1)將該特性標(biāo)簽打在需要清理字符串參數(shù)的中心方法上:
public class ChatHub { [LanguageFilter(filterArgument = 0)] public async Task SendMessage(string message, string username) { await Clients.All.SendAsync("SendMessage", $"{username} says: {message}"); } }
2)定義一個(gè)中心篩選器,以檢查該特性并將中心方法參數(shù)中的被禁短語(yǔ)替換為 ***:
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 方法中注冊(cè)中心篩選器。 為了避免每次調(diào)用都重新初始化被禁短語(yǔ)列表,中心篩選器將注冊(cè)為單一實(shí)例:
public void ConfigureServices(IServiceCollection services) { services.AddSignalR(hubOptions => { hubOptions.AddFilter<LanguageFilter>(); }); services.AddSingleton<LanguageFilter>(); }
4、HubInvocationContext 對(duì)象
HubInvocationContext
?包含當(dāng)前中心方法調(diào)用的信息。
屬性 | 說(shuō)明 | 類型 |
?Context | ?HubCallerContext ?包含有關(guān)連接的信息。 |
?HubCallerContext |
?Hub | ?用于此中心方法調(diào)用的中心實(shí)例。 | ?Hub |
?HubMethodName | ?正在調(diào)用的中心方法的名稱。 | ?string |
?HubMethodArguments | ?傳遞給中心方法的參數(shù)列表。 | ?IReadOnlyList<string> |
?ServiceProvider | ?用于此中心方法調(diào)用的已限定范圍的服務(wù)提供程序。 | ?IServiceProvider |
?HubMethod | ?中心方法信息。 | ?MethodInfo |
5、HubLifetimeContext 對(duì)象
HubLifetimeContext
?包含?OnConnectedAsync
?和?OnDisconnectedAsync
?中心方法的信息。
屬性 | 說(shuō)明 | 類型 |
Context |
HubCallerContext ?包含有關(guān)連接的信息。 |
HubCallerContext |
Hub | 用于此中心方法調(diào)用的中心實(shí)例。 | Hub |
ServiceProvider | 用于此中心方法調(diào)用的已限定范圍的服務(wù)提供程序。 | IServiceProvider |
6、授權(quán)和篩選器
中心方法上的 Authorize 屬性在中心篩選器之前運(yùn)行。
至此本文就全部介紹完了,想要了解更多內(nèi)容可參考微軟官網(wǎng)。
?文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-570091.html
Demo源碼:文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-570091.html
鏈接:https://pan.baidu.com/s/1la_AnXNqsXWRG0bslh5dFg 提取碼:54kz
到了這里,關(guān)于ASP.NET Core SignalR 系列(四)- 中心篩選器的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!