Menggunakan hub untuk SignalR ASP.NET Core
Oleh Rachel Appel dan Kevin Griffin
SignalR HUBS API memungkinkan klien yang terhubung untuk memanggil metode di server, memfasilitasi komunikasi real-time. Server mendefinisikan metode yang dipanggil oleh klien, dan klien menentukan metode yang dipanggil oleh server. SignalR juga memungkinkan komunikasi klien-ke-klien tidak langsung, selalu dimediasi oleh SignalR Hub, memungkinkan pesan dikirim antara klien individu, grup, atau ke semua klien yang terhubung. SignalR mengurus semua yang diperlukan untuk memungkinkan komunikasi klien-ke-server dan server-ke-klien secara real-time.
Mengonfigurasi SignalR hub
Untuk mendaftarkan layanan yang diperlukan oleh SignalR hub, hubungi AddSignalR di Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddSignalR();
Untuk mengonfigurasi SignalR titik akhir, panggil MapHub, juga di Program.cs
:
app.MapRazorPages();
app.MapHub<ChatHub>("/Chat");
app.Run();
Catatan
ASP.NET rakitan sisi server Core SignalR sekarang diinstal dengan .NET Core SDK. Lihat SignalR rakitan dalam kerangka kerja bersama untuk informasi selengkapnya.
Membuat dan menggunakan hub
Buat hub dengan mendeklarasikan kelas yang mewarisi dari Hub. Tambahkan public
metode ke kelas untuk membuatnya dapat dipanggil dari klien:
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
=> await Clients.All.SendAsync("ReceiveMessage", user, message);
}
Catatan
Hub bersifat sementara:
- Jangan menyimpan status di properti kelas hub. Setiap panggilan metode hub dijalankan pada instans hub baru.
- Jangan membuat instans hub secara langsung melalui injeksi dependensi. Untuk mengirim pesan ke klien dari tempat lain di aplikasi Anda, gunakan
IHubContext
. - Gunakan
await
saat memanggil metode asinkron yang bergantung pada hub tetap hidup. Misalnya, metode sepertiClients.All.SendAsync(...)
dapat gagal jika dipanggil tanpaawait
dan metode hub selesai sebelumSendAsync
selesai.
Objek Konteks
Kelas Hub menyertakan Context properti yang berisi properti berikut dengan informasi tentang koneksi:
Properti | Deskripsi |
---|---|
ConnectionId | Mendapatkan ID unik untuk koneksi, yang ditetapkan oleh SignalR. Ada satu ID koneksi untuk setiap koneksi. |
UserIdentifier | Mendapatkan pengidentifikasi pengguna. Secara default, SignalR menggunakan ClaimTypes.NameIdentifier dari yang ClaimsPrincipal terkait dengan koneksi sebagai pengidentifikasi pengguna. |
User | Mendapatkan yang ClaimsPrincipal terkait dengan pengguna saat ini. |
Items | Mendapatkan kumpulan kunci/nilai yang dapat digunakan untuk berbagi data dalam cakupan koneksi ini. Data dapat disimpan dalam koleksi ini dan akan bertahan untuk koneksi di berbagai pemanggilan metode hub. |
Features | Mendapatkan kumpulan fitur yang tersedia pada koneksi. Untuk saat ini, koleksi ini tidak diperlukan dalam sebagian besar skenario, sehingga belum didokumenkan secara rinci. |
ConnectionAborted | CancellationToken Mendapatkan yang memberi tahu ketika koneksi dibatalkan. |
Hub.Context juga berisi metode berikut:
Metode | Deskripsi |
---|---|
GetHttpContext | Mengembalikan HttpContext untuk koneksi, atau null jika koneksi tidak terkait dengan permintaan HTTP. Untuk koneksi HTTP, gunakan metode ini untuk mendapatkan informasi seperti header HTTP dan string kueri. |
Abort | Membatalkan koneksi. |
Objek Klien
Kelas Hub menyertakan Clients properti yang berisi properti berikut untuk komunikasi antara server dan klien:
Properti | Deskripsi |
---|---|
All | Memanggil metode pada semua klien yang terhubung |
Caller | Memanggil metode pada klien yang memanggil metode hub |
Others | Memanggil metode pada semua klien yang terhubung kecuali klien yang memanggil metode |
Hub.Clients juga berisi metode berikut:
Metode | Deskripsi |
---|---|
AllExcept | Memanggil metode pada semua klien yang terhubung kecuali untuk koneksi yang ditentukan |
Client | Memanggil metode pada klien terhubung tertentu |
Clients | Memanggil metode pada klien tertentu yang terhubung |
Group | Memanggil metode pada semua koneksi dalam grup yang ditentukan |
GroupExcept | Memanggil metode pada semua koneksi dalam grup yang ditentukan, kecuali koneksi yang ditentukan |
Groups | Memanggil metode pada beberapa grup koneksi |
OthersInGroup | Memanggil metode pada sekelompok koneksi, tidak termasuk klien yang memanggil metode hub |
User | Memanggil metode pada semua koneksi yang terkait dengan pengguna tertentu |
Users | Memanggil metode pada semua koneksi yang terkait dengan pengguna yang ditentukan |
Setiap properti atau metode dalam tabel sebelumnya mengembalikan objek dengan SendAsync
metode . Metode ini SendAsync
menerima nama metode klien untuk memanggil dan parameter apa pun.
Objek yang Client
dikembalikan oleh metode dan Caller
juga berisi InvokeAsync
metode, yang dapat digunakan untuk menunggu hasil dari klien.
Mengirim pesan ke klien
Untuk melakukan panggilan ke klien tertentu, gunakan properti Clients
objek. Dalam contoh berikut, ada tiga metode hub:
SendMessage
mengirim pesan ke semua klien yang terhubung, menggunakanClients.All
.SendMessageToCaller
mengirim pesan kembali ke pemanggil, menggunakanClients.Caller
.SendMessageToGroup
mengirim pesan ke semua klien dalamSignalR Users
grup.
public async Task SendMessage(string user, string message)
=> await Clients.All.SendAsync("ReceiveMessage", user, message);
public async Task SendMessageToCaller(string user, string message)
=> await Clients.Caller.SendAsync("ReceiveMessage", user, message);
public async Task SendMessageToGroup(string user, string message)
=> await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);
Hub yang sangat ditik
Kelemahan penggunaannya SendAsync
adalah mengandalkan string untuk menentukan metode klien yang akan dipanggil. Ini membuat kode terbuka untuk kesalahan runtime jika nama metode salah eja atau hilang dari klien.
Alternatif untuk menggunakan SendAsync
adalah mengetik Hub kelas dengan kuat dengan Hub<T>. Dalam contoh berikut, ChatHub
metode klien telah diekstraksi ke antarmuka yang disebut IChatClient
:
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Antarmuka ini dapat digunakan untuk merefaktor ChatHub
contoh sebelumnya untuk diketik dengan kuat:
public class StronglyTypedChatHub : Hub<IChatClient>
{
public async Task SendMessage(string user, string message)
=> await Clients.All.ReceiveMessage(user, message);
public async Task SendMessageToCaller(string user, string message)
=> await Clients.Caller.ReceiveMessage(user, message);
public async Task SendMessageToGroup(string user, string message)
=> await Clients.Group("SignalR Users").ReceiveMessage(user, message);
}
Menggunakan Hub<IChatClient>
mengaktifkan pemeriksaan waktu kompilasi metode klien. Ini mencegah masalah yang disebabkan oleh penggunaan string, karena Hub<T>
hanya dapat menyediakan akses ke metode yang ditentukan dalam antarmuka. Menggunakan tipe yang sangat Hub<T>
kuat menonaktifkan kemampuan untuk menggunakan SendAsync
.
Catatan
Akhiran Async
tidak dilucuti dari nama metode. Kecuali metode klien didefinisikan dengan .on('MyMethodAsync')
, jangan gunakan MyMethodAsync
sebagai nama.
Hasil klien
Selain melakukan panggilan ke klien, server dapat meminta hasil dari klien. Ini mengharuskan server untuk menggunakan ISingleClientProxy.InvokeAsync
dan klien untuk mengembalikan hasil dari handler-nya .On
.
Ada dua cara untuk menggunakan API di server, yang pertama adalah memanggil Client(...)
atau Caller
pada Clients
properti dalam metode Hub:
public class ChatHub : Hub
{
public async Task<string> WaitForMessage(string connectionId)
{
var message = await Clients.Client(connectionId).InvokeAsync<string>(
"GetMessage");
return message;
}
}
Cara kedua adalah memanggil Client(...)
instans :IHubContext<T>
async Task SomeMethod(IHubContext<MyHub> context)
{
string result = await context.Clients.Client(connectionID).InvokeAsync<string>(
"GetMessage");
}
Hub yang sangat di ketik juga dapat mengembalikan nilai dari metode antarmuka:
public interface IClient
{
Task<string> GetMessage();
}
public class ChatHub : Hub<IClient>
{
public async Task<string> WaitForMessage(string connectionId)
{
string message = await Clients.Client(connectionId).GetMessage();
return message;
}
}
Klien mengembalikan hasil dalam handler mereka .On(...)
, seperti yang ditunjukkan di bawah ini:
Klien .NET
hubConnection.On("GetMessage", async () =>
{
Console.WriteLine("Enter message:");
var message = await Console.In.ReadLineAsync();
return message;
});
Klien typescript
hubConnection.on("GetMessage", async () => {
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("message");
}, 100);
});
return promise;
});
Klien Java
hubConnection.onWithResult("GetMessage", () -> {
return Single.just("message");
});
Mengubah nama metode hub
Secara default, nama metode hub server adalah nama metode .NET. Untuk mengubah perilaku default ini untuk metode tertentu, gunakan atribut HubMethodName . Klien harus menggunakan nama ini alih-alih nama metode .NET saat memanggil metode:
[HubMethodName("SendMessageToUser")]
public async Task DirectMessage(string user, string message)
=> await Clients.User(user).SendAsync("ReceiveMessage", user, message);
Menyuntikkan layanan ke hub
Konstruktor hub dapat menerima layanan dari DI sebagai parameter, yang dapat disimpan di properti di kelas untuk digunakan dalam metode hub.
Saat menyuntikkan beberapa layanan untuk metode hub yang berbeda atau sebagai cara alternatif menulis kode, metode hub juga dapat menerima layanan dari DI. Secara default, parameter metode hub diperiksa dan diselesaikan dari DI jika memungkinkan.
services.AddSingleton<IDatabaseService, DatabaseServiceImpl>();
// ...
public class ChatHub : Hub
{
public Task SendMessage(string user, string message, IDatabaseService dbService)
{
var userName = dbService.GetUserName(user);
return Clients.All.SendAsync("ReceiveMessage", userName, message);
}
}
Jika resolusi implisit parameter dari layanan tidak diinginkan, nonaktifkan dengan DisableImplicitFromServicesParameters.
Untuk secara eksplisit menentukan parameter mana yang diselesaikan dari DI dalam metode hub, gunakan DisableImplicitFromServicesParameters
opsi dan gunakan [FromServices]
atribut atau atribut kustom yang menerapkan IFromServiceMetadata
pada parameter metode hub yang harus diselesaikan dari DI.
services.AddSingleton<IDatabaseService, DatabaseServiceImpl>();
services.AddSignalR(options =>
{
options.DisableImplicitFromServicesParameters = true;
});
// ...
public class ChatHub : Hub
{
public Task SendMessage(string user, string message,
[FromServices] IDatabaseService dbService)
{
var userName = dbService.GetUserName(user);
return Clients.All.SendAsync("ReceiveMessage", userName, message);
}
}
Catatan
Fitur ini memanfaatkan IServiceProviderIsService, yang secara opsional diimplementasikan oleh implementasi DI. Jika kontainer DI aplikasi tidak mendukung fitur ini, memasukkan layanan ke metode hub tidak didukung.
Dukungan layanan utama dalam Injeksi Dependensi
Layanan utama mengacu pada mekanisme untuk mendaftarkan dan mengambil layanan Dependency Injection (DI) menggunakan kunci. Layanan dikaitkan dengan kunci dengan memanggil AddKeyedSingleton (atau AddKeyedScoped
atau AddKeyedTransient
) untuk mendaftarkannya. Akses layanan terdaftar dengan menentukan kunci dengan [FromKeyedServices]
atribut . Kode berikut menunjukkan cara menggunakan layanan kunci:
using Microsoft.AspNetCore.SignalR;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddKeyedSingleton<ICache, BigCache>("big");
builder.Services.AddKeyedSingleton<ICache, SmallCache>("small");
builder.Services.AddRazorPages();
builder.Services.AddSignalR();
var app = builder.Build();
app.MapRazorPages();
app.MapHub<MyHub>("/myHub");
app.Run();
public interface ICache
{
object Get(string key);
}
public class BigCache : ICache
{
public object Get(string key) => $"Resolving {key} from big cache.";
}
public class SmallCache : ICache
{
public object Get(string key) => $"Resolving {key} from small cache.";
}
public class MyHub : Hub
{
public void SmallCacheMethod([FromKeyedServices("small")] ICache cache)
{
Console.WriteLine(cache.Get("signalr"));
}
public void BigCacheMethod([FromKeyedServices("big")] ICache cache)
{
Console.WriteLine(cache.Get("signalr"));
}
}
Menangani peristiwa untuk koneksi
SignalR HUBS API menyediakan OnConnectedAsync metode virtual dan OnDisconnectedAsync untuk mengelola dan melacak koneksi. Ambil alih OnConnectedAsync
metode virtual untuk melakukan tindakan saat klien tersambung ke hub, seperti menambahkannya ke grup:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Ambil alih OnDisconnectedAsync
metode virtual untuk melakukan tindakan saat klien terputus. Jika klien memutuskan sambungan dengan sengaja, seperti dengan memanggil connection.stop()
, exception
parameter diatur ke null
. Namun, jika klien terputus karena kesalahan, seperti kegagalan jaringan, exception
parameter berisi pengecualian yang menjelaskan kegagalan:
public override async Task OnDisconnectedAsync(Exception? exception)
{
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync tidak perlu dipanggil dalam , secara otomatis ditangani OnDisconnectedAsyncuntuk Anda.
Menangani kesalahan
Pengecualian yang dilemparkan dalam metode hub dikirim ke klien yang memanggil metode . Pada klien JavaScript, invoke
metode mengembalikan JavaScript Promise
. Klien dapat melampirkan catch
handler ke janji yang dikembalikan atau digunakan try
catch
/dengan async
/await
untuk menangani pengecualian:
try {
await connection.invoke("SendMessage", user, message);
} catch (err) {
console.error(err);
}
Koneksi tidak ditutup saat hub melemparkan pengecualian. Secara default, SignalR mengembalikan pesan kesalahan umum kepada klien, seperti yang ditunjukkan dalam contoh berikut:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'SendMessage' on the server.
Pengecualian tak terduga sering berisi informasi sensitif, seperti nama server database dalam pengecualian yang dipicu ketika koneksi database gagal. SignalR tidak mengekspos pesan kesalahan terperinci ini secara default sebagai ukuran keamanan. Untuk informasi selengkapnya tentang mengapa detail pengecualian ditekan, lihat Pertimbangan keamanan di ASP.NET Core SignalR.
Jika kondisi luar biasa harus disebarkan ke klien, gunakan HubException kelas . HubException
Jika dilemparkan dalam metode hub, SignalRmengirim seluruh pesan pengecualian ke klien, tidak dimodifikasi:
public Task ThrowException()
=> throw new HubException("This error will be sent to the client!");
Catatan
SignalR hanya mengirim Message
properti pengecualian ke klien. Jejak tumpukan dan properti lain pada pengecualian tidak tersedia untuk klien.
Sumber Daya Tambahan:
Oleh Rachel Appel dan Kevin Griffin
SignalR HUBS API memungkinkan klien yang terhubung untuk memanggil metode di server, memfasilitasi komunikasi real-time. Server mendefinisikan metode yang dipanggil oleh klien, dan klien menentukan metode yang dipanggil oleh server. SignalR juga memungkinkan komunikasi klien-ke-klien tidak langsung, selalu dimediasi oleh SignalR Hub, memungkinkan pesan dikirim antara klien individu, grup, atau ke semua klien yang terhubung. SignalR mengurus semua yang diperlukan untuk memungkinkan komunikasi klien-ke-server dan server-ke-klien secara real-time.
Mengonfigurasi SignalR hub
Untuk mendaftarkan layanan yang diperlukan oleh SignalR hub, hubungi AddSignalR di Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddSignalR();
Untuk mengonfigurasi SignalR titik akhir, panggil MapHub, juga di Program.cs
:
app.MapRazorPages();
app.MapHub<ChatHub>("/Chat");
app.Run();
Catatan
ASP.NET rakitan sisi server Core SignalR sekarang diinstal dengan .NET Core SDK. Lihat SignalR rakitan dalam kerangka kerja bersama untuk informasi selengkapnya.
Membuat dan menggunakan hub
Buat hub dengan mendeklarasikan kelas yang mewarisi dari Hub. Tambahkan public
metode ke kelas untuk membuatnya dapat dipanggil dari klien:
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
=> await Clients.All.SendAsync("ReceiveMessage", user, message);
}
Catatan
Hub bersifat sementara:
- Jangan menyimpan status di properti kelas hub. Setiap panggilan metode hub dijalankan pada instans hub baru.
- Jangan membuat instans hub secara langsung melalui injeksi dependensi. Untuk mengirim pesan ke klien dari tempat lain di aplikasi Anda, gunakan
IHubContext
. - Gunakan
await
saat memanggil metode asinkron yang bergantung pada hub tetap hidup. Misalnya, metode sepertiClients.All.SendAsync(...)
dapat gagal jika dipanggil tanpaawait
dan metode hub selesai sebelumSendAsync
selesai.
Objek Konteks
Kelas Hub menyertakan Context properti yang berisi properti berikut dengan informasi tentang koneksi:
Properti | Deskripsi |
---|---|
ConnectionId | Mendapatkan ID unik untuk koneksi, yang ditetapkan oleh SignalR. Ada satu ID koneksi untuk setiap koneksi. |
UserIdentifier | Mendapatkan pengidentifikasi pengguna. Secara default, SignalR menggunakan ClaimTypes.NameIdentifier dari yang ClaimsPrincipal terkait dengan koneksi sebagai pengidentifikasi pengguna. |
User | Mendapatkan yang ClaimsPrincipal terkait dengan pengguna saat ini. |
Items | Mendapatkan kumpulan kunci/nilai yang dapat digunakan untuk berbagi data dalam cakupan koneksi ini. Data dapat disimpan dalam koleksi ini dan akan bertahan untuk koneksi di berbagai pemanggilan metode hub. |
Features | Mendapatkan kumpulan fitur yang tersedia pada koneksi. Untuk saat ini, koleksi ini tidak diperlukan dalam sebagian besar skenario, sehingga belum didokumenkan secara rinci. |
ConnectionAborted | CancellationToken Mendapatkan yang memberi tahu ketika koneksi dibatalkan. |
Hub.Context juga berisi metode berikut:
Metode | Deskripsi |
---|---|
GetHttpContext | Mengembalikan HttpContext untuk koneksi, atau null jika koneksi tidak terkait dengan permintaan HTTP. Untuk koneksi HTTP, gunakan metode ini untuk mendapatkan informasi seperti header HTTP dan string kueri. |
Abort | Membatalkan koneksi. |
Objek Klien
Kelas Hub menyertakan Clients properti yang berisi properti berikut untuk komunikasi antara server dan klien:
Properti | Deskripsi |
---|---|
All | Memanggil metode pada semua klien yang terhubung |
Caller | Memanggil metode pada klien yang memanggil metode hub |
Others | Memanggil metode pada semua klien yang terhubung kecuali klien yang memanggil metode |
Hub.Clients juga berisi metode berikut:
Metode | Deskripsi |
---|---|
AllExcept | Memanggil metode pada semua klien yang terhubung kecuali untuk koneksi yang ditentukan |
Client | Memanggil metode pada klien terhubung tertentu |
Clients | Memanggil metode pada klien tertentu yang terhubung |
Group | Memanggil metode pada semua koneksi dalam grup yang ditentukan |
GroupExcept | Memanggil metode pada semua koneksi dalam grup yang ditentukan, kecuali koneksi yang ditentukan |
Groups | Memanggil metode pada beberapa grup koneksi |
OthersInGroup | Memanggil metode pada sekelompok koneksi, tidak termasuk klien yang memanggil metode hub |
User | Memanggil metode pada semua koneksi yang terkait dengan pengguna tertentu |
Users | Memanggil metode pada semua koneksi yang terkait dengan pengguna yang ditentukan |
Setiap properti atau metode dalam tabel sebelumnya mengembalikan objek dengan SendAsync
metode . Metode ini SendAsync
menerima nama metode klien untuk memanggil dan parameter apa pun.
Objek yang Client
dikembalikan oleh metode dan Caller
juga berisi InvokeAsync
metode, yang dapat digunakan untuk menunggu hasil dari klien.
Mengirim pesan ke klien
Untuk melakukan panggilan ke klien tertentu, gunakan properti Clients
objek. Dalam contoh berikut, ada tiga metode hub:
SendMessage
mengirim pesan ke semua klien yang terhubung, menggunakanClients.All
.SendMessageToCaller
mengirim pesan kembali ke pemanggil, menggunakanClients.Caller
.SendMessageToGroup
mengirim pesan ke semua klien dalamSignalR Users
grup.
public async Task SendMessage(string user, string message)
=> await Clients.All.SendAsync("ReceiveMessage", user, message);
public async Task SendMessageToCaller(string user, string message)
=> await Clients.Caller.SendAsync("ReceiveMessage", user, message);
public async Task SendMessageToGroup(string user, string message)
=> await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);
Hub yang sangat ditik
Kelemahan penggunaannya SendAsync
adalah mengandalkan string untuk menentukan metode klien yang akan dipanggil. Ini membuat kode terbuka untuk kesalahan runtime jika nama metode salah eja atau hilang dari klien.
Alternatif untuk menggunakan SendAsync
adalah mengetik Hub kelas dengan kuat dengan Hub<T>. Dalam contoh berikut, ChatHub
metode klien telah diekstraksi ke antarmuka yang disebut IChatClient
:
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Antarmuka ini dapat digunakan untuk merefaktor ChatHub
contoh sebelumnya untuk diketik dengan kuat:
public class StronglyTypedChatHub : Hub<IChatClient>
{
public async Task SendMessage(string user, string message)
=> await Clients.All.ReceiveMessage(user, message);
public async Task SendMessageToCaller(string user, string message)
=> await Clients.Caller.ReceiveMessage(user, message);
public async Task SendMessageToGroup(string user, string message)
=> await Clients.Group("SignalR Users").ReceiveMessage(user, message);
}
Menggunakan Hub<IChatClient>
mengaktifkan pemeriksaan waktu kompilasi metode klien. Ini mencegah masalah yang disebabkan oleh penggunaan string, karena Hub<T>
hanya dapat menyediakan akses ke metode yang ditentukan dalam antarmuka. Menggunakan tipe yang sangat Hub<T>
kuat menonaktifkan kemampuan untuk menggunakan SendAsync
.
Catatan
Akhiran Async
tidak dilucuti dari nama metode. Kecuali metode klien didefinisikan dengan .on('MyMethodAsync')
, jangan gunakan MyMethodAsync
sebagai nama.
Hasil klien
Selain melakukan panggilan ke klien, server dapat meminta hasil dari klien. Ini mengharuskan server untuk menggunakan ISingleClientProxy.InvokeAsync
dan klien untuk mengembalikan hasil dari handler-nya .On
.
Ada dua cara untuk menggunakan API di server, yang pertama adalah memanggil Client(...)
atau Caller
pada Clients
properti dalam metode Hub:
public class ChatHub : Hub
{
public async Task<string> WaitForMessage(string connectionId)
{
var message = await Clients.Client(connectionId).InvokeAsync<string>(
"GetMessage");
return message;
}
}
Cara kedua adalah memanggil Client(...)
instans :IHubContext<T>
async Task SomeMethod(IHubContext<MyHub> context)
{
string result = await context.Clients.Client(connectionID).InvokeAsync<string>(
"GetMessage");
}
Hub yang sangat di ketik juga dapat mengembalikan nilai dari metode antarmuka:
public interface IClient
{
Task<string> GetMessage();
}
public class ChatHub : Hub<IClient>
{
public async Task<string> WaitForMessage(string connectionId)
{
string message = await Clients.Client(connectionId).GetMessage();
return message;
}
}
Klien mengembalikan hasil dalam handler mereka .On(...)
, seperti yang ditunjukkan di bawah ini:
Klien .NET
hubConnection.On("GetMessage", async () =>
{
Console.WriteLine("Enter message:");
var message = await Console.In.ReadLineAsync();
return message;
});
Klien typescript
hubConnection.on("GetMessage", async () => {
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("message");
}, 100);
});
return promise;
});
Klien Java
hubConnection.onWithResult("GetMessage", () -> {
return Single.just("message");
});
Mengubah nama metode hub
Secara default, nama metode hub server adalah nama metode .NET. Untuk mengubah perilaku default ini untuk metode tertentu, gunakan atribut HubMethodName . Klien harus menggunakan nama ini alih-alih nama metode .NET saat memanggil metode:
[HubMethodName("SendMessageToUser")]
public async Task DirectMessage(string user, string message)
=> await Clients.User(user).SendAsync("ReceiveMessage", user, message);
Menyuntikkan layanan ke hub
Konstruktor hub dapat menerima layanan dari DI sebagai parameter, yang dapat disimpan di properti di kelas untuk digunakan dalam metode hub.
Saat menyuntikkan beberapa layanan untuk metode hub yang berbeda atau sebagai cara alternatif menulis kode, metode hub juga dapat menerima layanan dari DI. Secara default, parameter metode hub diperiksa dan diselesaikan dari DI jika memungkinkan.
services.AddSingleton<IDatabaseService, DatabaseServiceImpl>();
// ...
public class ChatHub : Hub
{
public Task SendMessage(string user, string message, IDatabaseService dbService)
{
var userName = dbService.GetUserName(user);
return Clients.All.SendAsync("ReceiveMessage", userName, message);
}
}
Jika resolusi implisit parameter dari layanan tidak diinginkan, nonaktifkan dengan DisableImplicitFromServicesParameters.
Untuk secara eksplisit menentukan parameter mana yang diselesaikan dari DI dalam metode hub, gunakan DisableImplicitFromServicesParameters
opsi dan gunakan [FromServices]
atribut atau atribut kustom yang menerapkan IFromServiceMetadata
pada parameter metode hub yang harus diselesaikan dari DI.
services.AddSingleton<IDatabaseService, DatabaseServiceImpl>();
services.AddSignalR(options =>
{
options.DisableImplicitFromServicesParameters = true;
});
// ...
public class ChatHub : Hub
{
public Task SendMessage(string user, string message,
[FromServices] IDatabaseService dbService)
{
var userName = dbService.GetUserName(user);
return Clients.All.SendAsync("ReceiveMessage", userName, message);
}
}
Catatan
Fitur ini memanfaatkan IServiceProviderIsService, yang secara opsional diimplementasikan oleh implementasi DI. Jika kontainer DI aplikasi tidak mendukung fitur ini, memasukkan layanan ke metode hub tidak didukung.
Menangani peristiwa untuk koneksi
SignalR HUBS API menyediakan OnConnectedAsync metode virtual dan OnDisconnectedAsync untuk mengelola dan melacak koneksi. Ambil alih OnConnectedAsync
metode virtual untuk melakukan tindakan saat klien tersambung ke hub, seperti menambahkannya ke grup:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Ambil alih OnDisconnectedAsync
metode virtual untuk melakukan tindakan saat klien terputus. Jika klien memutuskan sambungan dengan sengaja, seperti dengan memanggil connection.stop()
, exception
parameter diatur ke null
. Namun, jika klien terputus karena kesalahan, seperti kegagalan jaringan, exception
parameter berisi pengecualian yang menjelaskan kegagalan:
public override async Task OnDisconnectedAsync(Exception? exception)
{
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync tidak perlu dipanggil dalam , secara otomatis ditangani OnDisconnectedAsyncuntuk Anda.
Menangani kesalahan
Pengecualian yang dilemparkan dalam metode hub dikirim ke klien yang memanggil metode . Pada klien JavaScript, invoke
metode mengembalikan JavaScript Promise
. Klien dapat melampirkan catch
handler ke janji yang dikembalikan atau digunakan try
catch
/dengan async
/await
untuk menangani pengecualian:
try {
await connection.invoke("SendMessage", user, message);
} catch (err) {
console.error(err);
}
Koneksi tidak ditutup saat hub melemparkan pengecualian. Secara default, SignalR mengembalikan pesan kesalahan umum kepada klien, seperti yang ditunjukkan dalam contoh berikut:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'SendMessage' on the server.
Pengecualian tak terduga sering berisi informasi sensitif, seperti nama server database dalam pengecualian yang dipicu ketika koneksi database gagal. SignalR tidak mengekspos pesan kesalahan terperinci ini secara default sebagai ukuran keamanan. Untuk informasi selengkapnya tentang mengapa detail pengecualian ditekan, lihat Pertimbangan keamanan di ASP.NET Core SignalR.
Jika kondisi luar biasa harus disebarkan ke klien, gunakan HubException kelas . HubException
Jika dilemparkan dalam metode hub, SignalRmengirim seluruh pesan pengecualian ke klien, tidak dimodifikasi:
public Task ThrowException()
=> throw new HubException("This error will be sent to the client!");
Catatan
SignalR hanya mengirim Message
properti pengecualian ke klien. Jejak tumpukan dan properti lain pada pengecualian tidak tersedia untuk klien.
Sumber Daya Tambahan:
Oleh Rachel Appel dan Kevin Griffin
SignalR HUBS API memungkinkan klien yang terhubung untuk memanggil metode di server, memfasilitasi komunikasi real-time. Server mendefinisikan metode yang dipanggil oleh klien, dan klien menentukan metode yang dipanggil oleh server. SignalR juga memungkinkan komunikasi klien-ke-klien tidak langsung, selalu dimediasi oleh SignalR Hub, memungkinkan pesan dikirim antara klien individu, grup, atau ke semua klien yang terhubung. SignalR mengurus semua yang diperlukan untuk memungkinkan komunikasi klien-ke-server dan server-ke-klien secara real-time.
Mengonfigurasi SignalR hub
Untuk mendaftarkan layanan yang diperlukan oleh SignalR hub, hubungi AddSignalR di Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddSignalR();
Untuk mengonfigurasi SignalR titik akhir, panggil MapHub, juga di Program.cs
:
app.MapRazorPages();
app.MapHub<ChatHub>("/Chat");
app.Run();
Catatan
ASP.NET rakitan sisi server Core SignalR sekarang diinstal dengan .NET Core SDK. Lihat SignalR rakitan dalam kerangka kerja bersama untuk informasi selengkapnya.
Membuat dan menggunakan hub
Buat hub dengan mendeklarasikan kelas yang mewarisi dari Hub. Tambahkan public
metode ke kelas untuk membuatnya dapat dipanggil dari klien:
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
=> await Clients.All.SendAsync("ReceiveMessage", user, message);
}
Catatan
Hub bersifat sementara:
- Jangan menyimpan status di properti kelas hub. Setiap panggilan metode hub dijalankan pada instans hub baru.
- Jangan membuat instans hub secara langsung melalui injeksi dependensi. Untuk mengirim pesan ke klien dari tempat lain di aplikasi Anda, gunakan
IHubContext
. - Gunakan
await
saat memanggil metode asinkron yang bergantung pada hub tetap hidup. Misalnya, metode sepertiClients.All.SendAsync(...)
dapat gagal jika dipanggil tanpaawait
dan metode hub selesai sebelumSendAsync
selesai.
Objek Konteks
Kelas Hub menyertakan Context properti yang berisi properti berikut dengan informasi tentang koneksi:
Properti | Deskripsi |
---|---|
ConnectionId | Mendapatkan ID unik untuk koneksi, yang ditetapkan oleh SignalR. Ada satu ID koneksi untuk setiap koneksi. |
UserIdentifier | Mendapatkan pengidentifikasi pengguna. Secara default, SignalR menggunakan ClaimTypes.NameIdentifier dari yang ClaimsPrincipal terkait dengan koneksi sebagai pengidentifikasi pengguna. |
User | Mendapatkan yang ClaimsPrincipal terkait dengan pengguna saat ini. |
Items | Mendapatkan kumpulan kunci/nilai yang dapat digunakan untuk berbagi data dalam cakupan koneksi ini. Data dapat disimpan dalam koleksi ini dan akan bertahan untuk koneksi di berbagai pemanggilan metode hub. |
Features | Mendapatkan kumpulan fitur yang tersedia pada koneksi. Untuk saat ini, koleksi ini tidak diperlukan dalam sebagian besar skenario, sehingga belum didokumenkan secara rinci. |
ConnectionAborted | CancellationToken Mendapatkan yang memberi tahu ketika koneksi dibatalkan. |
Hub.Context juga berisi metode berikut:
Metode | Deskripsi |
---|---|
GetHttpContext | Mengembalikan HttpContext untuk koneksi, atau null jika koneksi tidak terkait dengan permintaan HTTP. Untuk koneksi HTTP, gunakan metode ini untuk mendapatkan informasi seperti header HTTP dan string kueri. |
Abort | Membatalkan koneksi. |
Objek Klien
Kelas Hub menyertakan Clients properti yang berisi properti berikut untuk komunikasi antara server dan klien:
Properti | Deskripsi |
---|---|
All | Memanggil metode pada semua klien yang terhubung |
Caller | Memanggil metode pada klien yang memanggil metode hub |
Others | Memanggil metode pada semua klien yang terhubung kecuali klien yang memanggil metode |
Hub.Clients juga berisi metode berikut:
Metode | Deskripsi |
---|---|
AllExcept | Memanggil metode pada semua klien yang terhubung kecuali untuk koneksi yang ditentukan |
Client | Memanggil metode pada klien terhubung tertentu |
Clients | Memanggil metode pada klien tertentu yang terhubung |
Group | Memanggil metode pada semua koneksi dalam grup yang ditentukan |
GroupExcept | Memanggil metode pada semua koneksi dalam grup yang ditentukan, kecuali koneksi yang ditentukan |
Groups | Memanggil metode pada beberapa grup koneksi |
OthersInGroup | Memanggil metode pada sekelompok koneksi, tidak termasuk klien yang memanggil metode hub |
User | Memanggil metode pada semua koneksi yang terkait dengan pengguna tertentu |
Users | Memanggil metode pada semua koneksi yang terkait dengan pengguna yang ditentukan |
Setiap properti atau metode dalam tabel sebelumnya mengembalikan objek dengan SendAsync
metode . Metode ini SendAsync
menerima nama metode klien untuk memanggil dan parameter apa pun.
Mengirim pesan ke klien
Untuk melakukan panggilan ke klien tertentu, gunakan properti Clients
objek. Dalam contoh berikut, ada tiga metode hub:
SendMessage
mengirim pesan ke semua klien yang terhubung, menggunakanClients.All
.SendMessageToCaller
mengirim pesan kembali ke pemanggil, menggunakanClients.Caller
.SendMessageToGroup
mengirim pesan ke semua klien dalamSignalR Users
grup.
public async Task SendMessage(string user, string message)
=> await Clients.All.SendAsync("ReceiveMessage", user, message);
public async Task SendMessageToCaller(string user, string message)
=> await Clients.Caller.SendAsync("ReceiveMessage", user, message);
public async Task SendMessageToGroup(string user, string message)
=> await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);
Hub yang sangat ditik
Kelemahan penggunaannya SendAsync
adalah mengandalkan string untuk menentukan metode klien yang akan dipanggil. Ini membuat kode terbuka untuk kesalahan runtime jika nama metode salah eja atau hilang dari klien.
Alternatif untuk menggunakan SendAsync
adalah mengetik Hub kelas dengan kuat dengan Hub<T>. Dalam contoh berikut, ChatHub
metode klien telah diekstraksi ke antarmuka yang disebut IChatClient
:
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Antarmuka ini dapat digunakan untuk merefaktor ChatHub
contoh sebelumnya untuk diketik dengan kuat:
public class StronglyTypedChatHub : Hub<IChatClient>
{
public async Task SendMessage(string user, string message)
=> await Clients.All.ReceiveMessage(user, message);
public async Task SendMessageToCaller(string user, string message)
=> await Clients.Caller.ReceiveMessage(user, message);
public async Task SendMessageToGroup(string user, string message)
=> await Clients.Group("SignalR Users").ReceiveMessage(user, message);
}
Menggunakan Hub<IChatClient>
mengaktifkan pemeriksaan waktu kompilasi metode klien. Ini mencegah masalah yang disebabkan oleh penggunaan string, karena Hub<T>
hanya dapat menyediakan akses ke metode yang ditentukan dalam antarmuka. Menggunakan tipe yang sangat Hub<T>
kuat menonaktifkan kemampuan untuk menggunakan SendAsync
.
Catatan
Akhiran Async
tidak dilucuti dari nama metode. Kecuali metode klien didefinisikan dengan .on('MyMethodAsync')
, jangan gunakan MyMethodAsync
sebagai nama.
Mengubah nama metode hub
Secara default, nama metode hub server adalah nama metode .NET. Untuk mengubah perilaku default ini untuk metode tertentu, gunakan atribut HubMethodName . Klien harus menggunakan nama ini alih-alih nama metode .NET saat memanggil metode:
[HubMethodName("SendMessageToUser")]
public async Task DirectMessage(string user, string message)
=> await Clients.User(user).SendAsync("ReceiveMessage", user, message);
Menangani peristiwa untuk koneksi
SignalR HUBS API menyediakan OnConnectedAsync metode virtual dan OnDisconnectedAsync untuk mengelola dan melacak koneksi. Ambil alih OnConnectedAsync
metode virtual untuk melakukan tindakan saat klien tersambung ke hub, seperti menambahkannya ke grup:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Ambil alih OnDisconnectedAsync
metode virtual untuk melakukan tindakan saat klien terputus. Jika klien memutuskan sambungan dengan sengaja, seperti dengan memanggil connection.stop()
, exception
parameter diatur ke null
. Namun, jika klien terputus karena kesalahan, seperti kegagalan jaringan, exception
parameter berisi pengecualian yang menjelaskan kegagalan:
public override async Task OnDisconnectedAsync(Exception? exception)
{
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync tidak perlu dipanggil dalam , secara otomatis ditangani OnDisconnectedAsyncuntuk Anda.
Menangani kesalahan
Pengecualian yang dilemparkan dalam metode hub dikirim ke klien yang memanggil metode . Pada klien JavaScript, invoke
metode mengembalikan JavaScript Promise
. Klien dapat melampirkan catch
handler ke janji yang dikembalikan atau digunakan try
catch
/dengan async
/await
untuk menangani pengecualian:
try {
await connection.invoke("SendMessage", user, message);
} catch (err) {
console.error(err);
}
Koneksi tidak ditutup saat hub melemparkan pengecualian. Secara default, SignalR mengembalikan pesan kesalahan umum kepada klien, seperti yang ditunjukkan dalam contoh berikut:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'SendMessage' on the server.
Pengecualian tak terduga sering berisi informasi sensitif, seperti nama server database dalam pengecualian yang dipicu ketika koneksi database gagal. SignalR tidak mengekspos pesan kesalahan terperinci ini secara default sebagai ukuran keamanan. Untuk informasi selengkapnya tentang mengapa detail pengecualian ditekan, lihat Pertimbangan keamanan di ASP.NET Core SignalR.
Jika kondisi luar biasa harus disebarkan ke klien, gunakan HubException kelas . HubException
Jika dilemparkan dalam metode hub, SignalRmengirim seluruh pesan pengecualian ke klien, tidak dimodifikasi:
public Task ThrowException()
=> throw new HubException("This error will be sent to the client!");
Catatan
SignalR hanya mengirim Message
properti pengecualian ke klien. Jejak tumpukan dan properti lain pada pengecualian tidak tersedia untuk klien.
Sumber Daya Tambahan:
Oleh Rachel Appel dan Kevin Griffin
Melihat atau mengunduh kode sampel (cara mengunduh)
Apa itu SignalR hub
SignalR HUBS API memungkinkan klien yang terhubung untuk memanggil metode di server, memfasilitasi komunikasi real-time. Server mendefinisikan metode yang dipanggil oleh klien, dan klien menentukan metode yang dipanggil oleh server. SignalR juga memungkinkan komunikasi klien-ke-klien tidak langsung, selalu dimediasi oleh SignalR Hub, memungkinkan pesan dikirim antara klien individu, grup, atau ke semua klien yang terhubung. SignalR mengurus semua yang diperlukan untuk memungkinkan komunikasi klien-ke-server dan server-ke-klien secara real-time.
Mengonfigurasi SignalR hub
Middleware SignalR memerlukan beberapa layanan, yang dikonfigurasi dengan memanggil AddSignalR:
services.AddSignalR();
Saat menambahkan SignalR fungsionalitas ke aplikasi ASP.NET Core, siapkan SignalR rute dengan memanggil MapHub panggilan Startup.Configure
balik metode UseEndpoints :
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>("/chathub");
});
Catatan
ASP.NET rakitan sisi server Core SignalR sekarang diinstal dengan .NET Core SDK. Lihat SignalR rakitan dalam kerangka kerja bersama untuk informasi selengkapnya.
Membuat dan menggunakan hub
Buat hub dengan mendeklarasikan kelas yang mewarisi dari Hub, dan menambahkan metode publik ke dalamnya. Klien dapat memanggil metode yang didefinisikan sebagai public
:
public class ChatHub : Hub
{
public Task SendMessage(string user, string message)
{
return Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
Anda dapat menentukan jenis pengembalian dan parameter, termasuk jenis dan array kompleks, seperti yang Anda lakukan dalam metode C# apa pun. SignalR menangani serialisasi dan deserialisasi objek dan array kompleks dalam parameter Anda dan mengembalikan nilai.
Catatan
Hub bersifat sementara:
- Jangan menyimpan status dalam properti di kelas hub. Setiap panggilan metode hub dijalankan pada instans hub baru.
- Jangan membuat instans hub secara langsung melalui injeksi dependensi. Untuk mengirim pesan ke klien dari tempat lain di aplikasi Anda, gunakan
IHubContext
. - Gunakan
await
saat memanggil metode asinkron yang bergantung pada hub tetap hidup. Misalnya, metode sepertiClients.All.SendAsync(...)
dapat gagal jika dipanggil tanpaawait
dan metode hub selesai sebelumSendAsync
selesai.
Objek Konteks
Kelas Hub memiliki Context properti yang berisi properti berikut dengan informasi tentang koneksi:
Properti | Deskripsi |
---|---|
ConnectionId | Mendapatkan ID unik untuk koneksi, yang ditetapkan oleh SignalR. Ada satu ID koneksi untuk setiap koneksi. |
UserIdentifier | Mendapatkan pengidentifikasi pengguna. Secara default, SignalR menggunakan ClaimTypes.NameIdentifier dari yang ClaimsPrincipal terkait dengan koneksi sebagai pengidentifikasi pengguna. |
User | Mendapatkan yang ClaimsPrincipal terkait dengan pengguna saat ini. |
Items | Mendapatkan kumpulan kunci/nilai yang dapat digunakan untuk berbagi data dalam cakupan koneksi ini. Data dapat disimpan dalam koleksi ini dan akan bertahan untuk koneksi di berbagai pemanggilan metode hub. |
Features | Mendapatkan kumpulan fitur yang tersedia pada koneksi. Untuk saat ini, koleksi ini tidak diperlukan dalam sebagian besar skenario, sehingga belum didokumenkan secara rinci. |
ConnectionAborted | CancellationToken Mendapatkan yang memberi tahu ketika koneksi dibatalkan. |
Hub.Context juga berisi metode berikut:
Metode | Deskripsi |
---|---|
GetHttpContext | Mengembalikan HttpContext untuk koneksi, atau null jika koneksi tidak terkait dengan permintaan HTTP. Untuk koneksi HTTP, Anda dapat menggunakan metode ini untuk mendapatkan informasi seperti header HTTP dan string kueri. |
Abort | Membatalkan koneksi. |
Objek Klien
Kelas Hub memiliki Clients properti yang berisi properti berikut untuk komunikasi antara server dan klien:
Properti | Deskripsi |
---|---|
All | Memanggil metode pada semua klien yang terhubung |
Caller | Memanggil metode pada klien yang memanggil metode hub |
Others | Memanggil metode pada semua klien yang terhubung kecuali klien yang memanggil metode |
Hub.Clients juga berisi metode berikut:
Metode | Deskripsi |
---|---|
AllExcept | Memanggil metode pada semua klien yang terhubung kecuali untuk koneksi yang ditentukan |
Client | Memanggil metode pada klien terhubung tertentu |
Clients | Memanggil metode pada klien tertentu yang terhubung |
Group | Memanggil metode pada semua koneksi dalam grup yang ditentukan |
GroupExcept | Memanggil metode pada semua koneksi dalam grup yang ditentukan, kecuali koneksi yang ditentukan |
Groups | Memanggil metode pada beberapa grup koneksi |
OthersInGroup | Memanggil metode pada sekelompok koneksi, tidak termasuk klien yang memanggil metode hub |
User | Memanggil metode pada semua koneksi yang terkait dengan pengguna tertentu |
Users | Memanggil metode pada semua koneksi yang terkait dengan pengguna yang ditentukan |
Setiap properti atau metode dalam tabel sebelumnya mengembalikan objek dengan SendAsync
metode . Metode ini SendAsync
memungkinkan Anda untuk memberikan nama dan parameter metode klien untuk dipanggil.
Mengirim pesan ke klien
Untuk melakukan panggilan ke klien tertentu, gunakan properti Clients
objek. Dalam contoh berikut, ada tiga metode Hub:
SendMessage
mengirim pesan ke semua klien yang terhubung, menggunakanClients.All
.SendMessageToCaller
mengirim pesan kembali ke pemanggil, menggunakanClients.Caller
.SendMessageToGroup
mengirim pesan ke semua klien dalamSignalR Users
grup.
public Task SendMessage(string user, string message)
{
return Clients.All.SendAsync("ReceiveMessage", user, message);
}
public Task SendMessageToCaller(string user, string message)
{
return Clients.Caller.SendAsync("ReceiveMessage", user, message);
}
public Task SendMessageToGroup(string user, string message)
{
return Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);
}
Hub yang sangat ditik
Kelemahan penggunaannya SendAsync
adalah mengandalkan string ajaib untuk menentukan metode klien yang akan dipanggil. Ini membuat kode terbuka untuk kesalahan runtime jika nama metode salah eja atau hilang dari klien.
Alternatif untuk menggunakan SendAsync
adalah mengetik Hub dengan kuat dengan Hub<T>. Dalam contoh berikut, ChatHub
metode klien telah diekstraksi ke antarmuka yang disebut IChatClient
.
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Antarmuka ini dapat digunakan untuk merefaktor contoh sebelumnya ChatHub
:
public class StronglyTypedChatHub : Hub<IChatClient>
{
public async Task SendMessage(string user, string message)
{
await Clients.All.ReceiveMessage(user, message);
}
public Task SendMessageToCaller(string user, string message)
{
return Clients.Caller.ReceiveMessage(user, message);
}
}
Menggunakan Hub<IChatClient>
mengaktifkan pemeriksaan waktu kompilasi metode klien. Ini mencegah masalah yang disebabkan oleh penggunaan string ajaib, karena Hub<T>
hanya dapat menyediakan akses ke metode yang ditentukan dalam antarmuka.
Menggunakan tipe yang sangat Hub<T>
kuat menonaktifkan kemampuan untuk menggunakan SendAsync
. Metode apa pun yang ditentukan pada antarmuka masih dapat didefinisikan sebagai asinkron. Bahkan, masing-masing metode ini harus mengembalikan Task
. Karena ini adalah antarmuka, jangan gunakan async
kata kunci. Contoh:
public interface IClient
{
Task ClientMethod();
}
Catatan
Akhiran Async
tidak dilucuti dari nama metode. Kecuali metode klien Anda didefinisikan dengan .on('MyMethodAsync')
, Anda tidak boleh menggunakan MyMethodAsync
sebagai nama.
Mengubah nama metode hub
Secara default, nama metode hub server adalah nama metode .NET. Namun, Anda dapat menggunakan atribut HubMethodName untuk mengubah default ini dan menentukan nama untuk metode secara manual. Klien harus menggunakan nama ini, alih-alih nama metode .NET, saat memanggil metode:
[HubMethodName("SendMessageToUser")]
public Task DirectMessage(string user, string message)
{
return Clients.User(user).SendAsync("ReceiveMessage", user, message);
}
Menangani peristiwa untuk koneksi
SignalR HUBS API menyediakan OnConnectedAsync metode virtual dan OnDisconnectedAsync untuk mengelola dan melacak koneksi. Ambil alih OnConnectedAsync
metode virtual untuk melakukan tindakan saat klien terhubung ke Hub, seperti menambahkannya ke grup:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Ambil alih OnDisconnectedAsync
metode virtual untuk melakukan tindakan saat klien terputus. Jika klien memutuskan sambungan dengan sengaja (dengan memanggil connection.stop()
, misalnya), exception
parameternya adalah null
. Namun, jika klien terputus karena kesalahan (seperti kegagalan jaringan), exception
parameter akan berisi pengecualian yang menjelaskan kegagalan:
public override async Task OnDisconnectedAsync(Exception exception)
{
await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", "I", "disconnect");
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync tidak perlu dipanggil dalam , secara otomatis ditangani OnDisconnectedAsyncuntuk Anda.
Peringatan
Peringatan keamanan: Mengekspos ConnectionId
dapat menyebabkan peniruan berbahaya jika SignalR server atau versi klien ASP.NET Core 2.2 atau yang lebih lama.
Menangani kesalahan
Pengecualian yang dilemparkan dalam metode hub Anda dikirim ke klien yang memanggil metode . Pada klien JavaScript, invoke
metode mengembalikan JavaScript Promise
. Ketika klien menerima kesalahan dengan handler yang melekat pada janji menggunakan catch
, klien dipanggil dan diteruskan sebagai objek JavaScript Error
:
connection.invoke("SendMessage", user, message).catch(err => console.error(err));
Jika Hub Anda melemparkan pengecualian, koneksi tidak ditutup. Secara default, SignalR mengembalikan pesan kesalahan umum kepada klien. Contohnya:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'MethodName' on the server.
Pengecualian tak terduga sering berisi informasi sensitif, seperti nama server database dalam pengecualian yang dipicu ketika koneksi database gagal. SignalR tidak mengekspos pesan kesalahan terperinci ini secara default sebagai ukuran keamanan. Untuk informasi selengkapnya tentang mengapa detail pengecualian ditekan, lihat Pertimbangan keamanan di ASP.NET Core SignalR.
Jika Anda memiliki kondisi luar biasa yang ingin Anda sebarkan ke klien, Anda dapat menggunakan kelas .HubException Jika Anda melempar HubException
dari metode hub Anda, SignalRakan mengirim seluruh pesan ke klien, tidak dimodifikasi:
public Task ThrowException()
{
throw new HubException("This error will be sent to the client!");
}
Catatan
SignalR hanya mengirim Message
properti pengecualian ke klien. Jejak tumpukan dan properti lain pada pengecualian tidak tersedia untuk klien.
Sumber Daya Tambahan:
Oleh Rachel Appel dan Kevin Griffin
Melihat atau mengunduh kode sampel (cara mengunduh)
Apa itu SignalR hub
SignalR HUBS API memungkinkan klien yang terhubung untuk memanggil metode di server, memfasilitasi komunikasi real-time. Server mendefinisikan metode yang dipanggil oleh klien, dan klien menentukan metode yang dipanggil oleh server. SignalR juga memungkinkan komunikasi klien-ke-klien tidak langsung, selalu dimediasi oleh SignalR Hub, memungkinkan pesan dikirim antara klien individu, grup, atau ke semua klien yang terhubung. SignalR mengurus semua yang diperlukan untuk memungkinkan komunikasi klien-ke-server dan server-ke-klien secara real-time.
Mengonfigurasi SignalR hub
Middleware SignalR memerlukan beberapa layanan, yang dikonfigurasi dengan memanggil AddSignalR:
services.AddSignalR();
Saat menambahkan SignalR fungsionalitas ke aplikasi ASP.NET Core, siapkan SignalR rute dengan memanggil UseSignalR dalam Startup.Configure
metode :
app.UseSignalR(route =>
{
route.MapHub<ChatHub>("/chathub");
});
Membuat dan menggunakan hub
Buat hub dengan mendeklarasikan kelas yang mewarisi dari Hub, dan menambahkan metode publik ke dalamnya. Klien dapat memanggil metode yang didefinisikan sebagai public
:
public class ChatHub : Hub
{
public Task SendMessage(string user, string message)
{
return Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
Anda dapat menentukan jenis pengembalian dan parameter, termasuk jenis dan array kompleks, seperti yang Anda lakukan dalam metode C# apa pun. SignalR menangani serialisasi dan deserialisasi objek dan array kompleks dalam parameter Anda dan mengembalikan nilai.
Catatan
Hub bersifat sementara:
- Jangan menyimpan status dalam properti di kelas hub. Setiap panggilan metode hub dijalankan pada instans hub baru.
- Jangan membuat instans hub secara langsung melalui injeksi dependensi. Untuk mengirim pesan ke klien dari tempat lain di aplikasi Anda, gunakan
IHubContext
. - Gunakan
await
saat memanggil metode asinkron yang bergantung pada hub tetap hidup. Misalnya, metode sepertiClients.All.SendAsync(...)
dapat gagal jika dipanggil tanpaawait
dan metode hub selesai sebelumSendAsync
selesai.
Objek Konteks
Kelas Hub memiliki Context properti yang berisi properti berikut dengan informasi tentang koneksi:
Properti | Deskripsi |
---|---|
ConnectionId | Mendapatkan ID unik untuk koneksi, yang ditetapkan oleh SignalR. Ada satu ID koneksi untuk setiap koneksi. |
UserIdentifier | Mendapatkan pengidentifikasi pengguna. Secara default, SignalR menggunakan ClaimTypes.NameIdentifier dari yang ClaimsPrincipal terkait dengan koneksi sebagai pengidentifikasi pengguna. |
User | Mendapatkan yang ClaimsPrincipal terkait dengan pengguna saat ini. |
Items | Mendapatkan kumpulan kunci/nilai yang dapat digunakan untuk berbagi data dalam cakupan koneksi ini. Data dapat disimpan dalam koleksi ini dan akan bertahan untuk koneksi di berbagai pemanggilan metode hub. |
Features | Mendapatkan kumpulan fitur yang tersedia pada koneksi. Untuk saat ini, koleksi ini tidak diperlukan dalam sebagian besar skenario, sehingga belum didokumenkan secara rinci. |
ConnectionAborted | CancellationToken Mendapatkan yang memberi tahu ketika koneksi dibatalkan. |
Hub.Context juga berisi metode berikut:
Metode | Deskripsi |
---|---|
GetHttpContext | Mengembalikan HttpContext untuk koneksi, atau null jika koneksi tidak terkait dengan permintaan HTTP. Untuk koneksi HTTP, Anda dapat menggunakan metode ini untuk mendapatkan informasi seperti header HTTP dan string kueri. |
Abort | Membatalkan koneksi. |
Objek Klien
Kelas Hub memiliki Clients properti yang berisi properti berikut untuk komunikasi antara server dan klien:
Properti | Deskripsi |
---|---|
All | Memanggil metode pada semua klien yang terhubung |
Caller | Memanggil metode pada klien yang memanggil metode hub |
Others | Memanggil metode pada semua klien yang terhubung kecuali klien yang memanggil metode |
Hub.Clients juga berisi metode berikut:
Metode | Deskripsi |
---|---|
AllExcept | Memanggil metode pada semua klien yang terhubung kecuali untuk koneksi yang ditentukan |
Client | Memanggil metode pada klien terhubung tertentu |
Clients | Memanggil metode pada klien tertentu yang terhubung |
Group | Memanggil metode pada semua koneksi dalam grup yang ditentukan |
GroupExcept | Memanggil metode pada semua koneksi dalam grup yang ditentukan, kecuali koneksi yang ditentukan |
Groups | Memanggil metode pada beberapa grup koneksi |
OthersInGroup | Memanggil metode pada sekelompok koneksi, tidak termasuk klien yang memanggil metode hub |
User | Memanggil metode pada semua koneksi yang terkait dengan pengguna tertentu |
Users | Memanggil metode pada semua koneksi yang terkait dengan pengguna yang ditentukan |
Setiap properti atau metode dalam tabel sebelumnya mengembalikan objek dengan SendAsync
metode . Metode ini SendAsync
memungkinkan Anda untuk memberikan nama dan parameter metode klien untuk dipanggil.
Mengirim pesan ke klien
Untuk melakukan panggilan ke klien tertentu, gunakan properti Clients
objek. Dalam contoh berikut, ada tiga metode Hub:
SendMessage
mengirim pesan ke semua klien yang terhubung, menggunakanClients.All
.SendMessageToCaller
mengirim pesan kembali ke pemanggil, menggunakanClients.Caller
.SendMessageToGroup
mengirim pesan ke semua klien dalamSignalR Users
grup.
public Task SendMessage(string user, string message)
{
return Clients.All.SendAsync("ReceiveMessage", user, message);
}
public Task SendMessageToCaller(string user, string message)
{
return Clients.Caller.SendAsync("ReceiveMessage", user, message);
}
public Task SendMessageToGroup(string user, string message)
{
return Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);
}
Hub yang sangat ditik
Kelemahan penggunaannya SendAsync
adalah mengandalkan string ajaib untuk menentukan metode klien yang akan dipanggil. Ini membuat kode terbuka untuk kesalahan runtime jika nama metode salah eja atau hilang dari klien.
Alternatif untuk menggunakan SendAsync
adalah mengetik Hub dengan kuat dengan Hub<T>. Dalam contoh berikut, ChatHub
metode klien telah diekstraksi ke antarmuka yang disebut IChatClient
.
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Antarmuka ini dapat digunakan untuk merefaktor contoh sebelumnya ChatHub
:
public class StronglyTypedChatHub : Hub<IChatClient>
{
public async Task SendMessage(string user, string message)
{
await Clients.All.ReceiveMessage(user, message);
}
public Task SendMessageToCaller(string user, string message)
{
return Clients.Caller.ReceiveMessage(user, message);
}
}
Menggunakan Hub<IChatClient>
mengaktifkan pemeriksaan waktu kompilasi metode klien. Ini mencegah masalah yang disebabkan oleh penggunaan string ajaib, karena Hub<T>
hanya dapat menyediakan akses ke metode yang ditentukan dalam antarmuka.
Menggunakan tipe yang sangat Hub<T>
kuat menonaktifkan kemampuan untuk menggunakan SendAsync
. Metode apa pun yang ditentukan pada antarmuka masih dapat didefinisikan sebagai asinkron. Bahkan, masing-masing metode ini harus mengembalikan Task
. Karena ini adalah antarmuka, jangan gunakan async
kata kunci. Contoh:
public interface IClient
{
Task ClientMethod();
}
Catatan
Akhiran Async
tidak dilucuti dari nama metode. Kecuali metode klien Anda didefinisikan dengan .on('MyMethodAsync')
, Anda tidak boleh menggunakan MyMethodAsync
sebagai nama.
Mengubah nama metode hub
Secara default, nama metode hub server adalah nama metode .NET. Namun, Anda dapat menggunakan atribut HubMethodName untuk mengubah default ini dan menentukan nama untuk metode secara manual. Klien harus menggunakan nama ini, alih-alih nama metode .NET, saat memanggil metode:
[HubMethodName("SendMessageToUser")]
public Task DirectMessage(string user, string message)
{
return Clients.User(user).SendAsync("ReceiveMessage", user, message);
}
Menangani peristiwa untuk koneksi
SignalR HUBS API menyediakan OnConnectedAsync metode virtual dan OnDisconnectedAsync untuk mengelola dan melacak koneksi. Ambil alih OnConnectedAsync
metode virtual untuk melakukan tindakan saat klien terhubung ke Hub, seperti menambahkannya ke grup:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Ambil alih OnDisconnectedAsync
metode virtual untuk melakukan tindakan saat klien terputus. Jika klien memutuskan sambungan dengan sengaja (dengan memanggil connection.stop()
, misalnya), exception
parameternya adalah null
. Namun, jika klien terputus karena kesalahan (seperti kegagalan jaringan), exception
parameter akan berisi pengecualian yang menjelaskan kegagalan:
public override async Task OnDisconnectedAsync(Exception exception)
{
await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", "I", "disconnect");
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync tidak perlu dipanggil dalam , secara otomatis ditangani OnDisconnectedAsyncuntuk Anda.
Peringatan
Peringatan keamanan: Mengekspos ConnectionId
dapat menyebabkan peniruan berbahaya jika SignalR server atau versi klien ASP.NET Core 2.2 atau yang lebih lama.
Menangani kesalahan
Pengecualian yang dilemparkan dalam metode hub Anda dikirim ke klien yang memanggil metode . Pada klien JavaScript, invoke
metode mengembalikan JavaScript Promise
. Ketika klien menerima kesalahan dengan handler yang melekat pada janji menggunakan catch
, klien dipanggil dan diteruskan sebagai objek JavaScript Error
:
connection.invoke("SendMessage", user, message).catch(err => console.error(err));
Jika Hub Anda melemparkan pengecualian, koneksi tidak ditutup. Secara default, SignalR mengembalikan pesan kesalahan umum kepada klien. Contohnya:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'MethodName' on the server.
Pengecualian tak terduga sering berisi informasi sensitif, seperti nama server database dalam pengecualian yang dipicu ketika koneksi database gagal. SignalR tidak mengekspos pesan kesalahan terperinci ini secara default sebagai ukuran keamanan. Untuk informasi selengkapnya tentang mengapa detail pengecualian ditekan, lihat Pertimbangan keamanan di ASP.NET Core SignalR.
Jika Anda memiliki kondisi luar biasa yang ingin Anda sebarkan ke klien, Anda dapat menggunakan kelas .HubException Jika Anda melempar HubException
dari metode hub Anda, SignalRakan mengirim seluruh pesan ke klien, tidak dimodifikasi:
public Task ThrowException()
{
throw new HubException("This error will be sent to the client!");
}
Catatan
SignalR hanya mengirim Message
properti pengecualian ke klien. Jejak tumpukan dan properti lain pada pengecualian tidak tersedia untuk klien.
Sumber Daya Tambahan:
ASP.NET Core