SignalRClient<TOptions>
Namespace: Meshmakers.Octo.Sdk.ServiceClient
Implementation of the SignalR client.
public class SignalRClient<TOptions> : ISignalRClient<TOptions>
Type Parameters
TOptions
Type of options
Inheritance Object → SignalRClient<TOptions>
Implements ISignalRClient<TOptions>
Properties
IsAlive
public bool IsAlive { get; }
Property Value
ClientAccessToken
public IServiceClientAccessToken ClientAccessToken { get; }
Property Value
Options
public TOptions Options { get; }
Property Value
TOptions
ServiceUri
public Uri ServiceUri { get; private set; }
Property Value
Uri
Constructors
SignalRClient(IOptions<TOptions>, ILogger<SignalRClient<TOptions>>, IServiceClientAccessToken, String)
Constructor.
public SignalRClient(IOptions<TOptions> clientOptions, ILogger<SignalRClient<TOptions>> logger, IServiceClientAccessToken serviceClientAccessToken, string hubName)
Parameters
clientOptions IOptions<TOptions>
The client options
logger ILogger<SignalRClient<TOptions>>
The logger instance
serviceClientAccessToken IServiceClientAccessToken
The access token management object
hubName String
Name of hub name.
SignalRClient(TOptions, ILogger<SignalRClient<TOptions>>, IServiceClientAccessToken, String)
Constructor.
public SignalRClient(TOptions clientOptions, ILogger<SignalRClient<TOptions>> logger, IServiceClientAccessToken serviceClientAccessToken, string hubName)
Parameters
clientOptions TOptions
The client options
logger ILogger<SignalRClient<TOptions>>
The logger instance
serviceClientAccessToken IServiceClientAccessToken
The access token management object
hubName String
Name of hub name.
Methods
EnableReconnect(Func<Boolean, Task>)
public void EnableReconnect(Func<bool, Task> onReconnectFunction)
Parameters
onReconnectFunction Func<Boolean, Task>
StartAsync(Func<Boolean, Task>, CancellationToken)
public Task StartAsync(Func<bool, Task> onReconnectFunction, CancellationToken stoppingToken)
Parameters
onReconnectFunction Func<Boolean, Task>
stoppingToken CancellationToken
Returns
StopAsync()
public Task StopAsync()
Returns
BuildServiceUri()
Builds the service URI for the SignalR hub connection. Override in subclasses to customize URL construction (e.g., for non-tenant-scoped hubs).
protected Uri BuildServiceUri()
Returns
Uri
RegisterServerCallbacks(HubConnection)
Hook for subclasses to (re-)register their server-to-client callback handlers
(HubConnection.On<...>(...)) on the supplied connection.
Called for EVERY connection created by — the
initial one and every one built after a SignalRClient<TOptions>.StopAsync() nulls the cached
connection. Registering the handlers only once in a subclass constructor is a bug:
a full stop/start (e.g. a PreUpdateTenant-triggered adapter restart) builds a fresh
with no handlers, so every server-to-client push is
silently dropped until the process restarts. Bind to the passed
hubConnection, never the property
(that would recurse, as the property is mid-creation here).
protected void RegisterServerCallbacks(HubConnection hubConnection)
Parameters
hubConnection HubConnection
The freshly created connection to register handlers on.
ConfigureHttpConnectionOptions(HttpConnectionOptions)
Configures the HTTP transport of every connection builds: certificate handling, the bearer credential, and the caller-supplied extra headers.
internal void ConfigureHttpConnectionOptions(HttpConnectionOptions options)
Parameters
options HttpConnectionOptions
Remarks:
🔴 The credential is supplied through ,
never as a literal Authorization header (AB#5062 — it used to be the placeholder
"Bearer your-access-token" under a // TODO, so the
IServiceClientAccessToken every caller already passes in was accepted and never
read). Three properties of the provider matter here and none of them hold for a header:
It is invoked on every connection attempt — the negotiate request and each transport start — so the token is re-read on every reconnect this class performs. A header assignment freezes the value at connection-object construction time, and a here outlives many token lifetimes (the reconnect loop reuses the same object for days).
SignalR cannot send headers on the WebSocket and SSE transports; the provider's value
is appended as the access_token query parameter there instead. A header only
ever authenticated the negotiate request.
Returning null for a blank token sends no credential at all — neither
header nor query parameter. A client without a configured token must look anonymous
rather than present a malformed one: a garbage bearer produces a failed
authentication rather than an absent one, which reads as an expired or revoked
credential in the server's logs and hides the real "this client was never given a
token" from any inventory built on them (the AB#5059 LogOnly stage on
/operatorHub is exactly such an inventory).
Internal rather than private so the wiring can be asserted without a live hub.