SignalR di ASP.NET Core 2026: Panduan Lengkap Real-Time, Hubs, dan Pertanyaan Interview
Pelajari SignalR di ASP.NET Core untuk komunikasi real-time bidirectional. Panduan lengkap tentang Hubs, Groups, autentikasi, scaling dengan Redis, dan pertanyaan interview teknis.

SignalR memungkinkan komunikasi bidirectional real-time antara server dan klien dalam aplikasi ASP.NET Core. Berbeda dengan pola request-response HTTP tradisional, SignalR mempertahankan koneksi persisten yang memungkinkan server mengirim pembaruan ke klien secara instan—sangat penting untuk aplikasi chat, dashboard live, collaborative editing, dan notifikasi real-time.
SignalR secara otomatis memilih transport terbaik yang tersedia: WebSockets terlebih dahulu, kemudian Server-Sent Events, lalu Long Polling. Mekanisme fallback ini memastikan kompatibilitas di semua browser dan konfigurasi jaringan tanpa perubahan kode apapun.
Cara Kerja SignalR Hubs untuk Komunikasi Server-Client
Hub bertindak sebagai pipeline tingkat tinggi yang menangani pemanggilan method antara klien dan server. Klien memanggil method pada hub, dan hub dapat memanggil method pada klien yang terhubung. Abstraksi ini menghilangkan kompleksitas pengelolaan koneksi WebSocket secara manual.
Contoh berikut mendemonstrasikan chat hub dasar yang menyiarkan pesan ke semua klien yang terhubung:
using Microsoft.AspNetCore.SignalR;
public class ChatHub : Hub
{
// Called when a client sends a message
public async Task SendMessage(string user, string message)
{
// Broadcast to ALL connected clients
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
// Called automatically when a client connects
public override async Task OnConnectedAsync()
{
await Clients.Caller.SendAsync("Connected", Context.ConnectionId);
await base.OnConnectedAsync();
}
// Called automatically when a client disconnects
public override async Task OnDisconnectedAsync(Exception? exception)
{
// Clean up resources, notify other users, etc.
await base.OnDisconnectedAsync(exception);
}
}Property Clients menyediakan akses ke semua klien yang terhubung melalui berbagai opsi targeting: All, Caller, Others, Group, dan User.
Konfigurasi SignalR di ASP.NET Core 9
Registrasi SignalR di ASP.NET Core 9 mengikuti pola middleware standar. Konfigurasi di bawah ini mengaktifkan protokol JSON dan MessagePack dengan ukuran buffer kustom:
var builder = WebApplication.CreateBuilder(args);
// Add SignalR services with configuration
builder.Services.AddSignalR(options =>
{
options.EnableDetailedErrors = builder.Environment.IsDevelopment();
options.MaximumReceiveMessageSize = 64 * 1024; // 64 KB
options.StreamBufferCapacity = 10;
options.KeepAliveInterval = TimeSpan.FromSeconds(15);
options.ClientTimeoutInterval = TimeSpan.FromSeconds(30);
})
.AddJsonProtocol(options =>
{
options.PayloadSerializerOptions.PropertyNamingPolicy = null; // PascalCase
});
var app = builder.Build();
// Map the hub endpoint
app.MapHub<ChatHub>("/chathub");
app.Run();Pengaturan KeepAliveInterval dan ClientTimeoutInterval mengontrol monitoring kesehatan koneksi. Klien yang gagal merespons dalam periode timeout dianggap terputus.
Mengelola Groups untuk Pengiriman Pesan Tertarget
Groups menyediakan mekanisme untuk mengorganisir koneksi dan mengirim pesan ke subset klien. Kasus penggunaan umum melibatkan chat room, di mana pengguna bergabung ke room tertentu dan hanya menerima pesan dari room tersebut.
public class GroupChatHub : Hub
{
// Add the current connection to a group
public async Task JoinRoom(string roomName)
{
await Groups.AddToGroupAsync(Context.ConnectionId, roomName);
// Notify the group that someone joined
await Clients.Group(roomName).SendAsync(
"UserJoined",
Context.User?.Identity?.Name ?? "Anonymous"
);
}
// Remove the current connection from a group
public async Task LeaveRoom(string roomName)
{
await Groups.RemoveFromGroupAsync(Context.ConnectionId, roomName);
await Clients.Group(roomName).SendAsync(
"UserLeft",
Context.User?.Identity?.Name ?? "Anonymous"
);
}
// Send a message to a specific group only
public async Task SendToRoom(string roomName, string message)
{
await Clients.Group(roomName).SendAsync(
"ReceiveMessage",
Context.User?.Identity?.Name,
message
);
}
}Keanggotaan group terikat pada koneksi, bukan pengguna. Ketika pengguna reconnect, mereka harus bergabung kembali ke group mereka. Untuk keanggotaan group yang persisten, simpan asosiasi group di database dan bergabung kembali secara otomatis di OnConnectedAsync.
Groups hanya ada di memory dan tidak dipersist setelah server restart atau dalam skenario scaled-out tanpa backplane. Untuk deployment produksi dengan multiple server, gunakan Redis atau Azure SignalR Service sebagai backplane.
Mengamankan Koneksi SignalR dengan Autentikasi
SignalR terintegrasi dengan autentikasi ASP.NET Core. Atribut [Authorize] membatasi akses hub ke pengguna yang terautentikasi, dan Context.User menyediakan akses ke claims pengguna yang terautentikasi.
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
[Authorize] // Require authentication for the entire hub
public class SecureHub : Hub
{
// Access user claims through Context.User
public async Task SendPrivateMessage(string recipientUserId, string message)
{
var senderName = Context.User?.Identity?.Name
?? throw new HubException("User not authenticated");
// Send to a specific user (all their connections)
await Clients.User(recipientUserId).SendAsync(
"PrivateMessage",
senderName,
message
);
}
[Authorize(Roles = "Admin")] // Role-based authorization on method
public async Task BroadcastAnnouncement(string announcement)
{
await Clients.All.SendAsync("Announcement", announcement);
}
}Untuk koneksi WebSocket, token autentikasi harus dikirim melalui query string karena WebSocket tidak mendukung custom headers. Konfigurasikan klien JavaScript untuk menyertakan token:
import * as signalR from "@microsoft/signalr";
const connection = new signalR.HubConnectionBuilder()
.withUrl("/securehub", {
accessTokenFactory: () => localStorage.getItem("authToken") || ""
})
.withAutomaticReconnect()
.build();
await connection.start();Di sisi server, konfigurasikan autentikasi JWT untuk membaca token dari query string:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
// Read token from query string for SignalR
var accessToken = context.Request.Query["access_token"];
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) &&
path.StartsWithSegments("/securehub"))
{
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
});Siap menguasai wawancara .NET Anda?
Berlatih dengan simulator interaktif, flashcards, dan tes teknis kami.
Scaling SignalR dengan Redis Backplane
Dalam environment load-balanced, klien dapat terhubung ke instance server yang berbeda. Tanpa backplane, pesan yang dikirim dari satu server hanya mencapai klien yang terhubung ke server tersebut. Redis berfungsi sebagai backplane untuk menyinkronkan pesan di semua instance server.
builder.Services.AddSignalR()
.AddStackExchangeRedis(options =>
{
options.Configuration = builder.Configuration
.GetConnectionString("Redis");
// Optional: configure Redis-specific options
options.Configuration.ChannelPrefix =
RedisChannel.Literal("MyApp_SignalR_");
});Redis backplane mempublikasikan semua pesan SignalR ke channel Redis. Setiap instance server berlangganan ke channel ini dan mengirimkan pesan ke klien lokalnya. Pendekatan ini menambahkan latensi minimal (biasanya 1-2ms) sambil memungkinkan horizontal scaling.
Untuk deployment enterprise, Azure SignalR Service menyediakan alternatif terkelola yang menangani scaling, manajemen koneksi, dan ketersediaan secara otomatis.
Strongly-Typed Hubs untuk Keamanan Compile-Time
Strongly-typed hubs menggantikan magic strings dengan method interface, memungkinkan verifikasi compile-time dari pemanggilan method klien:
public interface INotificationClient
{
Task ReceiveNotification(string title, string message, string severity);
Task UpdateProgress(int percentage);
Task TaskCompleted(Guid taskId, bool success);
}
// NotificationHub.cs
public class NotificationHub : Hub<INotificationClient>
{
public async Task NotifyAll(string title, string message)
{
// Compile-time checking - no magic strings
await Clients.All.ReceiveNotification(title, message, "info");
}
public async Task ReportProgress(string groupName, int percentage)
{
// IDE autocomplete works here
await Clients.Group(groupName).UpdateProgress(percentage);
}
}Refactoring menjadi lebih aman karena mengganti nama method di interface langsung menunjukkan semua call sites yang perlu diperbarui.
Streaming Data dengan SignalR Channels
SignalR mendukung streaming untuk skenario di mana data diproduksi secara incremental, seperti pembaruan progress, log tailing, atau data sensor real-time. Streaming server-ke-klien dan klien-ke-server keduanya didukung.
public class StreamingHub : Hub
{
// Server-to-client streaming with IAsyncEnumerable
public async IAsyncEnumerable<StockPrice> StreamStockPrices(
string[] symbols,
[EnumeratorCancellation] CancellationToken cancellationToken)
{
var random = new Random();
while (!cancellationToken.IsCancellationRequested)
{
foreach (var symbol in symbols)
{
yield return new StockPrice
{
Symbol = symbol,
Price = random.NextDouble() * 1000,
Timestamp = DateTime.UtcNow
};
}
await Task.Delay(1000, cancellationToken);
}
}
// Client-to-server streaming
public async Task UploadStream(IAsyncEnumerable<LogEntry> stream)
{
await foreach (var entry in stream)
{
// Process each log entry as it arrives
await ProcessLogEntry(entry);
}
}
}
public record StockPrice(string Symbol, double Price, DateTime Timestamp);
public record LogEntry(string Level, string Message, DateTime Timestamp);Klien JavaScript mengonsumsi stream menggunakan async iterator:
const stream = connection.stream("StreamStockPrices", ["AAPL", "MSFT"]);
stream.subscribe({
next: (price) => console.log(`${price.symbol}: $${price.price}`),
error: (err) => console.error(err),
complete: () => console.log("Stream completed")
});Pertanyaan Interview SignalR yang Sering Muncul
Interview teknis sering membahas arsitektur SignalR dan skenario dunia nyata. Pertanyaan berikut sering muncul dalam sesi interview .NET:
Jelaskan proses negosiasi transport: SignalR pertama mencoba WebSockets, fallback ke Server-Sent Events, kemudian Long Polling. Pahami kapan setiap transport digunakan dan limitasinya.
T: Bagaimana SignalR menangani state koneksi ketika klien sementara kehilangan konektivitas?
SignalR mempertahankan state koneksi di server untuk periode yang dapat dikonfigurasi. Dengan automatic reconnection diaktifkan, klien mencoba reconnect menggunakan connection ID yang sama. Jika berhasil, koneksi dilanjutkan tanpa kehilangan keanggotaan group. Jika disconnect melebihi timeout, koneksi baru dibuat dan klien harus bergabung kembali ke groups.
T: Apa perbedaan antara Clients.User() dan Clients.Client()?
Clients.User(userId) menargetkan semua koneksi yang dimiliki oleh pengguna terautentikasi tertentu—berguna ketika satu pengguna memiliki multiple browser tabs terbuka. Clients.Client(connectionId) menargetkan satu koneksi spesifik. Targeting berbasis pengguna memerlukan autentikasi dan menggunakan IUserIdProvider untuk memetakan koneksi ke user IDs.
T: Bagaimana mengimplementasikan presence detection (menunjukkan siapa yang online)?
Lacak koneksi di OnConnectedAsync dan OnDisconnectedAsync. Simpan mapping user-ke-koneksi di concurrent dictionary atau distributed cache. Untuk deployment scaled-out, gunakan shared store seperti Redis. Broadcast pembaruan presence ke relevant groups ketika pengguna connect atau disconnect.
T: Jelaskan tujuan dari SignalR backplane.
Backplane menyinkronkan pesan di multiple server instances dalam environment load-balanced. Tanpanya, pesan yang dikirim dari server A hanya mencapai klien yang terhubung ke server A. Redis dan Azure SignalR Service adalah opsi backplane yang umum. Backplane mempublikasikan pesan ke shared channel yang semua server berlangganan.
Strategi Optimasi Performa
Performa SignalR tergantung pada ukuran pesan, frekuensi, dan jumlah koneksi. Dokumentasi best practices performa ASP.NET Core menyediakan benchmark detail.
- Gunakan protokol MessagePack untuk serialisasi biner—mengurangi ukuran payload 30-50% dibandingkan JSON
- Batch pesan bila memungkinkan daripada mengirim banyak pesan kecil
- Batasi ukuran group ke ribuan anggota; untuk audiens yang lebih besar, pertimbangkan pola pub/sub
- Aktifkan kompresi untuk payload text-heavy:
.AddJsonProtocol().AddHubOptions(o => o.EnableDetailedErrors = false) - Atur timeout yang sesuai untuk melepaskan resources dari stale connections dengan cepat
// MessagePack configuration for smaller payloads
builder.Services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.SerializerOptions =
MessagePackSerializerOptions.Standard
.WithCompression(MessagePackCompression.Lz4Block);
});Kesimpulan
- SignalR mengabstraksi pemilihan transport (WebSockets, SSE, Long Polling) dan menyediakan model pemrograman konsisten untuk komunikasi real-time
- Hubs memusatkan manajemen koneksi; strongly-typed hubs menambahkan keamanan compile-time untuk pemanggilan method klien
- Groups memungkinkan pengiriman pesan tertarget ke subset koneksi—bergabung kembali ke groups setelah reconnection
- Autentikasi terintegrasi dengan ASP.NET Core identity; kirim token melalui query string untuk koneksi WebSocket
- Scale secara horizontal dengan Redis backplane atau Azure SignalR Service untuk menyinkronkan pesan di semua server instances
- Streaming mendukung pengiriman data incremental dengan
IAsyncEnumerableuntuk skenario server-ke-klien dan klien-ke-server
Mulai berlatih!
Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.

Ditulis oleh
Anthony Fillion-MailletDeveloper fullstack, pendiri SharpSkill
Developer fullstack selama lebih dari 10 tahun. Ia menjalankan SharpSkill dan bertanggung jawab atas semua yang diterbitkan di sini.
Diperbarui 12 Agustus 2026
Bagikan
Artikel terkait

ASP.NET Core Minimal APIs 2026: Arsitektur, Performa dan Pertanyaan Interview
Panduan lengkap ASP.NET Core Minimal APIs dengan arsitektur modern, optimasi performa Native AOT, dan pertanyaan interview umum untuk developer .NET.

.NET 10 di Tahun 2026: Fitur Baru, Native AOT, C# 14, dan Pertanyaan Interview
Panduan lengkap .NET 10 LTS: Native AOT yang siap produksi, extension member C# 14, keyword field, file-based apps, EF Core 10 named query filters, serta pertanyaan interview untuk developer .NET di tahun 2026.

.NET MAUI di 2026: Panduan Pengembangan Cross-Platform dan Pertanyaan Interview
Panduan lengkap .NET MAUI untuk pengembangan cross-platform dengan .NET 10, handler architecture, MVVM, HybridWebView, serta pertanyaan interview penting di tahun 2026.