SignalR connection disconnects upon OnBeforeUnload - signalr

I'm having C# self hosted server application using SignalR.
My client is SPA (angualr,javascript HTML5).
My application have some termination process which should run when leaving the page (running when OnBeforeUnload occurs and the user asks to leave...).
The termination process contains some server calls.
Till today I worked with WebSockets and all worked well. I'm now trying to deploy my application on a server machine that doesn't support WebSockets so I'm using SignalR instead.
My problem is that SignalR closes/disconnects the connection when "OnBeforeUnload" happens. This means that I can't perform the termination process.
I tried to workaround this by creating new connection but it also fails to open.
Is there a way to overcome the above problem?
thanks,
R.

You can use the connection lifetime event OnDisconnected instead of making an explicit call to the server. Using OnBeforeUnload for asynchronous code is not a good idea in general.

Related

Configuring Azure's Event Hub to receive events from ASP.NET MVC web application

Can someone point me in the right direction on how to configure network settings within event hub so i can successfully send data via the ASP.NET MVC application while running locally (localhost) as well as when I deploy the application in azure's dev/qa/production web environment.
I have build a proof of concept console application in .NET locally and on Azure's EventHub side added my IP address within Networking/Firewall settings, and have no issue sending data and receiving data from a local machine.
But when I try the same code in the ASP.NET MVC web application, the page just hangs on CreateBatchAsync() method and does not return any exception..
var producerClient = new EventHubProducerClient(connectionString, eventHubName);
EventDataBatch eventBatch = await producerClient.CreateBatchAsync();
eventBatch.TryAdd(new EventData(Encoding.UTF8.GetBytes("Event 1z at " + DateTime.Now.ToString())));
await producerClient.SendAsync(eventBatch);
Any help would be appreciated.
Thanks
The call to CreateBatchAsync is the first point in your code to request a network operation and, consequently, will trigger creation of the connection and link to the Event Hubs service. The connection attempt has a timeout associated with it which is 60 seconds in the default configuration that you're using. Depending on the error that it is encountering, you may see retries take place, each of which would have a 60 second timeout. With the default configuration, this would look like a 3 minute hang. (60 seconds * 3 attempts)
The most common connection issue in an enterprise environment is that the ports needed for AMQP over TCP (5671/5672) are not open. Changing the transport to AMQP over WebSockets often helps, as it will use port 443 and may be routed through a proxy, if needed.
For more information, you may want to look at the sample for configuring Event Hubs clients and the Event Hubs network troubleshooting guide.

SignalR and Web API communication

In one server, I have 2 web applications. One of them is a Web API, and the other one is SignalR. Both apps are hosted in IIS, under 2 different application pulls.
What is the best way to communicate between those 2 web applications? Is using either SignalR, or REST calls viable, for example?
You can use several way;
1) A message queue system would work. Your server is IIS, you can use MSMQ.
2) Alternate to MSMQ, you can use RabbitMQ.
3) As you mentioned, you can use HTTP calls.
4) You have already a SignalR. So you can use it for communication. Write a Hub that the servers join to hub.
Options are depends on your requirement. Backend servers, mostly, communicate with a message queue system. HTTP calls are also acceptable.
The biggest difference between HTTP and a message queue is async calls. For example, When a HTTP call trying to reach an endpoint, it waits for a response and if the server is down, you have to try again until server up. On the other hand, a message queue system uses a queue. Just fire and forget the data. Other side of the connection can get the data whenever the server is ready.
SignalR is too risky for this job.

How to get SignalR Connection to Respect Session Timeout

Using SignalR, it's designed to maintain a long-running connection to the web server. However, I have a scenario where the SignalR connection maintains an open connection to the web server, long after the ASP.Net session has expired. This happens even though neither the client nor the server is sending an data.
How can I set things up so that once the Asp.net session expires, the SignalR connection terminates, freeing up connections on the server?
This is desired because the web servers run on a load balancer, and when taking a server out of the rotation, we need the # of current connections to generally represent the number of active sessions - not SignalR connections that are still kicking just because user left browser open.
SignalR Server does not allow to disconnect a particular client connection (this would be super useful). So the client is responsible to do that.
A workaround would be to add an event listener on the client and disconnect from there, i.e:
hubProxy.On<string>("YouAreUselesLetMeAlone", _ => connection.Dispose());
Obviously, to make this work you need a relation (ConcurrentDictionary?) of asp.net sessions <-> signalr connections, so you can call this method in the correct client when the asp.net session ends.

