MapTraxTrainEventHub
Maps the Trax SignalR hub at a URL path. Clients connect here to receive train lifecycle events pushed by the UseSignalRHub sink.
Signature
public static HubEndpointConventionBuilder MapTraxTrainEventHub(
this IEndpointRouteBuilder endpoints,
string path = "/hubs/trax-events"
)| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
endpoints | IEndpointRouteBuilder | Yes | N/A | Typically WebApplication |
path | string | No | "/hubs/trax-events" | URL where clients open the SignalR connection |
Prerequisites
The host must register SignalR services:
builder.Services.AddSignalR();If AddSignalR() is missing, MapTraxTrainEventHub throws InvalidOperationException with guidance at startup. This fails fast before the host accepts requests rather than letting client connections fail later.
Example
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSignalR();
builder.Services.AddTrax(trax =>
trax.AddEffects(effects =>
effects
.UsePostgres(connStr)
.UseBroadcaster(b => b.UseSignalRHub())));
var app = builder.Build();
app.MapTraxTrainEventHub(); // default "/hubs/trax-events"
// or
app.MapTraxTrainEventHub("/internal/trax-events");
app.Run();Client examples
Blazor (C#)
@inject NavigationManager Nav
@implements IAsyncDisposable
@code {
private HubConnection? _hub;
protected override async Task OnInitializedAsync()
{
_hub = new HubConnectionBuilder()
.WithUrl(Nav.ToAbsoluteUri("/hubs/trax-events"))
.WithAutomaticReconnect()
.Build();
_hub.On<TraxClientEvent>("TrainEvent", async evt =>
{
// update component state, then re-render
await InvokeAsync(StateHasChanged);
});
await _hub.StartAsync();
}
public async ValueTask DisposeAsync()
{
if (_hub is not null) await _hub.DisposeAsync();
}
}JavaScript / TypeScript
import { HubConnectionBuilder } from "@microsoft/signalr";
const connection = new HubConnectionBuilder()
.withUrl("/hubs/trax-events")
.withAutomaticReconnect()
.build();
connection.on("TrainEvent", (evt) => {
// evt: { metadataId, externalId, trainName, eventType, timestamp, failureReason }
});
await connection.start();Payload shape
By default the hub sends a TraxClientEvent per matching lifecycle event. The shape is configurable via WithProjection. See UseSignalRHub for the field list.