翼度科技»论坛 编程开发 .net 查看内容

ASP.NET Core SignalR 系列(四)- 中心筛选器

3

主题

3

帖子

9

积分

新手上路

Rank: 1

积分
9
本章将和大家分享 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 中心方法。
  1. using Microsoft.AspNetCore.SignalR;
  2. namespace SignalRChat.HubFilter
  3. {
  4.     public class CustomFilter : IHubFilter
  5.     {
  6.         public async ValueTask<object> InvokeMethodAsync(
  7.         HubInvocationContext invocationContext, Func<HubInvocationContext, ValueTask<object>> next)
  8.         {
  9.             System.Diagnostics.Debug.WriteLine($"Calling hub method '{invocationContext.HubMethodName}'");
  10.             try
  11.             {
  12.                 var result = await next(invocationContext); //调用下一个筛选器,最终筛选器将调用中心方法
  13.                 System.Diagnostics.Debug.WriteLine($"Called hub method '{invocationContext.HubMethodName}'");
  14.                 return result;
  15.             }
  16.             catch (Exception ex)
  17.             {
  18.                 Console.WriteLine($"Exception calling '{invocationContext.HubMethodName}': {ex}");
  19.                 throw;
  20.             }
  21.         }
  22.         // Optional method
  23.         public Task OnConnectedAsync(HubLifetimeContext context, Func<HubLifetimeContext, Task> next)
  24.         {
  25.             return next(context);
  26.         }
  27.         // Optional method
  28.         public Task OnDisconnectedAsync(
  29.             HubLifetimeContext context, Exception exception, Func<HubLifetimeContext, Exception, Task> next)
  30.         {
  31.             return next(context, exception);
  32.         }
  33.     }
  34. }
复制代码
筛选器与中间件非常相似。 next 方法调用下一个筛选器。 最终筛选器将调用中心方法。 筛选器还可以存储等待 next 的结果,并在调用中心方法之后、从 next 返回结果之前运行逻辑。
若要跳过筛选器中的中心方法调用,请引发 HubException 类型的异常,而不是调用 next。 如果客户端需要结果,则会收到错误。
2、配置中心筛选器

中心筛选器可以全局应用或按中心类型应用。 筛选器的添加顺序就是其运行顺序。 全局中心筛选器在本地中心筛选器之前运行。
  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3.     services.AddSignalR(options =>
  4.     {
  5.         // Global filters will run first
  6.         options.AddFilter<CustomFilter>();
  7.     }).AddHubOptions<ChatHub>(options =>
  8.     {
  9.         // Local filters will run second
  10.         options.AddFilter<CustomFilter2>();
  11.     });
  12. }
复制代码
可以通过以下方式之一添加中心筛选器:
1)按具体类型添加筛选器:
  1. hubOptions.AddFilter<TFilter>();
复制代码
将通过依赖项注入 (DI) 或激活的类型来解析。
2)按运行时类型添加筛选器:
  1. hubOptions.AddFilter(typeof(TFilter));
复制代码
将通过 DI 或激活的类型来解析。
3)按实例添加筛选器:
  1. hubOptions.AddFilter(new MyFilter());
复制代码
将像单一实例一样使用此实例。 所有中心方法调用都将使用相同的实例。
系统根据中心调用来创建和释放中心筛选器。 如果要在筛选器中存储全局状态,或者不存储状态,请将中心筛选器类型作为单一实例添加到 DI,以获得更好的性能。 或者,如果可以,将筛选器添加为实例。
3、使用中心筛选器

编写筛选器逻辑时,请尝试通过在中心方法上使用特性而不是检查中心方法名称,使其成为泛型逻辑。
以某个筛选器为例,该筛选器将检查中心方法参数中是否有被禁短语,并将找到的任何短语替换为 ***。 对于此示例,假设定义了 LanguageFilterAttribute 特性类。 该类有一个名为 FilterArgument 的属性,可以在使用该属性时对其进行设置。
1)将该特性标签打在需要清理字符串参数的中心方法上:
  1. public class ChatHub
  2. {
  3.     [LanguageFilter(filterArgument = 0)]
  4.     public async Task SendMessage(string message, string username)
  5.     {
  6.         await Clients.All.SendAsync("SendMessage", $"{username} says: {message}");
  7.     }
  8. }
复制代码
2)定义一个中心筛选器,以检查该特性并将中心方法参数中的被禁短语替换为 ***:
  1. public class LanguageFilter : IHubFilter
  2. {
  3.     // populated from a file or inline
  4.     private List<string> bannedPhrases = new List<string> { "async void", ".Result" };
  5.     public async ValueTask<object> InvokeMethodAsync(HubInvocationContext invocationContext,
  6.         Func<HubInvocationContext, ValueTask<object>> next)
  7.     {
  8.         var languageFilter = (LanguageFilterAttribute)Attribute.GetCustomAttribute(
  9.             invocationContext.HubMethod, typeof(LanguageFilterAttribute));
  10.         if (languageFilter != null &&
  11.             invocationContext.HubMethodArguments.Count > languageFilter.FilterArgument &&
  12.             invocationContext.HubMethodArguments[languageFilter.FilterArgument] is string str)
  13.         {
  14.             foreach (var bannedPhrase in bannedPhrases)
  15.             {
  16.                 str = str.Replace(bannedPhrase, "***");
  17.             }
  18.             var arguments = invocationContext.HubMethodArguments.ToArray();
  19.             arguments[languageFilter.FilterArgument] = str;
  20.             invocationContext = new HubInvocationContext(invocationContext.Context,
  21.                 invocationContext.ServiceProvider,
  22.                 invocationContext.Hub,
  23.                 invocationContext.HubMethod,
  24.                 arguments);
  25.         }
  26.         return await next(invocationContext);
  27.     }
  28. }
复制代码
3)在 Startup.ConfigureServices 方法中注册中心筛选器。 为了避免每次调用都重新初始化被禁短语列表,中心筛选器将注册为单一实例:
  1. public void ConfigureServices(IServiceCollection services){    services.AddSignalR(hubOptions =>    {        hubOptions.AddFilter<TFilter>();    });    services.AddSingleton();}
复制代码
4、HubInvocationContext 对象

HubInvocationContext 包含当前中心方法调用的信息。
属性说明类型
 Context HubCallerContext 包含有关连接的信息。 HubCallerContext
 Hub 用于此中心方法调用的中心实例。 Hub
 HubMethodName 正在调用的中心方法的名称。 string
 HubMethodArguments 传递给中心方法的参数列表。 IReadOnlyList
 ServiceProvider 用于此中心方法调用的已限定范围的服务提供程序。 IServiceProvider
 HubMethod 中心方法信息。 MethodInfo
5、HubLifetimeContext 对象

HubLifetimeContext 包含 OnConnectedAsync 和 OnDisconnectedAsync 中心方法的信息。
属性说明类型
ContextHubCallerContext 包含有关连接的信息。HubCallerContext
Hub用于此中心方法调用的中心实例。Hub
ServiceProvider用于此中心方法调用的已限定范围的服务提供程序。IServiceProvider
6、授权和筛选器

中心方法上的 Authorize 属性在中心筛选器之前运行。
至此本文就全部介绍完了,想要了解更多内容可参考微软官网。
 
Demo源码:
  1. 链接:https://pan.baidu.com/s/1la_AnXNqsXWRG0bslh5dFg
  2. 提取码:54kz
复制代码
来源:https://www.cnblogs.com/xyh9039/archive/2023/07/16/17558580.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具