Welcome to the start of a new series here on the NimblePros blog focused on SignalR and Blazor! Real-time features can make an application feel alive, but building them from scratch is hard. In this series, we’ll look at how SignalR makes real-time communication approachable for .NET developers and how it fits into Blazor applications. We’ll start with the basics — what real-time communication is, what SignalR is, and why it’s a natural fit for Blazor — and then dive into practical examples in the posts that follow. This first article is meant to be a gentle, jargon-light introduction, so if you’re new to any of these topics, you’re in the right place.
What is Real-Time Communication? 📡
Let’s start with the idea itself. Most of the time, when you use a web application, your browser asks the server for something and waits for an answer. You click a link, the server sends back a new page, and the request is done. That’s the request-response model, and it works great for a lot of things. But it has a limitation: the server can’t talk to you unless you ask first.
Real-time communication flips that around. It means the server can push new information to connected clients the moment it’s available, without waiting for the client to ask. You’ve almost certainly experienced this without thinking about it:
- Chat applications, where a message someone else sent appears on your screen instantly.
- Online games, where your character’s movement shows up on other players’ screens in real time.
- Collaborative document editing, where you can watch a teammate’s cursor move and their edits appear as they type.
- Live scoreboards or stock tickers, where numbers update on their own without you refreshing the page.
The common thread is that information arrives the instant it happens, and everyone stays in sync. That’s the experience real-time communication is all about.
Introducing SignalR 📨
So how do we actually build that experience in .NET? That’s where SignalR comes in.
What is SignalR?
SignalR is a library built by Microsoft for ASP.NET Core that makes real-time web functionality simple. At a high level, it acts as a hub that connects web clients to server-side applications. Clients connect to a hub on the server, and once connected, the server can call methods on those clients and the clients can call methods on the server — all over a single, persistent connection.
Under the hood, SignalR does the heavy lifting for you. It negotiates the best available transport for the connection, preferring WebSockets when they’re available and gracefully falling back to Server-Sent Events or long polling when they aren’t. You don’t have to manage any of that yourself.
Key Benefits ✨
Why reach for SignalR instead of rolling your own real-time solution? A few of the big reasons:
- Simplified client-server communication: SignalR gives you a high-level abstraction. Instead of hand-writing the plumbing to push messages to connected clients, you define a hub, and SignalR handles connecting, sending, and receiving for you.
- Automatic reconnection: Network connections drop. SignalR can automatically reconnect clients that get disconnected, so your app recovers gracefully without users noticing (or having to do anything).
- Transport negotiation: Because SignalR picks the best available transport for each client, you get WebSocket-level performance where it’s supported and working fallbacks everywhere else.
- Scalability: SignalR scales from a single server all the way up to multi-server deployments using backplanes like the Azure SignalR Service or a Redis backplane, so you can grow when you need to.
SignalR & Blazor: A Natural Fit 🧩
If you’ve used Blazor Server before, you may already be familiar with SignalR without realizing it. Blazor Server uses SignalR to maintain a persistent connection between the browser and the server, pushing UI updates to the client as they happen. SignalR is already part of the Blazor story.
That means when you want real-time features in a Blazor app, you’re not bolting on a foreign technology. You’re working with the same infrastructure Blazor itself is built on. This integration is a big deal for a few reasons:
- It fits Blazor’s component model: SignalR hubs play nicely with Blazor components. A component can connect to a hub, subscribe to events, and update its own UI when messages arrive — no separate JavaScript front end required.
- Less complexity: Building real-time features from scratch means dealing with connection management, reconnection logic, and message handling yourself. SignalR (and Blazor’s built-in support for it) removes most of that burden.
- Works across hosting models: Whether you’re using Blazor Server or Blazor WebAssembly, SignalR can be used to connect to a server for real-time data. The same SignalR concepts apply.
In short, SignalR and Blazor were made for each other, and you can take advantage of that right out of the box.
Common Use Cases in Blazor 📋
Throughout this series, we’ll be focusing on a few areas where real-time capabilities really shine in Blazor applications:
- Collaboration: Multiple users interacting with the same data and seeing each other’s changes in real time, like shared boards or live editing.
- Data updates: Pushing fresh data to the UI the moment it changes, so dashboards, feeds, and lists stay current without polling or refreshing.
- Notifications: Alerting users about events as they happen — new messages, activity from other users, or status changes.
We’ll dig into each of these in upcoming posts, so consider this a preview of what’s to come.
Installation & Basic Setup 🛠️
Now that we know why SignalR is valuable, let’s get a very simple example running. We’ll keep this extremely minimal on purpose — future posts in this series will expand on these foundations.
First, create a new Blazor Web App targeting .NET 10:
dotnet new blazor -n SignalRForBlazorDemo
Next, add the SignalR client package. (The Blazor Web App template already includes the server-side SignalR pieces for interactive components, but this package lets us open a separate hub connection from within a component, which is what we’ll use throughout the series.)
dotnet add package Microsoft.AspNetCore.SignalR.Client
Now let’s create a hub. A hub is just a class that inherits from Hub. Create a file called ChatHub.cs:
using Microsoft.AspNetCore.SignalR;
namespace SignalRForBlazorDemo.Hubs;
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
This hub defines one method, SendMessage, that any connected client can call. When it’s called, the server broadcasts a ReceiveMessage event to all connected clients. That’s the whole server side — SignalR takes care of the rest.
Next, tell the application about the hub. In Program.cs, register it and map it to a URL:
using SignalRForBlazorDemo.Components;
using SignalRForBlazorDemo.Hubs;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
var app = builder.Build();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
app.MapHub<ChatHub>("/chathub");
app.Run();
The app.MapHub<ChatHub>("/chathub") line is what makes our hub reachable at that address.
Finally, let’s create a component that opens a connection to the hub, sends a message, and listens for the messages broadcast to everyone. Create a component called RealTimeChat.razor:
@using Microsoft.AspNetCore.SignalR.Client
@implements IAsyncDisposable
<input @bind="_message" />
<button @onclick="SendMessageAsync">Send</button>
<ul>
@foreach (var message in _messages)
{
<li>@message</li>
}
</ul>
@code {
private HubConnection? _hubConnection;
private string _message = string.Empty;
private List<string> _messages = [];
protected override async Task OnInitializedAsync()
{
_hubConnection = new HubConnectionBuilder()
.WithUrl("/chathub")
.WithAutomaticReconnect()
.Build();
_hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
{
_messages.Add($"{user}: {message}");
StateHasChanged();
});
await _hubConnection.StartAsync();
}
private async Task SendMessageAsync()
{
if (_hubConnection is not null)
{
await _hubConnection.InvokeAsync("SendMessage", "You", _message);
_message = string.Empty;
}
}
public async ValueTask DisposeAsync()
{
if (_hubConnection is not null)
{
await _hubConnection.DisposeAsync();
}
}
}
Let’s walk through what’s happening here:
HubConnectionBuildercreates a connection pointed at our/chathubendpoint.WithAutomaticReconnect()means the connection will try to reconnect on its own if it drops — one of those benefits we mentioned earlier._hubConnection.On<string, string>("ReceiveMessage", ...)registers a handler for theReceiveMessageevent the server broadcasts. Whenever it fires, we add the message to our list and ask Blazor to re-render.await _hubConnection.StartAsync()opens the connection.- The
Sendbutton callsInvokeAsync("SendMessage", "You", _message), which invokes our hub method and triggers the broadcast.
That’s it — a working real-time connection, end to end. If you run the app and open two browser tabs, a message sent from one tab will appear in the other instantly.
What’s Next? 🎬
We’ve covered the what and why of real-time communication and SignalR, and we’ve seen a minimal example of a hub connection inside a Blazor app. We intentionally kept this one simple. In the next posts in this series, we’ll go deeper — we’ll explore hubs and methods in more detail, look at grouping and targeting specific clients, and build out the real-world use cases (collaboration, data updates, and notifications) we previewed above.
Resources 📚
- SignalR — official product page
- Introduction to SignalR for ASP.NET Core — official documentation
- Build your first Blazor app — a basic Blazor tutorial to get oriented

