My ASP.NET Web API (target framework: .NET Framework 4.6.2) project frequently loses connection with Azure SignalR service (free tier). I have followed the example as shown in aspnet ‘chatroom’ example.
My client application is based on Angular JS. Messages are being send to the clients but after a few hours, the server connection with Azure SignalR service is lost and is not established again.
As far as I understand from the MS Azure SignalR Internals documentation:
If a server connection is disconnected for network issue,
the server connection starts reconnecting automatically.
The following error is returned back in response:
Azure SignalR Service is not connected yet, please try again later
However, this does not seem to be happening i.e. server connection with Azure SignalR service is not established again.
nuget packages:
Microsoft.AspNet.SignalR v2.4.0
Microsoft.AspNet.SignalR.Core v2.4.0
Microsoft.AspNet.SignalR.SystemWeb v2.4.0
Microsoft.Azure.SignalR.AspNet v1.0.0-preview1-10317
Microsoft.Azure.SignalR.Protocols v1.0.6
There is currently an issue with Microsoft.Azure.SignalR.AspNet v1.0.0-preview1-10317. The fix is planned to be released this week.
Have you added error handling code in your client like below-
// Define handlers for any errors
//
this.hubConnection.error((error: any) => {
// Push the error on our subject
//
this.hubConnection.start()
.done(() => {
this.startingSubject.next();
//Invoke connect method on Hub
// this.hubProxy.invoke("Connect", userId, usertype);
})
.fail((error: any) => {
this.startingSubject.error(error);
});
});
Also in case of closed connection code would be like
this.hubConnection.onclose(() => {
setTimeout(function(){
this.hubConnection.start()
.done(() => {
this.startingSubject.next();
//Invoke connect method on Hub
// this.hubProxy.invoke("Connect", userId, usertype);
})
.fail((error: any) => {
this.startingSubject.error(error);
});
},3000);
});
Hope it helps.
MV
Related
I implemented JsonTranscoding
in my simple gRPC
application. I've a POST
api. When I test my POST
api using swagger, I could call it; but when I test it using Postman or
HttpClient (Acually calling api using code) I get two below exception:
IOException: Unable to read data from the transport connection: An established connection was aborted by the software in your host machine.
and also:
SocketException: An established connection was aborted by the software in your host machine.
*** I have no firewall on my local machine.**
I figured out that my gRPC service does not support HTTP request and this makes problem. so I cofigured it to support HTTP1 and HTTP2. There is two ways to configure it:
Adding below code in Program.cs :
builder.WebHost.ConfigureKestrel((context, options) =>
{
options.ListenAnyIP(7013, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
listenOptions.UseHttps();
});
});
or in appsettings.json :
"Kestrel": {
"EndpointDefaults": {
"Protocols": "Http1AndHttp2"
}
}
We currently have a Web Application, a SignalR Server and a RabbitMQ Server. The Web application receives events from SignalR based on the events received via RabbitMQ. Our Web Application has a fallback which, in case the connection to SignalR closes and can't be established, has a polling mechanism to try to keep the data updated.
The problem: If, instead of the SignalR server, the RabbitMQ is having issues, then, from the perspective of teh WebApplication it is still connected to SignalR server, which prevents it from polling data.
The possible solution: On the event of the RabbitMQ Server has issues connecting to SignalR, we would like to the SignalR server to actively refuse connections on a specified Hub and terminate all the connections it has.
Based on that i tried the following approach (inside the specified Hub), but no success:
public async override Task OnConnectedAsync()
{
var feature = Context.Features.Get<IConnectionHeartbeatFeature>();
feature.OnHeartbeat(state =>
{
try
{
if (rabbitMQWorker.IsConnected == false)
Context.Abort();
}
catch
{
}
}, Context.ConnectionId);
await base.OnConnectedAsync();
}
Even if it worked, I would still need to refuse any connections. Is this something feasable or am I heading towards the wrong direction?
I created a very simple ASP.NET Core app with SignalR with Visual Studio using a Web App MVC application template with the following customization:
added a reference to #microsoft/signalr library via libman,
referenced <script src="~/lib/microsoft-signalr/signalr.min.js"></script> in _Layout.cshtml,
added the required SignalR services in Startup.cs and created an empty Hub, exposed in the following way:
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<MyHub>("hub/remote");
// ... MVC router definitions
}
created the SignalR connection in JS:
const connection =
new signalR.HubConnectionBuilder()
.withUrl("/hub/remote")
.configureLogging(signalR.LogLevel.Trace)
.withAutomaticReconnect()
.build();
connection.start().then(() => console.log("Connected."));
Then I launched the MVC app and everything started without an error.
However, I took a closer look at SignalR log messages:
I believe this is the SignalR's internal heartbeat that keeps the connection alive.
I wonder why does it take 4-5s between sending the message and receiving the response?
I also tried using SignalR in a more complex application and from time to time I even started receiving "Reconnecting" events, as the load was significantly larger there.
That makes me feel that I do something wrong while configuring the connection, but no idea what exactly.
"Connection Slow" isn't an event in ASP.NET Core SignalR.
The heartbeats are not directly related to each other, so the gaps between client and server pings are normal.
Background:
I would like to connect to my SignalR hub using Xamarin forms SignalR websocket transport.
My setup:
-> SignalR hub is sitting on a Windows VM. I am connecting to the VM using the iphone simulator on Mac.
-> I have created a reverse proxy rule on iis for my self hosted SignalR hub.
-> I have added an entry to my hosts file to connect to the Hub.
What is going wrong?
I am able to succesfully connect to the Hub however the issue is that the transport is always set to Server Sent Events. This should be using WebSocket transport.
What have I tried?
I have created a web client and I was able to successfully run that, initially connecting on a http request, and after negotiation the message upgraded to WebSocket.
The difference between the two connection is one is using Javascript and Websocket support on a browser, where as Xamarin forms is using a nuget package AspNetCore.SingalR.Client.
I understand on Xamarin, the connection will first try connecting using WebSocket, then Server Sent Request and if the previous two fail long polling. But as far as I understand Mono is now able to support websocket.
Xamarin client connection code (A quick write up to test that WebSocket transport works on Xamarin forms):
public class PriceStream
{
readonly HubConnection connection;
public PriceStream()
{
connection = new HubConnectionBuilder()
.WithUrl("https://dev.prices:5001/priceHub")
.Build();
connection.On<TestObject>("ReceiveMessage", (data) =>
{
var priceUpdate = new PriceUpdateMessage
{
ProductId = data.ProductId,
PriceId = data.PriceId,
Price = data.Price
};
// update price on app
// TODO
});
}
public async Task SubscribeAsync(int productId)
{
// connecting here because I want to see the transprot before sending message
await connection.StartAsync();
await connection.SendCoreAsync("SendMessage", new[] { productId });
}
}
So what am I missing that it is not able to connect using WebSocket transport?
I'm trying out the latest SignalR on ASP.NET Core 2.1. I have the basic app working but it times out pretty soon right now. I see this error -
Error: Connection disconnected with error 'Error: Server timeout elapsed without receiving a message from the server.'.
Where can this timeout setting be changed? I tried the docs here but no info about timeout there.
I'm running on a dev environment of Windows 10 and using JavaScript client.
Edit: Inserting image after enabling client logging.
Edit 2: Link to page containing timeouts about the older SignalR version.
For people that may come here in future:
Here is how to increase Javascript client timeout
hubConnection.serverTimeoutInMilliseconds = 100000; // 100 second
But also take a look at this link and then read my comments below:
If signalR got disconnected, you should try re-establishing the connection again. The connection could drop for several other reasons, including the user switching networks. For example if the user is using a cell-phone and connected to the home/office wifi but steps out which then connects to cellular data connection.
To reconnect you could use the following (works like a charm for me):
// re-establish the connection if connection dropped
connection.onclose(() => setTimeout(startSignalRConnection(connection), 5000));
where startSignalRConnection is :
const startSignalRConnection = connection => connection.start()
.then(() => console.info('Websocket Connection Established'))
.catch(err => console.error('SignalR Connection Error: ', err));
and connection is
const connection = new HubConnectionBuilder()
.withUrl(connectionHub, options)
.withHubProtocol(protocol)
.build();
in startup.cs
services.AddSignalR(hubOptions =>
{
hubOptions.EnableDetailedErrors = true;
hubOptions.KeepAliveInterval = TimeSpan.FromMinutes(60);
})
The following worked for me.
Put the below code in the Javascript client.
// Connecting to the signalR
var connection = new signalR.HubConnectionBuilder().withUrl(huburl + hubname).build();
// Setting the connection timeout
connection.serverTimeoutInMilliseconds = 180000; // 3 mins