Skip to main content

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​

Boolean

ClientAccessToken​

public IServiceClientAccessToken ClientAccessToken { get; }

Property Value​

IServiceClientAccessToken

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​

Task

StopAsync()​

public Task StopAsync()

Returns​

Task

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.