当我在 ASP.NET Core 中使用非控制器类时,SignalR 的客户端列表为空

问题描述 投票:0回答:1

我有一个 ASP.NET Core Web 服务和一个 Blazor 客户端。当我的方法在 Web 服务中的类(而不是控制器)中触发时,我想将数据发送给我的客户端。

当我使用控制器时,它可以工作,但在常规课程中,我看到

clients.All
是空的,即使
OnConnectedAsync
被触发(表示已连接)

据我了解,

HubContext
不是单例而是瞬态的。我尝试了很多方法,但连接的客户端列表是空的。

在我的

Startup

public void ConfigureServices(IServiceCollection services)
{
     services.AddSignalR();
     services.InstallServicesInAssembly(Configuration);
    services.AddTransient<IGeneralStockMarketHandler, GeneralStockMarketHandler>();

    services.AddCors(options =>
    {
       options.AddPolicy("CorsPolicy", policy =>
       {
         policy.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();
        });
    });            
}


public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
 app.UseCors("CorsPolicy");
 app.UseEndpoints(endpoints =>
 {
    endpoints.MapHub<NotificationHub>("/notificationhub");
    endpoints.MapControllers();
 }); 
}

我的中心:

public class NotificationHub : Hub
{
     public override Task OnConnectedAsync()
     {
        Console.WriteLine("Client has connected");
        return base.OnConnectedAsync();
     }

     public override Task OnDisconnectedAsync(Exception exception)
     {
        Console.WriteLine("Client has disconnected");
       return base.OnDisconnectedAsync(exception);
     }
}

我注入的

GeneralStockMarketHandler
IHubContext

 public GeneralStockMarketHandler(IHubContext<NotificationHub> hubContext)
 {
   _hubContext = hubContext;            
 }

 private async void MyStockMarketHandler_OnDataReceived(StreamSnapshotResponseModel response)
 {
   await HandleStreamSnapshotResponse(response);
   await _hubContext.Clients.All.SendAsync("notification", response.Data);
 }

正如您在上面看到的,即使客户端已连接,

_hubContext.Clients.All
也是空的,因此它不会发送任何客户端。

在我的 Blazor 应用程序中,

Index.razor

@code {
    string url = "http://localhost:1580/notificationhub";    
    HubConnection _connection = null;
    bool isConnected = false;
    string connectionStatus = "Ready";


    private async Task ConnectToServer()
    {
        _connection = new HubConnectionBuilder()
            .WithUrl(url)
            .Build();

        await _connection.StartAsync();
        isConnected = true;   
        connectionStatus = "Connected";

        _connection.Closed += async (s) =>
        {
            isConnected = false;
            connectionStatus = "Disconnected";
            await _connection.StartAsync();
            isConnected = true;
        };
            
        _connection.On<string>("notification", m =>
        {      
          connectionStatus = "I have data!";     
          StateHasChanged();
        });
    }
}

当我的

HubContext
注入控制器时,它可以工作,但是当它在常规类中时,它不起作用,因为
clients.All
是空的。我该如何解决这个问题?

更新:

我想,我发现了问题所在。在我的安装程序中,我从 GeneralStockMarketHandler 类创建一个实例,并调用 StartToSubscribeAllStocksFromDb 方法。我必须一开始就调用一次这个方法

 services.AddScoped<IGeneralStockMarketHandler, GeneralStockMarketHandler>();    
 var serviceProvider = services.BuildServiceProvider();
 var stockMarketHandler serviceProvider.GetRequiredService<IGeneralStockMarketHandler>();
 stockMarketHandler.StartToSubscribeAllStocksFromDb();

如果我不从 GeneralStockMarketHandler 类创建实例,那么我可以获得连接的客户端。

我不明白为什么它会影响逻辑。它不是单例,我只使用了一次

c# asp.net-core blazor signalr-hub
1个回答
0
投票

我也遇到这个问题了。在我看来,解决方案是定义一个名为 HubClientInfo 的类,并将其作为 Singleton 添加到方法中的项目服务中 该类定义如下::

public interface IHubClientInfo
{
  List<IClientProxy> Clients {  set; get; }
  void Add(IClientProxy Client);
  void Remove(IClientProxy Client);
}

在我的hub中,我注入了这个类的服务,在OnConnectedAsync方法中,我调用了我的类的Add方法,在OnDisconnectedAsync方法中,我调用了我的类的Remove方法。最后,无论我需要向客户端广播消息,我都会注入 HubClientInfo 服务并以这种方式发送消息。

foreach(var Client in _HubClientInfo.Clients)
   await Client.SendAsync("SendMessage", "a", "b");
© www.soinside.com 2019 - 2024. All rights reserved.