SignalR how to reconnect with same connectionId #54818
Replies: 5 comments 24 replies
-
Beta Was this translation helpful? Give feedback.
-
|
As a workaround you should be able to use |
Beta Was this translation helpful? Give feedback.
-
|
Hi @BrennanConroy, I have also been unable to get stateful re-connect to work as far as I understand it should work. I have setup a sample here The steps I am using to work with the sample are as follows:
Please can you confirm if there is something which I have done incorrectly, or if my expectations of how this feature works is incorrect. Thanks in advance! |
Beta Was this translation helpful? Give feedback.
-
|
Hi @BrennanConroy, like the posters before me, I cannot get stateful reconnect to work: the The automatic reconnect kicks in after the serverTimeout is exceeded, but the response always contains a different This is simple to verify by configuring the client's
On the server side, a simple (This wasn't the only way I tested, also happens with regular timeouts and throttling in DevTools to block server KeepAlive pings until the serverTimeout is hit) If maintaining the Connection ID is not a goal of stateful reconnect, then what is the purpose of the feature? |
Beta Was this translation helpful? Give feedback.
-
|
FWIW, I did some digging around in the source and found confirmation that re-using the /// <summary>
* /// If set, the connection should attempt to reconnect with the same <see cref="BaseConnectionContext.ConnectionId"/> if it disconnects.
/// It should also set <see cref="IStatefulReconnectFeature"/> on the <see cref="BaseConnectionContext.Features"/> collection so other layers of the
/// application (like SignalR) can react.
/// </summary>
public bool UseStatefulReconnect { get; set; } /// <summary>
/// Setting to enable Stateful Reconnect between client and server, this allows reconnecting that preserves messages sent while disconnected.
* /// Also preserves the <see cref="HttpConnection.ConnectionId"/> when the reconnect is successful.
/// </summary>
/// <remarks>
/// Only works with WebSockets transport currently.
/// </remarks>
public bool UseStatefulReconnect { get; set; }However in HttpConnectionManager a new ID is always generated (and a new internal HttpConnectionContext CreateConnection(HttpConnectionDispatcherOptions options, int negotiateVersion = 0, bool useStatefulReconnect = false)
{
string connectionToken;
var id = MakeNewConnectionId();
if (negotiateVersion > 0)
{
connectionToken = MakeNewConnectionId();
}
else
{
connectionToken = id;
}
var metricsContext = _metrics.CreateContext();
Log.CreatedNewConnection(_logger, id);
var pair = CreateConnectionPair(options.TransportPipeOptions, options.AppPipeOptions);
var connection = new HttpConnectionContext(id, connectionToken, _connectionLogger, metricsContext, pair.Application, pair.Transport, options, useStatefulReconnect);
_connections.TryAdd(connectionToken, connection);
return connection;
}The HttpConnectionDispatcher calls this method; it does have a GetConnectionToken method and uses it in one instance to obtain an already existing connection: private static StringValues GetConnectionToken(HttpContext context) => context.Request.Query["id"];
// [...]
// This is only used for WebSockets connections, which can connect directly without negotiating
private async Task<HttpConnectionContext?> GetOrCreateConnectionAsync(HttpContext context, HttpConnectionDispatcherOptions options)
{
var connectionToken = GetConnectionToken(context);
HttpConnectionContext? connection;
// There's no connection id so this is a brand new connection
if (StringValues.IsNullOrEmpty(connectionToken))
{
connection = CreateConnection(options);
}
// Use ToString; IsNullOrEmpty doesn't tell the compiler anything about implicit conversion to string.
else if (!_manager.TryGetConnection(connectionToken.ToString(), out connection))
{
// No connection with that ID: Not Found
context.Response.StatusCode = StatusCodes.Status404NotFound;
await context.Response.WriteAsync("No Connection with that ID");
return null;
}
return connection;
}I have no experience with the whole code base, but it seems to me that all the pieces may be there and the feature just hasn't been fully implemented? In the TS client, resolveNegotiateUrl appends the My point / question is, could not the |
Beta Was this translation helpful? Give feedback.




Uh oh!
There was an error while loading. Please reload this page.
-
Hi everyone, my question is related to signalR.
I have a long-running task on Hub and after it is complete, the hub will send a response base on Clients.Caller.SendAsync method
But currently, while running, it look like that hub doesn't send keep-alive message to client and after ServerTimeout (default is 30s), the connection will timeout and reconnect cause I config WithAutomaticReconnect() on client.
But when after reconnecting, the connection comes with difference connectionId so it can't listen to messages from server which send to old connectionId
I understand that there are Groups and Users to handle this scenario, but perhaps there is an alternative approach to retaining the connection ID after reconnecting?
Thank you!
Beta Was this translation helpful? Give feedback.
All reactions