How does Signal-R fit in the IIS activation model?

I am learning Signal-R, and this is something that has been in my head during all time.
How does Signal-R fits in the IIS/ASP.NET life cycle?
How long does the Hubs live (I see they have re-connection semantics)?
Does IIS does prevent the shutdown of an AppDomain that has a persistent connection?
It is my understanding that IIS is designed to handle request-response scenarios. A request hits IIS, this finds the AppDomain, activate it, and then pass the request to it. And after an idle time, shutdown the AppDomain. If the request takes too long, a timeout exception is thrown.
Now let´s imagine that I have another application that broadcast information through a TCP socket. I want my javascript clients to get that information in real time, so I create a Signal-R web application. I can create a TCP client on application start, but what does guarantee that IIS is not going to shutdown the whole thing after some time with inactivity?
I could self host the Signal-R app in a window service, but then I would have to use a different port, enable cross domain, etc... Many problems for deployment. But, I am concerned about using an ASP.NET MVC application for this, since it looks to me like fitting a driving wheel in a motorbike.
Cheers.
SignalR in IIS/ASP.NET Lifecycle
SignalR uses Owin: http://owin.org/
A good article on Owin here: http://msdn.microsoft.com/en-us/magazine/dn451439.aspx
Hub object lifetime
From the SignalR docs: http://www.asp.net/signalr/overview/signalr-20/hubs-api/hubs-api-guide-server#transience:
You don't instantiate the Hub class or call its methods from your own code on the server; all that is done for you by the SignalR Hubs pipeline. SignalR creates a new instance of your Hub class each time it needs to handle a Hub operation such as when a client connects, disconnects, or makes a method call to the server.
Because instances of the Hub class are transient, you can't use them to maintain state from one method call to the next. Each time the server receives a method call from a client, a new instance of your Hub class processes the message. To maintain state through multiple connections and method calls, use some other method such as a database, or a static variable on the Hub class, or a different class that does not derive from Hub. If you persist data in memory, using a method such as a static variable on the Hub class, the data will be lost when the app domain recycles.
Your long running TCP client
This is not a problem with SignalR. Your TCP client can be shutdown by IIS: http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx/
I would rather make the TCP client run in a windows service. The TCP client receives TCP broadcast messages and forwards the messages to the Hub using the SignalR .NET client.
Hubs are recreated on each SignalR request, so if you need a persistent connection you may have to look into using static vars or dictionary to hold state. But as you point ASP.NET can restart for a variety of reasons.
It depends on what persistancy you really need. If you have a connection that MUST stay alive at all times and cannot be torn down and reestablished then hosting in IIS is not the right choice. However, if you can re-establish the same connection after a shutdown, then maybe this can still work.
You can do quite a bit in making sure that ASP.NET apps don't shut down in recent versions of IIS:
http://weblog.west-wind.com/posts/2013/Oct/02/Use-IIS-Application-Initialization-for-keeping-ASPNET-Apps-alive
If that's not enough for you running as a separate service is an option. If you run as a service on the same IP address there are no cross domain concerns. Here's more info on running SignalR using a Windows Service:
http://weblog.west-wind.com/posts/2013/Sep/04/SelfHosting-SignalR-in-a-Windows-Service

ASP.NET network issue

So i want to to create a web application using asp.net to connect to another application (for example a simple windows form) using sockets. The problem is i'm behind firewall and i don't have the authority to mess with the firewall settings, what other options can i do besides sockets?
My application is fairly simple, the web application will be hosted on the internet and has a "connect" button, when its click it establish connection with the windows form that is on another computer and display the message "Connected" if its connected. All this will be tested behind some kind of corporal firewall. How do i get around this?
The firewall is there specifically to stop this kind of thing.
The bestway around it would be to have the Forms app poll the server for connectivity - this can be made to look near real time by making the server receive the request, then wait until it gets a connect action, or time out after a few minutes and return nothing. Then the forms app would request again.
I think instead of using directly a web application, you should look forward to create a web service to solve both the purposes. You can have its reference in both of them. your Web Form will make a request to connect to the web service instead of application. That will solve both purposes.

Resources