storing signalr hub connection details in local storage - signalr

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.

Related

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 in multiple instances in Azure

I'd like to use Azure to host my web application, for instance CloudService web role or Azure Websites, inside the application I use SignalR to connect client and server.
Since I scaled two instances for my web roles, it seems I came across a very common problem, the SignalR could not find the correct original instance. The client JavaScript said it was already started, but the server hub OnConnected event randomly not raised, so were the server methods which intended to be called by clients, all these strange issues happened randomly.
Once I changed the instance to be one, all the problems gone. So can anyone explain what happened when the client call server method, why sometimes the server seems not response properly?
I found the post, can Azure Service Bus solve this issue?
Yes, you need to use the azure service bus. Otherwise the connections are stored in memory on the given server and the other server will know nothing about them. Once you create the service bus, just reference it in the startup class.
public void Configuration(IAppBuilder app)
{
System.Diagnostics.Trace.TraceInformation("SignalR Startup > Configurtion start");
// Any connection or hub wire up and configuration should go here
string connectionString = "XXX";
GlobalHost.DependencyResolver.UseServiceBus(connectionString, "TopicName");
...
}
You will also need to get a reference to the context in each of your hub methods:
var context = GlobalHost.ConnectionManager.GetHubContext<HubName>();
It's easy peasy :)

Getting specific hub instance associated with a specific SignalRConnectionId

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.

SignalR hosting on separate appPool

My web application have a chat app module built on SignalR hub.
The app will have 1000+ concurrent users. I want to host the Chat Module on a separate app pool to separate it from my main application so that SignalR does not bottleneck my main application.
I'm not sure how to go about it. I've built a simple Chat system (much like Google Talk) tied to my Main Web project using Hub class and client side code resides in Site Master since it will be common across the application.
i also want to be able to call Hub method outside the Hub class. For example, an admin might assign certain task to an user from admin panel. So, from the Controller method after completing service operation (task assignment) successfully, I want to send a SignalR message to that particular user. Should I be using Hub or Persistence connection to achieve both the goal? Host SignalR on a different port? I'd appreciate some guidance on this. Thanks!
Not that I think you necessarily have to do this, but I can understand the desire to separate. To do this you would have to have your MVC application call hub methods as if it was a SignalR client itself. You can either do this by putting separate methods on the same hub or by adding a secondary hub which exists solely for this kind of inter-app communication.
I would probably use the latter approach of having a second hub because you can secure it differently. If you go this route, you would simply get the HubContext for the primary hub and make whatever calls you want/fire whatever signals you want to it. That might look something like this:
public MyInterAppCommunicationHub : Hub
{
public void SendSystemAlert(string message)
{
HubContext myPrimaryHubContext = GlobalHost.ConnectionManager.GetHubContext<MyPrimaryHub>();
myPrimaryHubContext.Clients.systemAlert(message);
}
}

How can I Manually create a client proxy for a WF4 (xamlX) Service

I've created several services by wrapping the WorkflowServiceHost in a WCF service; using WorkflowHostingEndpoint. Doing this I was able to define my service contract and create proxy classes to connect to those services.
I'm now creating a service in which I want to use the WF4 messaging activities and again self host the service. I also REALLY want to manually create my proxy classes without using the ServiceReference in VS2010 or ServiceUtil...
I've seen some references that use the Send Activity in the Service client but I'd like to be able to use a more "WCF-like" proxy created directly against the service contract like I've done with the other services. How can I do that? Is there anywhere a xamlX (or xaml with messaging activities) stores the interface contract that I can use to generate a proxy manually?
NOTE: I don't want to use the Send activity as described in the WF_WCF_Samples.
UPDATE:
I tried creating an interface identical to the workflow receive activity before posting this question; but I keep getting the following error:
The message with Action 'http://tempuri.org/ISvrClientService/Create'
cannot be processed at the receiver, due to a ContractFilter mismatch
at the EndpointDispatcher. This may be because of either a contract
mismatch (mismatched Actions between sender and receiver) or a
binding/security mismatch between the sender and the receiver. Check
that sender and receiver have the same contract and the same binding
(including security requirements, e.g. Message, Transport, None).
Thanks!
There is no need to use the Send activity. When you host a workflow service you are hosting a SOAP endpoint, the only difference is the implementation but that is a private detail. You can create a proxy object using ChannelFactory just like with any other WCF service.
var factory = new ChannelFactory<IYourService>();
var proxy = factory.CreateChannel();
The IYourService interface is somethign you have to hand craft. There isn't one on the server, it is done in a workflow, so you have to code up the identical contract.
I've done this successfully with channel factory and manually created interfaces. The trick was in matching-up the reply/send in/out parameters names not just type signature.
This is particularly crucial if you have bookmarks with correlation in your workflow.

Resources