Signalr server side, OnDisconnect only called for 1 hub - signalr

I am writing a web application an it uses SignalR. On the server c#, I have two hubs.
It really does need to be two otherwise I would just merge them and solve the problem.
The problem that I am having, is that while I am aware that SignalR client side, hubs
will share a connection. The issue I am having, is that when I close the browser, or call stop on the client. Only 1 of my server side OnDisconnect(bool stopCalled) events will fire.
I somehow expected that both would fire when the client disconnects.
Am I being silly or doing something wrong perhaps?
Any info will be greatly appreciated.
Louis

I think the problem you are experiencing might be due to you not hooking up any event handlers (i.e. client hub methods) to the Hub that isn't triggering OnDisconnected. If this really is the cause, OnConnected also shouldn't be triggered on the same Hub.
The SignalR Hubs API Guide for the JavaScript client goes into some detail in one of its "notes" about why this is the case. Here's the relevant quote:
Note: Normally you register event handlers before calling the start method to establish the connection. If you want to register some event handlers after establishing the connection, you can do that, but you must register at least one of your event handler(s) before calling the start method. One reason for this is that there can be many Hubs in an application, but you wouldn't want to trigger the OnConnected event on every Hub if you are only going to use to one of them. When the connection is established, the presence of a client method on a Hub's proxy is what tells SignalR to trigger the OnConnected event. If you don't register any event handlers before calling the start method, you will be able to invoke methods on the Hub, but the Hub's OnConnected method won't be called and no client methods will be invoked from the server.
Every reference to the OnConnected method applies equally to the OnDisconnected method.
You can add an arbitrary event handler to your Hub before calling start() on the client to ensure that OnConnected and OnDisconnected get called on that Hub. It doesn't matter if the event handler will never be called. Ex:
$.connection.myHub.client.thisWillNeverBeCalled = function () { };
$.connection.hub.start()//...
As long as the first line is there, OnConnected and OnDisconnected should be called on MyHub.

In the end, after almost 2 days troubles shooting and browsing the web for answers.
I ended up just merging the two hubs into a single hub. It might not be the most elegant solution, but it did get the job done and progress can now be made on the rest of the app.
Thanks for the advice though from everyone :)
Louis

Related

Long Polling does not hit hub class?

When the browser says long polling but the debugger in the constructor of hub class does not hit. What is the problem?
Basically what I want is everytime the long polling happens, I also want a particular functionality like a database call to be executed.
poll requests are receive channel (i.e. are only used by the server to send data to the client if there is any) and as the result they don't cause instantiating hubs. However you can override the ProcessRequest method on the server side - it is being called for each HTTP request the server is receiving so you can do whatever you want there.

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

Invoke client side method synchronously with SignalR

How can the web server invoke a method on the client synchronously using SignalR? The key part here is that the server should wait for client to send data back to the server before continuing on?
Basically I'm looking to treat a client method invoke like a WCF service request. Invoke the client and wait for the data to be returned.
SignalR does not provide a way to synchronously invoke client-side methods.
To achieve the same functionality as a synchronous call, you could pass some sort of invocation ID as an argument to your client-side method. The client could then invoke a server-side method like ClientMethodCompleted with its invocation ID when the client-side method is done. Basically you will be implementing your own ACK.
If you go this route, you will have to track the client invocations along with their respective ID's on the server. You can then execute whatever logic you would have done after a synchronous call in the ClientMethodCompleted method on the server.
This should be fairly simple if you are invoking the method on only one client. If you are invoking the method on multiple clients you will have to keep track of which clients you are invoking your method on so you can ensure all the clients have acknowledged the invocation before running your followup code.
I would also make sure that you periodically clean up the data structure storing unacknowledged client invocations if you are at all worried about a DOS attack, since this would be an obvious attack vector that could allow a malicious client blowup memory consumption.

Understanding how netty works

I'm trying to understand how netty works, and after reading some of the documentation I was to see if I understood how things work at a high level.
Basically netty has an event cycle, so whenever you make a call it gets serialized and the request gets pushed down to the o/s level, and it uses epoll and waits for an event to send back to netty.
When the operation system generates an event that netty subscribed to, netty then has an event loop that gets triggered.
Now the interested part here is, the event that gets triggered has to be parsed, and the client code (or custom code) has to figure out who actually this event is for.
So for example, if this was for a chat application, when a message is sent, it is up to the client code to figure out to send this message via ajax to the correct user.
Is this, at a high level, a correct overview of how netty works?
BTW, when netty listens for events sent via epoll, is this event loop single threaded or does it work from a pool of threads?
Sounds correct to me.
There are more than one event loop thread in Netty, but it does not mean a single Channel's event is handled by multiple event loop threads. Netty picks one thread and assigns it to a Channel. Once assigned, all events related with the Channel is handled by the picked thread.
It does not also necessarily mean that an event loop thread handles only one Channel. An event loop thread can handle multiple Channels.

alert session end with server sent events

I want to send a message to the client when the ASP.NET session ends. I did not want to use timers so I tried using "server sent events" to call the client from the session_end event in global.asax. Is there a way to call a specific client from global.asax? I tried using the 'SignalR' library for this propose, but had problems calling a specific client from Global.asax (I have managed to call a group of clients but not a specific client)
What are the best practices for this propose?
I'm not sure if this is what you need, but does this help?
(Of course you don't need to use DevExpress for this, you can implement your own popup window)

Resources