SignalR disconnect doesn't fire immediately - c#

I am trying to handle disconnect error with reconnection so I used the nextRetryDelayInMilliseconds method for reconnection, but in this case, if the connection is lost or there are some problems with the connection, the onclose handler does not work.
I am using "#microsoft/signalr": "^7.0.2" package in Angular project
I used "withAutomaticReconnect" option, but it doesn't fire immediately. I get a callback after some timeout.
Connection builder:
this.hubconnection = new HubConnectionBuilder()
.withUrl(url)
.withAutomaticReconnect({
nextRetryDelayInMilliseconds: () => {
this._errorState$.next(true);
return 1000;
}
})
.build();
Error handler (which doesn't fire if I use "withAutomaticReconnect"):
this.hubConnection.onclose(error => callback(error)
Expecting to handle the error immediately when there are some errors related to connection.

After test, I found the correct format should be like below.
connection.onclose(() => {
});
In your scenario, code should be
this.hubConnection.onclose((error) => {
console.error(`Something went wrong: ${error}`);
});
After testing, if you restart the signalr server, you may not get the error information, which should be normal. I don’t know if you can see more in the production environment. This is the standard usage, you can also refer to the following Link.
onclose event in signalr client
Suggestion:
The test above I test in signalr javascript client, and I also reproduce the issue, if it not works, please use #microsoft/signalr 7.0.0 version to troubleshoot problems caused by the new version.
I also using reconnectDelay property when build the connection.
var connection = new signalR.HubConnectionBuilder().withUrl("/mainHub")
.withAutomaticReconnect({
nextRetryDelayInMilliseconds: () => {
this._errorState$.next(true);
return 1000;
},
reconnectDelay: 500 // set the reconnect delay to 500ms
})
.configureLogging(signalR.LogLevel.Trace).build();

Related

Detect and handle when StrawberryShake Subscription connection wasn't successful

I have two asp.net applications running locally in development mode. One is running HotChocolate as the GraphQL server and working well. The second application is attempting to run StrawberryShake GraphQL client and access a subscription.
The StrawberyShake documentation is pretty sparse, especially with subscriptions and I'm unable to figure out how to know when a connection error happens. I've pasted below the code that shows what I've tried so far with no success. I've added comments to show what doesn't happen.
try
{
// client is the client auto-generated by StrawberryShake.
session = client.KeyRequest
.Watch(new ServerInfoInput
{
Name = "test",
MachineIdentifier = "machine",
}).Subscribe(result =>
{
// A breakpoint in here never gets hit.
var data = result.Data;
}, () =>
{
// This writeline never gets hit.
Console.WriteLine("Complete");
});
}
catch (Exception e)
{
// An exception is never thrown.
Console.WriteLine(e.ToString());
}
In conclusion, is there a way to know if my connection to the server was successful?

SignalR client does not call the reconnecting event when the Server shuts down, or restarts

I created a hubConnection, and added the .WithAutomaticReconnect() so when the connection is lost it will automaticaly reconnect. When testing i wrote the .Reconnecting event, and when i stop the server, the client signalR connection is going immediately in the Disconnected state, and in the Closed event without going in the Reconnecting event, and does not reconnect. This is only when i stop the server, if the server is not stoped, and the connection is somehow lost, it does try to recconect and it goes in the Reconnecting event. So, why the Reconnecting event is not fired when i stop the server?
I am asking this because i want to make sure the client will reconnect even if I restart the server after some updates. With only the .WithAutomaticReconnect() method, the client does not reconnect if the server was restarted.
This is my code for the signalR connection build:
_hubConnection = new HubConnectionBuilder().WithUrl(Url, options =>
{
options.AccessTokenProvider = () => Task.FromResult(token);
})
.WithAutomaticReconnect()
.Build();
I am working with signalR 3.0 and have a .net core console app as client.
This happens because when you stop the server, it sends the event that the server stooped the connection so this is no connection lost caused by client or the network, so there is no sense to reconnect because it was "purposed" connection end.
So, if you still want to reconnect when you turn of the server, you need to implement the it by yourself. When the server disconnects you will catch the error and you can try to connect again. See this example:
private async connectSignalR() {
await this.hubMessageConnection.start()
.then(() => {
this.doSomething();
}).catch(() => {
this.onError.emit(WidgetStateEnum.connectionClose);
});
}
private configureSignalR(signalRUrl: string, token: string) {
this.hubMessageConnection = new signalR.HubConnectionBuilder()
.configureLogging(signalR.LogLevel.Error).withUrl(signalRUrl + "/yourHubEndpoint",
{
accessTokenFactory: () => token
})
.withAutomaticReconnect()
.build();
this.hubMessageConnection.onclose(() => {
this.connectionClose();
});
}
private connectionClose() {
this.onError.emit(WidgetStateEnum.connectionClose);
this.doSomethingWhenConnectionIsClose();
}.catch(() => {
this.onError.emit(WidgetStateEnum.connectionClosed);
});
}

SignalR Send method not firing while trying to poll for existing connections

I'm using the latest version of SignalR with jQuery and getting some odd behavior where a user disconnects, but still hangs around in my "UserQueue" despite having disconnected.
I think this may be related to the fact that a page refresh appears to trigger the OnDisconnected and OnConnected events almost simultaneously. When I set a break point in one of these methods and step through, my pointer bounces back and forth between the two methods with each step (F10).
I'd like to run a check with each OnConnected event to find out who is actually connected to my app. I want to fire a JS event from my C# code in the OnConnected event, and then allow the client/front end to fire back a confirmation of the user being present:
public override Task OnConnected()
{
// Check for other users:
Clients.All.checkForOtherUsers();
// Do stuff with my user queue
var curmodelId = GetModelId(Context);
var curUserConnection = GetCurrentUser(Context);
// First create the ledger is missing, setting the modelId as the first key
if (_ledger == null)
{
_ledger = new ConnectionLedger(curmodelId, curUserConnection);
}
else
{
// key not found, create new connection pool this model
if (!_ledger.PoolIds.Contains(curmodelId))
{
_ledger.AddConnectionPool(curmodelId, curUserConnection);
}
else
{
var curModelPool = _ledger.ConnectionPools.First(x => x.Id == curmodelId);
curModelPool.UserQueue.Enqueue(curUserConnection);
}
}
return base.OnConnected();
}
Now in the client JS, if I have this code:
modelHub.client.checkForOtherUsers = function () {
// I can see logging here if I add console.log("checking for other users...")
modelHub.server.send();
}
...I'm expecting my C# Send method to receive back the context (if the user is actually present at the client for the JS to execute) and update my UserQueue:
public void Send()
{
var curmodelId = GetModelId(Context);
var curModelPool = _ledger.ConnectionPools.First(x => x.Id == curmodelId);
var curUserConnection = GetCurrentUser(Context);
curModelPool.UserQueue.Enqueue(curUserConnection);
}
... but my Send method never gets fired, even when I fire it from the JS Console directly $.connection.modelingHub.server.send().
Why doesn't the Send method fire? Is there something about the order of events / async nature of the SignalR library that causes this?
Comments on the overall design are welcome too (since I suspect it could be stupid), but note that I cannot access Context.User or Clients.User because of my customized Authentication config.
Seems to be two causes below.
Server-side
Not good to call Clients.All.checkForOtherUsers(); within OnConnected().
I would recommend calling it after connected.
Please refer to SignalR - Send message OnConnected
Client-side
Might need to regist modelHub.client.checkForOtherUsers = function () { before calling start method.
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. - How to establish a connection

Simple.OData BeforeRequest event not triggered

I'm using the Simple.OData adapter to try to connect to an OData service. The service needs authentication to connect.
I have registered the BeforeRequest event to set the neccesary headers before doing any request.
However, my BeforeRequest is not triggered at all which results in not being able to open the Context, due too missing credentials and my code hangs and waits forever.
See my code below, am I missing something?
public void GetData()
{
var oDataFeed = new ODataFeed(ApiBaseUrl);
oDataFeed.BeforeRequest += BeforeRequest;
oDataFeed.AfterResponse += AfterResponse;
Context = Database.Opener.Open(ApiBaseUrl);
// do some more
}
private void BeforeRequest(HttpRequestMessage httpRequestMessage)
{
// add headers.
}
It did seem to fire or trigger the event once, however, after a rebuild of the project it doesn't work anymore.
There is a know bug in Simple.Data.Client 3x that affects request interception in certain scenarios. The bug is fixed in the forthcoming version 4 of Simple.OData.Client, currently available as pre-release but it's very stable and comes with tons of new features including support for JSON payload and OData protocol V4.

SignalR in SL5 stops working after upgrade to 1.0.1

I have a simple Hub that was working with 1.0.0-rc2 between my web app and my SL5 application.
After upgrading to 1.0.1, my .Net Winform clients can still connect to the hub, but my SL5 client can no longer connect.
Upon calling Subscribe, I can see the Negotiate call in Fiddler (which returns 200, with what appears to be valid JSON), followed by the hub Closed event firing. The Error event never fires, and then that's the end of it. There is no attempt to actually connect, at least as far as I can tell in Fiddler.
Any ideas? Here's my SL5 code, it's pretty simple/straight forward.
hub = new HubConnection("http://localhost/ADE");
hub.Closed += new Action(hub_Closed);
hub.Error += new Action<Exception>(hub_Error);
hub.Reconnected += new Action(hub_Reconnected);
hub.Reconnecting += new Action(hub_Reconnecting);
hub.StateChanged += new Action<StateChange>(hub_StateChanged);
hubProxy = hub.CreateHubProxy(hubName);
//Removed my hubProxy.On calls for brevity.
hub.Start().ContinueWith(task =>
// {
//});
Try this sample that is using SignalR1.0.1 and SL5.
To access SL5 client navigate to http://localhost:18628/SignalR.Sample.SilverlightClientTestPage.aspx
On Fiddler, you should get these http requests
http://localhost:18628/signalr/negotiate?noCache=cd92304d-c824-4c91-abdd-e77c8d096b58
http://localhost:18628/signalr/connect?transport=serverSentEvents&connectionToken=rse-NdoiZ1Hi7riN_beL6J-zrkGMPm1A9p8urTZn_1sTuZVeEzVWayykaN-Km_fmqBoV06D1e7h5fPWl4kgggABs3x7wiItdd8zJKE9FSCjZsYEUQOdFrzAg-WmA7rUx0&connectionData=[{"Name":"SampleHub"}]&noCache=0c4c1fa1-9aa9-409b-acf7-165faa0d699a
http://localhost:18628/signalr/send?transport=serverSentEvents&connectionToken=rse-NdoiZ1Hi7riN_beL6J-zrkGMPm1A9p8urTZn_1sTuZVeEzVWayykaN-Km_fmqBoV06D1e7h5fPWl4kgggABs3x7wiItdd8zJKE9FSCjZsYEUQOdFrzAg-WmA7rUx0

Categories