TL;DR: Blazor WebAssembly combined with SignalR creates incredibly fast, real-time dashboards entirely in C#. Use
IAsyncDisposableto clean up your SignalR connections when components are destroyed to prevent memory leaks.
Building real-time dashboards used to require heavy JavaScript frameworks, complex WebSocket management, and dozens of NPM packages.
With Blazor WebAssembly and SignalR, you can build a blazing-fast real-time stock ticker using 100% C#. Let's look at how to set up the client side optimally.
1. Setting up the SignalR Hub (Backend)
First, your ASP.NET Core backend needs a Hub to broadcast the stock prices.
public class StockHub : Hub
{
// The server will broadcast to a method called "ReceivePriceUpdate" on the client
public async Task BroadcastPrice(string symbol, decimal price)
{
await Clients.All.SendAsync("ReceivePriceUpdate", symbol, price);
}
}
2. The Blazor WebAssembly Client
The biggest mistake developers make with SignalR in Blazor is forgetting to clean up their connections. If a user navigates away from your Stock Ticker page, the connection stays open, draining battery and memory.
✅ The Good Way (Proper Component Lifecycle)
@page "/ticker"
@implements IAsyncDisposable
@inject NavigationManager Navigation
<h3>Real-Time Stock Ticker</h3>
<div class="glass-card p-4">
@if (stockPrices.Count == 0)
{
<p>Waiting for market data...</p>
}
else
{
<ul>
@foreach (var stock in stockPrices)
{
<li><strong>@stock.Key:</strong> $@stock.Value</li>
}
</ul>
}
</div>
@code {
private HubConnection? hubConnection;
private Dictionary<string, decimal> stockPrices = new();
protected override async Task OnInitializedAsync()
{
// 1. Build the connection
hubConnection = new HubConnectionBuilder()
.WithUrl(Navigation.ToAbsoluteUri("/stockhub"))
.WithAutomaticReconnect() // Crucial for unreliable mobile networks!
.Build();
// 2. Listen for events
hubConnection.On<string, decimal>("ReceivePriceUpdate", (symbol, price) =>
{
stockPrices[symbol] = price;
InvokeAsync(StateHasChanged); // Tell Blazor to re-render the UI
});
// 3. Start the connection
await hubConnection.StartAsync();
}
// 4. CLEANUP! (Prevents memory leaks)
public async ValueTask DisposeAsync()
{
if (hubConnection is not null)
{
await hubConnection.DisposeAsync();
}
}
}
Summary
By leveraging WithAutomaticReconnect() and properly implementing IAsyncDisposable, your Blazor SignalR applications will be robust, scalable, and memory-efficient. No JavaScript required!