SignalR – Tổng quan & sử dụng trong Blazor
Trang này trình bày SignalR theo hướng học từ tổng quan đến thực hành: SignalR là gì, Hub, đăng ký trong Program.cs, kết nối từ Blazor, gửi và nhận message realtime.
1️⃣ Tổng quan về SignalR
SignalR là thư viện của ASP.NET Core dùng để xây dựng chức năng realtime giữa server và client.
Khác với HTTP thông thường (client gửi request rồi chờ response), SignalR giữ kết nối mở giữa client và server để:
- Server có thể chủ động đẩy dữ liệu xuống client
- Client có thể gửi dữ liệu lên server theo thời gian thực
- Nhiều client có thể nhận cùng một message ngay lập tức
SignalR rất phù hợp cho các chức năng như: chat realtime, thông báo realtime, dashboard realtime, game, tracking trạng thái, collaborative app...
Xem sơ đồ luồng hoạt động
Client A ─┐
├── SignalR Hub (Server) ──> Broadcast / Send / Group / User
Client B ─┤
└── Server có thể đẩy message realtime xuống các client
2️⃣ Hub là gì?
Hub là trung tâm giao tiếp realtime trong SignalR.
Bạn có thể hiểu Hub giống như một “điểm kết nối”
để client và server gọi lẫn nhau:
- Client gọi method trên Hub
- Hub xử lý logic phía server
- Hub gửi message xuống một hoặc nhiều client
Hầu hết các ứng dụng SignalR đều bắt đầu bằng việc tạo một class kế thừa từ
Hub.
Xem code Hub cơ bản
using Microsoft.AspNetCore.SignalR;
public class ChatHub : Hub
{
}
3️⃣ Đăng ký SignalR trong Program.cs
Để dùng SignalR, cần làm 2 bước:
AddSignalR()để đăng ký serviceMapHub<THub>("/hub-url")để ánh xạ endpoint Hub
Đây là bước tương tự như Web API dùng AddControllers() và
MapControllers().
Xem code Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
// Đăng ký SignalR
builder.Services.AddSignalR();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
// Map Hub
app.MapHub<ChatHub>("/chathub");
app.Run();
4️⃣ Tạo Hub hoàn chỉnh
Một Hub thường sẽ có các method để:
- Nhận dữ liệu từ client
- Gửi message đến tất cả client
- Gửi đến client hiện tại, user cụ thể hoặc group
Ví dụ đơn giản nhất là chat realtime: client gửi tên và nội dung, server nhận rồi broadcast lại cho mọi người.
Xem code ChatHub đầy đủ
using Microsoft.AspNetCore.SignalR;
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
public override async Task OnConnectedAsync()
{
await Clients.All.SendAsync("ReceiveSystemMessage",
$"{Context.ConnectionId} connected");
await base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception? exception)
{
await Clients.All.SendAsync("ReceiveSystemMessage",
$"{Context.ConnectionId} disconnected");
await base.OnDisconnectedAsync(exception);
}
}
5️⃣ Kết nối từ Blazor đến Hub
Phía Blazor, ta dùng HubConnectionBuilder để tạo kết nối đến Hub.
Quy trình thường là:
- Tạo
HubConnection - Đăng ký các handler nhận message bằng
On<T>(...) - Gọi
StartAsync()để kết nối
Khi không dùng nữa, cần DisposeAsync() để giải phóng kết nối.
Xem code kết nối Hub trong Blazor
using Microsoft.AspNetCore.SignalR.Client;
private HubConnection? _hubConnection;
protected override async Task OnInitializedAsync()
{
_hubConnection = new HubConnectionBuilder()
.WithUrl(Nav.ToAbsoluteUri("/chathub"))
.WithAutomaticReconnect()
.Build();
_hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
{
_messages.Add($"{user}: {message}");
InvokeAsync(StateHasChanged);
});
await _hubConnection.StartAsync();
}
6️⃣ Gửi message từ client lên server
Sau khi kết nối thành công, client có thể gọi method trên Hub bằng
InvokeAsync().
Ví dụ: gọi method SendMessage để gửi tên và nội dung lên server.
Xem code gửi message
private async Task Send()
{
if (_hubConnection is not null)
{
await _hubConnection.InvokeAsync("SendMessage", _userName, _message);
}
}
7️⃣ Nhận message từ server xuống client
Để nhận message, client đăng ký callback bằng On<...>().
Ví dụ:
- Server gọi
Clients.All.SendAsync("ReceiveMessage", ...) - Client đã đăng ký
On<string, string>("ReceiveMessage", ...) - Callback sẽ chạy ngay khi message đến
Đây là phần tạo nên tính realtime của SignalR.
Xem code nhận message
_hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
{
_messages.Add($"{user}: {message}");
InvokeAsync(StateHasChanged);
});
8️⃣ Demo chat realtime trong Blazor
Status: Disconnected
ConnectionId: -
Xem code component demo hoàn chỉnh
@page "/signalr-demo"
@implements IAsyncDisposable
@inject NavigationManager Nav
using Microsoft.AspNetCore.SignalR.Client;
private HubConnection? _hubConnection;
private List<string> _messages = new();
private string _userName = "PLC & SCADA";
private string _message = "";
private bool _isConnected = false;
private string _connectionInfo = "-";
private async Task ConnectHub()
{
if (_hubConnection is not null)
return;
_hubConnection = new HubConnectionBuilder()
.WithUrl(Nav.ToAbsoluteUri("/chathub"))
.WithAutomaticReconnect()
.Build();
_hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
{
_messages.Add($"{user}: {message}");
InvokeAsync(StateHasChanged);
});
_hubConnection.On<string>("ReceiveSystemMessage", (message) =>
{
_messages.Add($"[System] {message}");
InvokeAsync(StateHasChanged);
});
await _hubConnection.StartAsync();
_isConnected = true;
_connectionInfo = _hubConnection.ConnectionId ?? "-";
}
private async Task SendMessage()
{
if (_hubConnection is null || string.IsNullOrWhiteSpace(_message))
return;
await _hubConnection.InvokeAsync("SendMessage", _userName, _message);
_message = "";
}
public async ValueTask DisposeAsync()
{
if (_hubConnection is not null)
{
await _hubConnection.DisposeAsync();
}
}
Logs:
9️⃣ Group, User và Broadcast
SignalR hỗ trợ nhiều kiểu gửi message:
Clients.All→ gửi cho tất cả clientClients.Caller→ gửi cho client hiện tạiClients.Others→ gửi cho mọi client trừ client hiện tạiClients.User(userId)→ gửi cho một user cụ thểClients.Group(groupName)→ gửi cho một group
Đây là lý do SignalR rất mạnh khi làm chat room, notification room, dashboard theo từng nhóm người dùng.
Xem code ví dụ Group
public async Task JoinGroup(string groupName)
{
await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
await Clients.Group(groupName).SendAsync("ReceiveSystemMessage",
$"{Context.ConnectionId} joined {groupName}");
}
public async Task SendGroupMessage(string groupName, string user, string message)
{
await Clients.Group(groupName).SendAsync("ReceiveMessage", user, message);
}
🔟 Tổng kết
- SignalR dùng để giao tiếp realtime giữa server và client.
- Hub là trung tâm nhận và gửi message realtime.
- Dùng
AddSignalR()vàMapHub<THub>()để đăng ký trong ASP.NET Core. - Phía Blazor dùng
HubConnectionBuilderđể kết nối đến Hub. - Dùng
InvokeAsync()để client gọi method trên server. - Dùng
On<...>()để client nhận message từ server. - SignalR rất phù hợp cho chat, notification, dashboard realtime và collaborative app.