I have the following hub implementation in a new and clean ASP.NET Core 2.1 Web Application. I just updated to the latest version of ASP.NET Core 2.1 and the latest version of Visual Studio 2017.
The class worked and when launched from the debugger, one client connects. I can see this with the debugger, and, I can see this in the client because I log the "userobject" I send after it connected. The client remains connected.
In a second step, I injected the IPbxConnection into the hub, which works as well (I can see a valid object with the debugger). The IPbxConnection implementation will call the OnUserUpdated handler after 5 seconds (I just do this with a timer callback now in the IPbxConnection implementation for testing). This always results in an object disposed exception thrown on the Clients object. How can I send a notification to all clients in this callback? It seems the Clients object does not keep it's state and is only valid during the message handlers... however, I want to push information to the client at all times.
public class PresenceHub : Hub
{
//Members
private IPbxConnection _connection;
/// <summary>
/// Constructor, pbx connection must be provided by dependency injection
/// </summary>
public PresenceHub(IPbxConnection connection)
{
_connection = connection;
_connection.OnUserUpdated((e) =>
{
Clients.All.SendAsync("UpdateUser", "updateuserobject");
});
_connection.Connect();
}
/// <summary>
/// Called whenever a user is connected to the hub. We will send him all the user information
/// </summary>
public override async Task OnConnectedAsync()
{
await base.OnConnectedAsync();
await Clients.Caller.SendAsync("AddUser", "userobject");
}
}
SignalR requires that all HTTP requests for a specific connection be handled by the same server process. When SignalR is running on a server farm (multiple servers), "sticky sessions" must be used. "Sticky sessions" are also called session affinity by some load balancers.
In the default mode, the app server creates five server connections with Azure SignalR Service. The app server uses the Azure SignalR Service SDK by default. In the following performance test results, server connections are increased to 15 (or more for broadcasting and sending a message to a big group).
SignalR is deprecated. May I know the latest package for the same.
A SignalR connection can end in any of the following ways: If the client calls the Stop method, a stop message is sent to the server, and both client and server end the SignalR connection immediately.
As described in this issue on Github https://github.com/aspnet/SignalR/issues/2424 Hubs are short lived by design and are disposed after every invocation.
The only way I found to access your Clients outside of the current request Scope on your Hub is by injecting the HubContext into a seperate Class.
In your case a Broadcast to all Clients would look something like this
public class HubEventEmitter
{
private IHubContext<PresenceHub> _hubContext;
public HubEventEmitter(IPbxConnection connection, IHubContext<PresenceHub> hubContext)
{
_hubContext = hubContext;
_connection.OnUserUpdated((e) =>
{
_hubContext.Clients.All.SendAsync("UpdateUser", "updateuserobject");
});
}
}
if you wanted to notify only specific Clients you'll have to collect the connectionId from the Context and use it like this
_hubContext.Clients.Client(connectionId).SendAsync("UpdateUser", "updateuserobject");
This simple solution works for me. I haven't added anything extra to the start up class.
EDIT After some thought I decided that although this code works, it isn't a good pattern, not least because the static code ends up trying to use fields within a disposed object. A hub is a lightweight, short-lived container and should be used as such. I am therefore moving my long running process from static elements of the Hub into an IHostedService pattern
My hub contains a long running async process defined in a static member. Because Hubs are transient, on some occasions the hub is disposed when the async process tries to send messages. I have added a hub context for Injection into the Hub Constructor
public class IisLogFileHub : Hub
{
IHubContext<IisLogFileHub> _hubContext = null;
public IisLogFileHub(IHubContext<IisLogFileHub> hubContext)
{
_hubContext = hubContext;
}
}
At any point in the long-running process, messages can be sent as follows
await _hubContext.Clients.All.SendAsync("ReceiveMessage", msg);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With