diff --git a/src/SignalR/clients/csharp/Client.Core/src/HubConnectionBuilder.cs b/src/SignalR/clients/csharp/Client.Core/src/HubConnectionBuilder.cs
index 54b33e572446..b9910ea786c8 100644
--- a/src/SignalR/clients/csharp/Client.Core/src/HubConnectionBuilder.cs
+++ b/src/SignalR/clients/csharp/Client.Core/src/HubConnectionBuilder.cs
@@ -21,6 +21,22 @@ public class HubConnectionBuilder : IHubConnectionBuilder
///
public IServiceCollection Services { get; }
+ ///
+ /// Gets or sets the server timeout interval for the connection.
+ ///
+ ///
+ /// The client times out if it hasn't heard from the server for `this` long.
+ ///
+ public TimeSpan? ServerTimeout { get; set; }
+
+ ///
+ /// Gets or sets the interval at which the client sends ping messages.
+ ///
+ ///
+ /// Sending any message resets the timer to the start of the interval.
+ ///
+ public TimeSpan? KeepAliveInterval { get; set; }
+
///
/// Initializes a new instance of the class.
///
@@ -52,7 +68,19 @@ public HubConnection Build()
var endPoint = serviceProvider.GetService() ??
throw new InvalidOperationException($"Cannot create {nameof(HubConnection)} instance. An {nameof(EndPoint)} was not configured.");
- return serviceProvider.GetRequiredService();
+ var hubConnection = serviceProvider.GetRequiredService();
+
+ if (ServerTimeout.HasValue)
+ {
+ hubConnection.ServerTimeout = ServerTimeout.Value;
+ }
+
+ if (KeepAliveInterval.HasValue)
+ {
+ hubConnection.KeepAliveInterval = KeepAliveInterval.Value;
+ }
+
+ return hubConnection;
}
// Prevents from being displayed in intellisense
diff --git a/src/SignalR/clients/csharp/Client.Core/src/PublicAPI.Unshipped.txt b/src/SignalR/clients/csharp/Client.Core/src/PublicAPI.Unshipped.txt
index 40077fde5c02..7717d245a8a5 100644
--- a/src/SignalR/clients/csharp/Client.Core/src/PublicAPI.Unshipped.txt
+++ b/src/SignalR/clients/csharp/Client.Core/src/PublicAPI.Unshipped.txt
@@ -1,4 +1,8 @@
#nullable enable
+Microsoft.AspNetCore.SignalR.Client.HubConnectionBuilder.KeepAliveInterval.get -> System.TimeSpan?
+Microsoft.AspNetCore.SignalR.Client.HubConnectionBuilder.KeepAliveInterval.set -> void
+Microsoft.AspNetCore.SignalR.Client.HubConnectionBuilder.ServerTimeout.get -> System.TimeSpan?
+Microsoft.AspNetCore.SignalR.Client.HubConnectionBuilder.ServerTimeout.set -> void
static Microsoft.AspNetCore.SignalR.Client.HubConnectionExtensions.On(this Microsoft.AspNetCore.SignalR.Client.HubConnection! hubConnection, string! methodName, System.Func!>! handler) -> System.IDisposable!
static Microsoft.AspNetCore.SignalR.Client.HubConnectionExtensions.On(this Microsoft.AspNetCore.SignalR.Client.HubConnection! hubConnection, string! methodName, System.Func! handler) -> System.IDisposable!
static Microsoft.AspNetCore.SignalR.Client.HubConnectionExtensions.On(this Microsoft.AspNetCore.SignalR.Client.HubConnection! hubConnection, string! methodName, System.Func!>! handler) -> System.IDisposable!
diff --git a/src/SignalR/clients/csharp/Client/test/UnitTests/HubConnectionBuilderTests.cs b/src/SignalR/clients/csharp/Client/test/UnitTests/HubConnectionBuilderTests.cs
index f9473ae9a1b5..6bec4935cade 100644
--- a/src/SignalR/clients/csharp/Client/test/UnitTests/HubConnectionBuilderTests.cs
+++ b/src/SignalR/clients/csharp/Client/test/UnitTests/HubConnectionBuilderTests.cs
@@ -77,4 +77,32 @@ public void AddMessagePackProtocolSetsHubProtocolToMsgPack()
Assert.IsType(serviceProvider.GetService());
}
+
+ [Fact]
+ public void CanSetServerTimeout()
+ {
+ var serverTimeout = TimeSpan.FromMinutes(1);
+ var builder = new HubConnectionBuilder();
+ builder.Services.AddSingleton(new HttpConnectionFactory(Options.Create(new HttpConnectionOptions()), NullLoggerFactory.Instance));
+ builder.WithUrl("http://example.com");
+ builder.ServerTimeout = serverTimeout;
+
+ var connection = builder.Build();
+
+ Assert.Equal(builder.ServerTimeout, connection.ServerTimeout);
+ }
+
+ [Fact]
+ public void CanSetKeepAliveInterval()
+ {
+ var keepAliveInterval = TimeSpan.FromMinutes(2);
+ var builder = new HubConnectionBuilder();
+ builder.Services.AddSingleton(new HttpConnectionFactory(Options.Create(new HttpConnectionOptions()), NullLoggerFactory.Instance));
+ builder.WithUrl("http://example.com");
+ builder.KeepAliveInterval = keepAliveInterval;
+
+ var connection = builder.Build();
+
+ Assert.Equal(builder.KeepAliveInterval, connection.KeepAliveInterval);
+ }
}
diff --git a/src/SignalR/clients/ts/signalr/src/HubConnectionBuilder.ts b/src/SignalR/clients/ts/signalr/src/HubConnectionBuilder.ts
index 2cf4e09a3dbf..f21a642bd0c5 100644
--- a/src/SignalR/clients/ts/signalr/src/HubConnectionBuilder.ts
+++ b/src/SignalR/clients/ts/signalr/src/HubConnectionBuilder.ts
@@ -48,6 +48,22 @@ export class HubConnectionBuilder {
/** @internal */
public logger?: ILogger;
+ /** The server timeout in milliseconds.
+ *
+ * If this timeout elapses without receiving any messages from the server, the connection will be terminated with an error.
+ * The default timeout value is 30,000 milliseconds (30 seconds).
+ */
+ public serverTimeoutInMilliseconds?: number;
+
+ /** Default interval at which to ping the server.
+ *
+ * The default value is 15,000 milliseconds (15 seconds).
+ * Allows the server to detect hard disconnects (like when a client unplugs their computer).
+ * The ping will happen at most as often as the server pings.
+ * If the server pings every 5 seconds, a value lower than 5 will ping every 5 seconds.
+ */
+ public keepAliveIntervalInMilliseconds?: number;
+
/** If defined, this indicates the client should automatically attempt to reconnect if the connection is lost. */
/** @internal */
public reconnectPolicy?: IRetryPolicy;
@@ -204,11 +220,21 @@ export class HubConnectionBuilder {
}
const connection = new HttpConnection(this.url, httpConnectionOptions);
- return HubConnection.create(
+ const hubConnection = HubConnection.create(
connection,
this.logger || NullLogger.instance,
this.protocol || new JsonHubProtocol(),
this.reconnectPolicy);
+
+ if (this.serverTimeoutInMilliseconds !== undefined) {
+ hubConnection.serverTimeoutInMilliseconds = this.serverTimeoutInMilliseconds;
+ }
+
+ if (this.keepAliveIntervalInMilliseconds !== undefined) {
+ hubConnection.keepAliveIntervalInMilliseconds = this.keepAliveIntervalInMilliseconds;
+ }
+
+ return hubConnection;
}
}