Getting specific hub instance associated with a specific SignalRConnectionId - signalr

Getting a reference to the client using the SignalRConnectionId is pretty simple via the GlobalHost class. Is there a way to get a reference to a hub instance associated with that client/connection? In other words, given the client connection Guid, can I get a reference to a hub instance that's talking to that client? The reason I want to do this is so I can invoke an instance method on the hub from somewhere else in the server.

It is not possible to get a Hub instance from outside of the SignalR Hub pipeline or the Hub itself.
Hubs are ephemeral in SignalR. Generally a new Hub is instantiated for each invocation, and then disposed immediately after.
This means that a single WebSocket connection can have an arbitrary number of associated Hub instances over its lifetime. Moreover, unless there is an ongoing invocation, it's unlikely that there is even an associated Hub in existence.
I would suggest replicating the Hub instance method you want to call with a static method that takes an IHubContext as a parameter. You can get the IHubContext using GlobalHost.ConnectionManager.GetHubContext.

Related

storing signalr hub connection details in local storage

I am using signalr client in my application. I want to establish the connection and use the same in all the pages. I could get the connection. To access the hub details i am trying to store it local storage.
Below is the hub details i am getting once i build it.
localStorage.setItem("thisConnectionHub",JSON.stringify(thisConnectionHub));
It is stored as below.
HubConnection is missing in this. Because of this i could not listen to any methods from server.
Any ideas how can i get this work.
Thanks,
If you want to use the same connection, you need to create a service that can be #injected in your components so you don't lose the context and can invoke the client side methods that instead will invoke the hub methods. This is called dependency injection. Your service will establish the connection on the application init and then other components would use the hubConnection methods that you will declare public or event implement an interface to do that.

Is it possible to create a global context available throughout the web application when i receive a message from Azure Service Bus?

I have a web api application which subscribes to a topic in azure service bus during startup.
When I receive a message from service bus, is it possible to establish a context similar to HttpContext that is available across the application methods?
There's not enough here to give you any exact direction, but in general, this just involves scopes. If whatever is listening for messages is has a "scoped" lifetime, then you can inject your context directly. If, as is more likely, it has a singleton lifetime, then you must instead inject IServiceProvider and retrieve your context via:
using (var scope = provider.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<MyContext>();
// do something with context
}
You can only use the context within the scope, so do not try to do something like store it in an instance variable or something.

SignalR hub is shortlived

I have a self hosted webApi project in a desktop C# application. This uses Microsoft.Owin.Hosting.WebApp.
I have a Hub derived class that has a send and a receive from an angular client.
The hub is instanced by the WebApp.start. I find that it is short lived. When the client sends a message, the hub is instanced and then disposed. I need to send message to the client, but I don't have an instance of the hub to send a message in the other direction.
At one point, I was holding a reference to the instance (as in memory leak) and I could get a message to the client.
The client shows as it is always connected. No disconnected messages.
What am I missing?
You should not hold this instance by yourself and you shold never create an instance by yourself.
Read the details about the hub onject life time here:
https://learn.microsoft.com/en-us/aspnet/signalr/overview/guide-to-the-api/hubs-api-guide-server#hub-object-lifetime
In the case you need to send a message to the connected clients you need to use GetHubContext.
Example:
var context = GlobalHost.ConnectionManager.GetHubContext<yourHub>();
context.Clients.All.Send("Something");
(In the case you are using core signalr read: Call SignalR Core Hub method from Controller)

SignalR - Sending from server-to-client from latest Hub context

I have a simple demo with only 1 client and the server. I can send messages back and forth, very trivial stuff.
The server Hub has a timer which sends a message to the client(s) every 1000 milliseconds. Now I have a button, where when clicked, sends a message to the server (via signalR).
Problem:
When the button is clicked (and the message sent to the server), the Hub is instantiated each time (I read about the SignalR lifecycle here).
Of course, when the Hub is instantiated the Timer is also instantiated. So the side effect (ie. bug) that I am seeing is that messages are being send to the client from multiple Hub instances.
What I would like:
I would like the client to receive messages (from the Timer that is running on the Hub), but only 1 set of messages from a single Hub (latest Hub instance?). I do not want simultaneous/multiple messages that were spawned from each Hub that was instantiated.
But perhaps I am doing something drastically wrong in design here.
You shouldn´t set the timer in the hub instance because they are re-created on every request.
Just create a Singleton class to handle the timer and actions. Then access that singleton from your hub instance.
The singleton instance will persist during the whole live cycle of your application, thus you will create only one timer.
To avoid concurrency problems, your singleton should be Lazy

SignalR request pipeline, Hub lifetime

I am starting on signalR with asp.net webapi, and I am trying to understand the whole signalR request/connection pipeline and what is the lifetime of the hub and who creates and dispose the hub instance (does it gets created on every communication between client and server?)
One of the reason is that we need to understand how we should be using an IoC contain in signalR request scenario, how we control the lifetime of the dependency correct specifically the ISession or DBContext.
Hubs instances are created at every single request from a client. They are not kept around, therefore you should not put any state in them.
Hubs are created through a factory system which you can customize through its built-in dependency injection mechanism.

Resources