首页 > 编程语言 >ASP.NET Core SignalR 系列(四)- 中心筛选器

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

时间:2023-07-16 22:56:32浏览次数:45  
标签:Core ASP 中心 next SignalR 调用 筛选 方法 invocationContext

本章将和大家分享 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

标签:Core,ASP,中心,next,SignalR,调用,筛选,方法,invocationContext
From: https://www.cnblogs.com/xyh9039/p/17558580.html

相关文章

  • 如何在.NET Core中使用redis
    一、1.添加Redis依赖项:在.NETCore项目中,你需要添加对StackExchange.Redis库的引用。你可以通过NuGet包管理器或手动添加依赖项来完成此操作。2. 配置Redis连接:在appsettings.json文件中,添加Redis连接配置。例如:"Redis":{"ConnectionString":"localhost:6379"}3.......
  • 记录一次.net core使用redis报错
    一、记录一次报错:报错信息如下RedisTimeoutException:Timeoutawaitingresponse(outbound=0KiB,inbound=1KiB,12063mselapsed,timeoutis1000ms),command=SCAN,next:SCAN,inst:0,qu:0,qs:1,aw:False,bw:Inactive,rs:DequeueResult,ws:Idle,in:0,in-......
  • .net core使用Dapper
    一、记录一下.NETcoreAPI下使用dapper的方法。1.引入两个Nuget包:Dapper这个是dapper的主要引用包System.Data.SqlClient这个包主要是用来使用SQLServer的时候使用的,如果是使用MySQL,就不能使用这个。2.添加配置文件:"ConnectionStrings":{"DefaultConnection":"Se......
  • ASP.NET Core学习笔记
    ASP.NETCore教程:https://www.bilibili.com/video/BV1Kk4y117Xy/?p=2&spm_id_from=pageDriver&vd_source=34dc5215532143d76607ef8957c72691的笔记ASP.NETCore启动流程ASP.NETCoreWeb应用程序最初作为控制台应用程序启动,Main()方法是应用程序的入口点。因此,当我们执行AS......
  • ASP.NET Core Web API中操作方法中的参数来源
    在ASP.NETCoreWebAPI中,有多种方式可以传递参数给操作方法。以下是一些常见的参数传递方式:路由参数(RouteParameters):参数值从URL的路由中提取。//Route:api/users/{id}[HttpGet("api/users/{id}")]publicIActionResultGetUserById(intid){//使用id执行操作......
  • 【IP】vivado中IP核的Core Container特性
    一、XCI和XCIX格式文件在Vivado中生成IP核时,一般默认是对应的IP核文件夹会生成在工程目录的.srcs/sources_1/ip路径下。这个文件夹包含了所有与该IP核相关的文件,最主要的是XCI文件,其中包含了用户配置的相关信息。 Vivado还提供了CoreContainer特性,可以将所有与IP相关的文件......
  • lib64/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by /home/liuj
     glibc是GNU发布的libc库,即c运行库。glibc是linux系统中最底层的api,几乎其它任何运行库都会依赖于glibc。glibc除了封装linux操作系统所提供的系统服务外,它本身也提供了许多其它一些必要功能服务的实现。由于glibc囊括了几乎所有的 UNIX 通行的标准,可以想见其内容包罗万象。而......
  • linux 中 asprta 软件的安装
     001、下载软件:官网:https://www.ibm.com/aspera/connect/ 002、上传至linux系统中并安装tar-xzvfibm-aspera-connect_4.2.6.393_linux_x86_64.tar.gzbashibm-aspera-connect_4.2.6.393_linux_x86_64.sh 003、 ......
  • 会声会影2023旗舰版Corel VideoStudio Ultimate 2023 V26.0.0.136整合盘版本
    会声会影2023旗舰版CorelVideoStudioUltimate2023V26.0.0.136整合盘版本是一款有趣且直观的视频编辑器,包含高级工具和高级效果,智能功能和最佳性能的高级视频编辑软件,将您最美好的时刻和生活体验变成令人惊叹的电影。会声会影2023下载地址:https://souurl.cn/kdsHII会声会影2022......
  • dotnet 连接sqlite数据库 orm EntityFrameworkCore
    dotnet_learn/appsettings.json{"Logging":{"LogLevel":{"Default":"Information","Microsoft.AspNetCore":"Warning"}},"AllowedHosts":"*"}d......