I have an ASP.NET Core Webservice and a Blazor client. When my method is triggered in a class (not a controller) in the webservice, I want to send my data to my clients.
When I use a controller, it works but in a regular class, I see the clients.All are empty even OnConnectedAsync is triggered (means connected)
As I understand, HubContext is not a singleton but transient. I tried many things but the connected clients list is empty.
In my 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();
});
}
My hub:
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);
}
}
My GeneralStockMarketHandler class which I injected 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);
}
As you see above _hubContext.Clients.All is empty even a client has connected, so it does not send any client.
In my Blazor app, 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();
});
}
}
When my HubContext is injected into the controller, it works but when it is in a regular class, it does not work because the clients.All is empty. How can I solve this problem?
UPDATE:
I think, I found out the problem. In my installer, I create an instance from GeneralStockMarketHandler class and call a method which is StartToSubscribeAllStocksFromDb. I have to call this method once in the beginning
services.AddScoped<IGeneralStockMarketHandler, GeneralStockMarketHandler>();
var serviceProvider = services.BuildServiceProvider();
var stockMarketHandler serviceProvider.GetRequiredService<IGeneralStockMarketHandler>();
stockMarketHandler.StartToSubscribeAllStocksFromDb();
If I do not create an instance from GeneralStockMarketHandler class then I can get the connected clients.
I dont understand why it effects the logic. It is not singleton and I use it only one time