Używanie koncentratorów w programie SignalR dla platformy ASP.NET Core
Przez Rachel Appel i Kevin Griffin
Interfejs SignalR API usługi Hubs umożliwia połączonym klientom wywoływanie metod na serwerze, ułatwiając komunikację w czasie rzeczywistym. Serwer definiuje metody wywoływane przez klienta, a klient definiuje metody wywoływane przez serwer. SignalR Umożliwia również pośrednią komunikację między klientem a klientem, zawsze mediaowaną przez SignalR centrum, umożliwiając wysyłanie komunikatów między poszczególnymi klientami, grupami lub wszystkimi połączonymi klientami. SignalR dba o wszystko, co jest wymagane, aby umożliwić komunikację między klientem i klientem w czasie rzeczywistym.
Konfigurowanie SignalR koncentratorów
Aby zarejestrować usługi wymagane przez SignalR centra, wywołaj metodę AddSignalR w pliku Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddSignalR();
Aby skonfigurować SignalR punkty końcowe, wywołaj metodę MapHub, również w pliku Program.cs
:
app.MapRazorPages();
app.MapHub<ChatHub>("/Chat");
app.Run();
Uwaga
zestawy ASP.NET Core SignalR po stronie serwera są teraz instalowane przy użyciu zestawu .NET Core SDK. Aby uzyskać więcej informacji, zobacz SignalR zestawy w strukturze udostępnionej .
Tworzenie centrów i korzystanie z nich
Utwórz centrum, deklarując klasę dziedziczącą z Hubklasy . Dodaj public
metody do klasy, aby umożliwić ich wywoływanie z klientów:
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
=> await Clients.All.SendAsync("ReceiveMessage", user, message);
}
Uwaga
Koncentratory są przejściowe:
- Nie przechowuj stanu we właściwości klasy centrum. Każde wywołanie metody centrum jest wykonywane w nowym wystąpieniu centrum.
- Nie tworzy wystąpienia koncentratora bezpośrednio za pośrednictwem wstrzykiwania zależności. Aby wysyłać komunikaty do klienta z innego miejsca w aplikacji, użyj polecenia
IHubContext
. - Użyj
await
funkcji podczas wywoływania metod asynchronicznych, które zależą od centrum pozostającego przy życiu. Na przykład metoda taka jakClients.All.SendAsync(...)
może zakończyć się niepowodzeniem, jeśli zostanie wywołana bezawait
, a metoda centrum zostanie ukończona przed zakończeniemSendAsync
.
Obiekt Context
Klasa Hub zawiera właściwość zawierającą Context następujące właściwości z informacjami o połączeniu:
Właściwości | opis |
---|---|
ConnectionId | Pobiera unikatowy identyfikator połączenia przypisanego przez SignalR. Dla każdego połączenia istnieje jeden identyfikator połączenia. |
UserIdentifier | Pobiera identyfikator użytkownika. Domyślnie SignalR używa ClaimTypes.NameIdentifier elementu z skojarzonego ClaimsPrincipal z połączeniem jako identyfikatora użytkownika. |
User | ClaimsPrincipal Pobiera element skojarzony z bieżącym użytkownikiem. |
Items | Pobiera kolekcję klucz/wartość, która może służyć do udostępniania danych w zakresie tego połączenia. Dane mogą być przechowywane w tej kolekcji i będą utrwalane dla połączenia między różnymi wywołaniami metod centrum. |
Features | Pobiera kolekcję funkcji dostępnych w połączeniu. Na razie ta kolekcja nie jest potrzebna w większości scenariuszy, więc nie została jeszcze szczegółowo udokumentowana. |
ConnectionAborted | Pobiera element CancellationToken , który powiadamia o przerwaniu połączenia. |
Hub.Context Zawiera również następujące metody:
Metoda | opis |
---|---|
GetHttpContext | HttpContext Zwraca wartość dla połączenia lub null jeśli połączenie nie jest skojarzone z żądaniem HTTP. W przypadku połączeń HTTP użyj tej metody, aby uzyskać informacje, takie jak nagłówki HTTP i ciągi zapytania. |
Abort | Przerywa połączenie. |
Obiekt Klienci
Klasa Hub zawiera właściwość zawierającą Clients następujące właściwości komunikacji między serwerem a klientem:
Właściwości | opis |
---|---|
All | Wywołuje metodę na wszystkich połączonych klientach |
Caller | Wywołuje metodę na kliencie, który wywołał metodę centrum |
Others | Wywołuje metodę na wszystkich połączonych klientach z wyjątkiem klienta, który wywołał metodę |
Hub.Clients Zawiera również następujące metody:
Metoda | opis |
---|---|
AllExcept | Wywołuje metodę na wszystkich połączonych klientach z wyjątkiem określonych połączeń |
Client | Wywołuje metodę na określonym połączonym kliencie |
Clients | Wywołuje metodę dla określonych połączonych klientów |
Group | Wywołuje metodę dla wszystkich połączeń w określonej grupie |
GroupExcept | Wywołuje metodę dla wszystkich połączeń w określonej grupie, z wyjątkiem określonych połączeń |
Groups | Wywołuje metodę w wielu grupach połączeń |
OthersInGroup | Wywołuje metodę w grupie połączeń, z wyłączeniem klienta, który wywołał metodę centrum |
User | Wywołuje metodę dla wszystkich połączeń skojarzonych z określonym użytkownikiem |
Users | Wywołuje metodę dla wszystkich połączeń skojarzonych z określonymi użytkownikami |
Każda właściwość lub metoda w poprzednich tabelach zwraca obiekt z SendAsync
metodą . Metoda SendAsync
otrzymuje nazwę metody klienta do wywołania i wszystkich parametrów.
Obiekt zwracany przez Client
metody i Caller
zawiera również metodę InvokeAsync
, która może służyć do oczekiwania na wynik od klienta.
Wysyłanie komunikatów do klientów
Aby wykonywać wywołania do określonych klientów, użyj właściwości Clients
obiektu. W poniższym przykładzie istnieją trzy metody koncentratora:
SendMessage
wysyła komunikat do wszystkich połączonych klientów przy użyciu poleceniaClients.All
.SendMessageToCaller
wysyła wiadomość z powrotem do wywołującego przy użyciu poleceniaClients.Caller
.SendMessageToGroup
wysyła komunikat do wszystkich klientów wSignalR Users
grupie.
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);
Silnie typizowane koncentratory
Wadą użycia SendAsync
jest to, że opiera się na ciągu, aby określić metodę klienta do wywołania. Spowoduje to pozostawienie kodu otwartego na błędy środowiska uruchomieniowego, jeśli nazwa metody jest błędnie wpisać lub brakuje jej w kliencie.
Alternatywą do użycia SendAsync
jest silnie typizowanej Hub klasy za pomocą Hub<T>polecenia . W poniższym przykładzie ChatHub
metoda klienta została wyodrębniona do interfejsu o nazwie IChatClient
:
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Ten interfejs może służyć do refaktoryzacji poprzedniego ChatHub
przykładu, aby był silnie typowany:
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);
}
Użycie Hub<IChatClient>
umożliwia sprawdzanie czasu kompilacji metod klienta. Zapobiega to problemom spowodowanym używaniem ciągów, ponieważ Hub<T>
może zapewnić dostęp tylko do metod zdefiniowanych w interfejsie. Użycie silnie typizowanego Hub<T>
elementu wyłącza możliwość używania elementu SendAsync
.
Uwaga
Sufiks Async
nie jest usuwany z nazw metod. Chyba że metoda klienta jest zdefiniowana za .on('MyMethodAsync')
pomocą metody , nie używaj MyMethodAsync
jej jako nazwy.
Wyniki klienta
Oprócz wykonywania wywołań do klientów serwer może zażądać wyniku od klienta. Wymaga to, aby serwer używał ISingleClientProxy.InvokeAsync
polecenia , a klient zwrócił wynik z programu .On
obsługi.
Istnieją dwa sposoby używania interfejsu API na serwerze, a pierwszą metodą jest wywołanie Client(...)
lub Caller
na Clients
właściwość w metodzie Hub:
public class ChatHub : Hub
{
public async Task<string> WaitForMessage(string connectionId)
{
var message = await Clients.Client(connectionId).InvokeAsync<string>(
"GetMessage");
return message;
}
}
Drugim sposobem jest wywołanie Client(...)
wystąpienia IHubContext<T>
klasy :
async Task SomeMethod(IHubContext<MyHub> context)
{
string result = await context.Clients.Client(connectionID).InvokeAsync<string>(
"GetMessage");
}
Silnie typizowane koncentratory mogą również zwracać wartości z metod interfejsu:
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;
}
}
Klienci zwracają wyniki w swoich .On(...)
programach obsługi, jak pokazano poniżej:
Klient .NET
hubConnection.On("GetMessage", async () =>
{
Console.WriteLine("Enter message:");
var message = await Console.In.ReadLineAsync();
return message;
});
Klient typescript
hubConnection.on("GetMessage", async () => {
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("message");
}, 100);
});
return promise;
});
Klienta środowiska Java
hubConnection.onWithResult("GetMessage", () -> {
return Single.just("message");
});
Zmienianie nazwy metody centrum
Domyślnie nazwa metody centrum serwera to nazwa metody .NET. Aby zmienić to domyślne zachowanie dla określonej metody, użyj atrybutu HubMethodName . Klient powinien użyć tej nazwy zamiast nazwy metody .NET podczas wywoływania metody:
[HubMethodName("SendMessageToUser")]
public async Task DirectMessage(string user, string message)
=> await Clients.User(user).SendAsync("ReceiveMessage", user, message);
Wstrzykiwanie usług do centrum
Konstruktory koncentratora mogą akceptować usługi z di jako parametry, które mogą być przechowywane we właściwościach klasy do użycia w metodzie piasty.
W przypadku wstrzykiwania wielu usług dla różnych metod centrum lub jako alternatywnego sposobu pisania kodu metody centrum mogą również akceptować usługi z di. Domyślnie parametry metody centrum są sprawdzane i rozpoznawane z di, jeśli to możliwe.
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);
}
}
Jeśli nie jest wymagane niejawne rozpoznawanie parametrów z usług, wyłącz je za pomocą polecenia DisableImplicitFromServicesParameters.
Aby jawnie określić, które parametry są rozpoznawane z di w metodach koncentratora, użyj opcji i użyj DisableImplicitFromServicesParameters
atrybutu [FromServices]
lub atrybutu niestandardowego, który implementuje IFromServiceMetadata
parametry metody centrum, które powinny zostać rozpoznane z 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);
}
}
Uwaga
Ta funkcja korzysta z IServiceProviderIsServiceelementu , który jest opcjonalnie implementowany przez implementacje di. Jeśli kontener DI aplikacji nie obsługuje tej funkcji, wstrzykiwanie usług do metod centrum nie jest obsługiwane.
Obsługa usług kluczy w iniekcji zależności
Usługi kluczy odnoszą się do mechanizmu rejestrowania i pobierania usług wstrzykiwania zależności (DI) przy użyciu kluczy. Usługa jest skojarzona z kluczem przez wywołanie AddKeyedSingleton metody (lub AddKeyedScoped
AddKeyedTransient
) w celu jej zarejestrowania. Uzyskaj dostęp do zarejestrowanej usługi, określając klucz za pomocą atrybutu [FromKeyedServices]
. Poniższy kod pokazuje, jak używać usług kluczy:
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"));
}
}
Obsługa zdarzeń dla połączenia
Interfejs SignalR API usługi Hubs udostępnia OnConnectedAsync metody i OnDisconnectedAsync wirtualne do zarządzania połączeniami i śledzenia ich. Zastąpij metodę wirtualną OnConnectedAsync
, aby wykonywać akcje, gdy klient łączy się z centrum, na przykład dodając ją do grupy:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Zastąpij metodę wirtualną OnDisconnectedAsync
, aby wykonywać akcje po rozłączeniu klienta. Jeśli klient rozłącza się celowo, na przykład przez wywołanie connection.stop()
metody , exception
parametr jest ustawiony na null
wartość . Jeśli jednak klient rozłącza się z powodu błędu, takiego jak awaria sieci, exception
parametr zawiera wyjątek opisujący błąd:
public override async Task OnDisconnectedAsync(Exception? exception)
{
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync nie musi być wywoływana w elemecie OnDisconnectedAsync, jest automatycznie obsługiwana.
Obsługa błędów
Wyjątki zgłaszane w metodach centrum są wysyłane do klienta, który wywołał metodę. Na kliencie invoke
JavaScript metoda zwraca kod JavaScript Promise
. Klienci mogą dołączyć procedurę catch
obsługi do zwróconej obietnicy lub użyć polecenia try
/catch
w async
/await
celu obsługi wyjątków:
try {
await connection.invoke("SendMessage", user, message);
} catch (err) {
console.error(err);
}
Połączenia nie są zamykane, gdy centrum zgłasza wyjątek. Domyślnie SignalR zwraca ogólny komunikat o błędzie do klienta, jak pokazano w poniższym przykładzie:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'SendMessage' on the server.
Nieoczekiwane wyjątki często zawierają poufne informacje, takie jak nazwa serwera bazy danych w wyjątku wyzwalanym w przypadku niepowodzenia połączenia z bazą danych. SignalR domyślnie nie ujawnia tych szczegółowych komunikatów o błędach jako środka zabezpieczeń. Aby uzyskać więcej informacji o tym, dlaczego szczegóły wyjątku są pomijane, zobacz Zagadnienia dotyczące zabezpieczeń w programie ASP.NET Core SignalR.
Jeśli do klienta należy propagować wyjątkowy warunek, użyj HubException klasy . Jeśli element HubException
jest zgłaszany w metodzie centrum, SignalRwysyła cały komunikat o wyjątku do klienta, niezmodyfikowany:
public Task ThrowException()
=> throw new HubException("This error will be sent to the client!");
Uwaga
SignalR wysyła Message
tylko właściwość wyjątku do klienta. Ślad stosu i inne właściwości wyjątku nie są dostępne dla klienta.
Dodatkowe zasoby
Przez Rachel Appel i Kevin Griffin
Interfejs SignalR API usługi Hubs umożliwia połączonym klientom wywoływanie metod na serwerze, ułatwiając komunikację w czasie rzeczywistym. Serwer definiuje metody wywoływane przez klienta, a klient definiuje metody wywoływane przez serwer. SignalR Umożliwia również pośrednią komunikację między klientem a klientem, zawsze mediaowaną przez SignalR centrum, umożliwiając wysyłanie komunikatów między poszczególnymi klientami, grupami lub wszystkimi połączonymi klientami. SignalR dba o wszystko, co jest wymagane, aby umożliwić komunikację między klientem i klientem w czasie rzeczywistym.
Konfigurowanie SignalR koncentratorów
Aby zarejestrować usługi wymagane przez SignalR centra, wywołaj metodę AddSignalR w pliku Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddSignalR();
Aby skonfigurować SignalR punkty końcowe, wywołaj metodę MapHub, również w pliku Program.cs
:
app.MapRazorPages();
app.MapHub<ChatHub>("/Chat");
app.Run();
Uwaga
zestawy ASP.NET Core SignalR po stronie serwera są teraz instalowane przy użyciu zestawu .NET Core SDK. Aby uzyskać więcej informacji, zobacz SignalR zestawy w strukturze udostępnionej .
Tworzenie centrów i korzystanie z nich
Utwórz centrum, deklarując klasę dziedziczącą z Hubklasy . Dodaj public
metody do klasy, aby umożliwić ich wywoływanie z klientów:
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
=> await Clients.All.SendAsync("ReceiveMessage", user, message);
}
Uwaga
Koncentratory są przejściowe:
- Nie przechowuj stanu we właściwości klasy centrum. Każde wywołanie metody centrum jest wykonywane w nowym wystąpieniu centrum.
- Nie tworzy wystąpienia koncentratora bezpośrednio za pośrednictwem wstrzykiwania zależności. Aby wysyłać komunikaty do klienta z innego miejsca w aplikacji, użyj polecenia
IHubContext
. - Użyj
await
funkcji podczas wywoływania metod asynchronicznych, które zależą od centrum pozostającego przy życiu. Na przykład metoda taka jakClients.All.SendAsync(...)
może zakończyć się niepowodzeniem, jeśli zostanie wywołana bezawait
, a metoda centrum zostanie ukończona przed zakończeniemSendAsync
.
Obiekt Context
Klasa Hub zawiera właściwość zawierającą Context następujące właściwości z informacjami o połączeniu:
Właściwości | opis |
---|---|
ConnectionId | Pobiera unikatowy identyfikator połączenia przypisanego przez SignalR. Dla każdego połączenia istnieje jeden identyfikator połączenia. |
UserIdentifier | Pobiera identyfikator użytkownika. Domyślnie SignalR używa ClaimTypes.NameIdentifier elementu z skojarzonego ClaimsPrincipal z połączeniem jako identyfikatora użytkownika. |
User | ClaimsPrincipal Pobiera element skojarzony z bieżącym użytkownikiem. |
Items | Pobiera kolekcję klucz/wartość, która może służyć do udostępniania danych w zakresie tego połączenia. Dane mogą być przechowywane w tej kolekcji i będą utrwalane dla połączenia między różnymi wywołaniami metod centrum. |
Features | Pobiera kolekcję funkcji dostępnych w połączeniu. Na razie ta kolekcja nie jest potrzebna w większości scenariuszy, więc nie została jeszcze szczegółowo udokumentowana. |
ConnectionAborted | Pobiera element CancellationToken , który powiadamia o przerwaniu połączenia. |
Hub.Context Zawiera również następujące metody:
Metoda | opis |
---|---|
GetHttpContext | HttpContext Zwraca wartość dla połączenia lub null jeśli połączenie nie jest skojarzone z żądaniem HTTP. W przypadku połączeń HTTP użyj tej metody, aby uzyskać informacje, takie jak nagłówki HTTP i ciągi zapytania. |
Abort | Przerywa połączenie. |
Obiekt Klienci
Klasa Hub zawiera właściwość zawierającą Clients następujące właściwości komunikacji między serwerem a klientem:
Właściwości | opis |
---|---|
All | Wywołuje metodę na wszystkich połączonych klientach |
Caller | Wywołuje metodę na kliencie, który wywołał metodę centrum |
Others | Wywołuje metodę na wszystkich połączonych klientach z wyjątkiem klienta, który wywołał metodę |
Hub.Clients Zawiera również następujące metody:
Metoda | opis |
---|---|
AllExcept | Wywołuje metodę na wszystkich połączonych klientach z wyjątkiem określonych połączeń |
Client | Wywołuje metodę na określonym połączonym kliencie |
Clients | Wywołuje metodę dla określonych połączonych klientów |
Group | Wywołuje metodę dla wszystkich połączeń w określonej grupie |
GroupExcept | Wywołuje metodę dla wszystkich połączeń w określonej grupie, z wyjątkiem określonych połączeń |
Groups | Wywołuje metodę w wielu grupach połączeń |
OthersInGroup | Wywołuje metodę w grupie połączeń, z wyłączeniem klienta, który wywołał metodę centrum |
User | Wywołuje metodę dla wszystkich połączeń skojarzonych z określonym użytkownikiem |
Users | Wywołuje metodę dla wszystkich połączeń skojarzonych z określonymi użytkownikami |
Każda właściwość lub metoda w poprzednich tabelach zwraca obiekt z SendAsync
metodą . Metoda SendAsync
otrzymuje nazwę metody klienta do wywołania i wszystkich parametrów.
Obiekt zwracany przez Client
metody i Caller
zawiera również metodę InvokeAsync
, która może służyć do oczekiwania na wynik od klienta.
Wysyłanie komunikatów do klientów
Aby wykonywać wywołania do określonych klientów, użyj właściwości Clients
obiektu. W poniższym przykładzie istnieją trzy metody koncentratora:
SendMessage
wysyła komunikat do wszystkich połączonych klientów przy użyciu poleceniaClients.All
.SendMessageToCaller
wysyła wiadomość z powrotem do wywołującego przy użyciu poleceniaClients.Caller
.SendMessageToGroup
wysyła komunikat do wszystkich klientów wSignalR Users
grupie.
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);
Silnie typizowane koncentratory
Wadą użycia SendAsync
jest to, że opiera się na ciągu, aby określić metodę klienta do wywołania. Spowoduje to pozostawienie kodu otwartego na błędy środowiska uruchomieniowego, jeśli nazwa metody jest błędnie wpisać lub brakuje jej w kliencie.
Alternatywą do użycia SendAsync
jest silnie typizowanej Hub klasy za pomocą Hub<T>polecenia . W poniższym przykładzie ChatHub
metoda klienta została wyodrębniona do interfejsu o nazwie IChatClient
:
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Ten interfejs może służyć do refaktoryzacji poprzedniego ChatHub
przykładu, aby był silnie typowany:
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);
}
Użycie Hub<IChatClient>
umożliwia sprawdzanie czasu kompilacji metod klienta. Zapobiega to problemom spowodowanym używaniem ciągów, ponieważ Hub<T>
może zapewnić dostęp tylko do metod zdefiniowanych w interfejsie. Użycie silnie typizowanego Hub<T>
elementu wyłącza możliwość używania elementu SendAsync
.
Uwaga
Sufiks Async
nie jest usuwany z nazw metod. Chyba że metoda klienta jest zdefiniowana za .on('MyMethodAsync')
pomocą metody , nie używaj MyMethodAsync
jej jako nazwy.
Wyniki klienta
Oprócz wykonywania wywołań do klientów serwer może zażądać wyniku od klienta. Wymaga to, aby serwer używał ISingleClientProxy.InvokeAsync
polecenia , a klient zwrócił wynik z programu .On
obsługi.
Istnieją dwa sposoby używania interfejsu API na serwerze, a pierwszą metodą jest wywołanie Client(...)
lub Caller
na Clients
właściwość w metodzie Hub:
public class ChatHub : Hub
{
public async Task<string> WaitForMessage(string connectionId)
{
var message = await Clients.Client(connectionId).InvokeAsync<string>(
"GetMessage");
return message;
}
}
Drugim sposobem jest wywołanie Client(...)
wystąpienia IHubContext<T>
klasy :
async Task SomeMethod(IHubContext<MyHub> context)
{
string result = await context.Clients.Client(connectionID).InvokeAsync<string>(
"GetMessage");
}
Silnie typizowane koncentratory mogą również zwracać wartości z metod interfejsu:
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;
}
}
Klienci zwracają wyniki w swoich .On(...)
programach obsługi, jak pokazano poniżej:
Klient .NET
hubConnection.On("GetMessage", async () =>
{
Console.WriteLine("Enter message:");
var message = await Console.In.ReadLineAsync();
return message;
});
Klient typescript
hubConnection.on("GetMessage", async () => {
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("message");
}, 100);
});
return promise;
});
Klienta środowiska Java
hubConnection.onWithResult("GetMessage", () -> {
return Single.just("message");
});
Zmienianie nazwy metody centrum
Domyślnie nazwa metody centrum serwera to nazwa metody .NET. Aby zmienić to domyślne zachowanie dla określonej metody, użyj atrybutu HubMethodName . Klient powinien użyć tej nazwy zamiast nazwy metody .NET podczas wywoływania metody:
[HubMethodName("SendMessageToUser")]
public async Task DirectMessage(string user, string message)
=> await Clients.User(user).SendAsync("ReceiveMessage", user, message);
Wstrzykiwanie usług do centrum
Konstruktory koncentratora mogą akceptować usługi z di jako parametry, które mogą być przechowywane we właściwościach klasy do użycia w metodzie piasty.
W przypadku wstrzykiwania wielu usług dla różnych metod centrum lub jako alternatywnego sposobu pisania kodu metody centrum mogą również akceptować usługi z di. Domyślnie parametry metody centrum są sprawdzane i rozpoznawane z di, jeśli to możliwe.
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);
}
}
Jeśli nie jest wymagane niejawne rozpoznawanie parametrów z usług, wyłącz je za pomocą polecenia DisableImplicitFromServicesParameters.
Aby jawnie określić, które parametry są rozpoznawane z di w metodach koncentratora, użyj opcji i użyj DisableImplicitFromServicesParameters
atrybutu [FromServices]
lub atrybutu niestandardowego, który implementuje IFromServiceMetadata
parametry metody centrum, które powinny zostać rozpoznane z 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);
}
}
Uwaga
Ta funkcja korzysta z IServiceProviderIsServiceelementu , który jest opcjonalnie implementowany przez implementacje di. Jeśli kontener DI aplikacji nie obsługuje tej funkcji, wstrzykiwanie usług do metod centrum nie jest obsługiwane.
Obsługa zdarzeń dla połączenia
Interfejs SignalR API usługi Hubs udostępnia OnConnectedAsync metody i OnDisconnectedAsync wirtualne do zarządzania połączeniami i śledzenia ich. Zastąpij metodę wirtualną OnConnectedAsync
, aby wykonywać akcje, gdy klient łączy się z centrum, na przykład dodając ją do grupy:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Zastąpij metodę wirtualną OnDisconnectedAsync
, aby wykonywać akcje po rozłączeniu klienta. Jeśli klient rozłącza się celowo, na przykład przez wywołanie connection.stop()
metody , exception
parametr jest ustawiony na null
wartość . Jeśli jednak klient rozłącza się z powodu błędu, takiego jak awaria sieci, exception
parametr zawiera wyjątek opisujący błąd:
public override async Task OnDisconnectedAsync(Exception? exception)
{
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync nie musi być wywoływana w elemecie OnDisconnectedAsync, jest automatycznie obsługiwana.
Obsługa błędów
Wyjątki zgłaszane w metodach centrum są wysyłane do klienta, który wywołał metodę. Na kliencie invoke
JavaScript metoda zwraca kod JavaScript Promise
. Klienci mogą dołączyć procedurę catch
obsługi do zwróconej obietnicy lub użyć polecenia try
/catch
w async
/await
celu obsługi wyjątków:
try {
await connection.invoke("SendMessage", user, message);
} catch (err) {
console.error(err);
}
Połączenia nie są zamykane, gdy centrum zgłasza wyjątek. Domyślnie SignalR zwraca ogólny komunikat o błędzie do klienta, jak pokazano w poniższym przykładzie:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'SendMessage' on the server.
Nieoczekiwane wyjątki często zawierają poufne informacje, takie jak nazwa serwera bazy danych w wyjątku wyzwalanym w przypadku niepowodzenia połączenia z bazą danych. SignalR domyślnie nie ujawnia tych szczegółowych komunikatów o błędach jako środka zabezpieczeń. Aby uzyskać więcej informacji o tym, dlaczego szczegóły wyjątku są pomijane, zobacz Zagadnienia dotyczące zabezpieczeń w programie ASP.NET Core SignalR.
Jeśli do klienta należy propagować wyjątkowy warunek, użyj HubException klasy . Jeśli element HubException
jest zgłaszany w metodzie centrum, SignalRwysyła cały komunikat o wyjątku do klienta, niezmodyfikowany:
public Task ThrowException()
=> throw new HubException("This error will be sent to the client!");
Uwaga
SignalR wysyła Message
tylko właściwość wyjątku do klienta. Ślad stosu i inne właściwości wyjątku nie są dostępne dla klienta.
Dodatkowe zasoby
Przez Rachel Appel i Kevin Griffin
Interfejs SignalR API usługi Hubs umożliwia połączonym klientom wywoływanie metod na serwerze, ułatwiając komunikację w czasie rzeczywistym. Serwer definiuje metody wywoływane przez klienta, a klient definiuje metody wywoływane przez serwer. SignalR Umożliwia również pośrednią komunikację między klientem a klientem, zawsze mediaowaną przez SignalR centrum, umożliwiając wysyłanie komunikatów między poszczególnymi klientami, grupami lub wszystkimi połączonymi klientami. SignalR dba o wszystko, co jest wymagane, aby umożliwić komunikację między klientem i klientem w czasie rzeczywistym.
Konfigurowanie SignalR koncentratorów
Aby zarejestrować usługi wymagane przez SignalR centra, wywołaj metodę AddSignalR w pliku Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddSignalR();
Aby skonfigurować SignalR punkty końcowe, wywołaj metodę MapHub, również w pliku Program.cs
:
app.MapRazorPages();
app.MapHub<ChatHub>("/Chat");
app.Run();
Uwaga
zestawy ASP.NET Core SignalR po stronie serwera są teraz instalowane przy użyciu zestawu .NET Core SDK. Aby uzyskać więcej informacji, zobacz SignalR zestawy w strukturze udostępnionej .
Tworzenie centrów i korzystanie z nich
Utwórz centrum, deklarując klasę dziedziczącą z Hubklasy . Dodaj public
metody do klasy, aby umożliwić ich wywoływanie z klientów:
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
=> await Clients.All.SendAsync("ReceiveMessage", user, message);
}
Uwaga
Koncentratory są przejściowe:
- Nie przechowuj stanu we właściwości klasy centrum. Każde wywołanie metody centrum jest wykonywane w nowym wystąpieniu centrum.
- Nie tworzy wystąpienia koncentratora bezpośrednio za pośrednictwem wstrzykiwania zależności. Aby wysyłać komunikaty do klienta z innego miejsca w aplikacji, użyj polecenia
IHubContext
. - Użyj
await
funkcji podczas wywoływania metod asynchronicznych, które zależą od centrum pozostającego przy życiu. Na przykład metoda taka jakClients.All.SendAsync(...)
może zakończyć się niepowodzeniem, jeśli zostanie wywołana bezawait
, a metoda centrum zostanie ukończona przed zakończeniemSendAsync
.
Obiekt Context
Klasa Hub zawiera właściwość zawierającą Context następujące właściwości z informacjami o połączeniu:
Właściwości | opis |
---|---|
ConnectionId | Pobiera unikatowy identyfikator połączenia przypisanego przez SignalR. Dla każdego połączenia istnieje jeden identyfikator połączenia. |
UserIdentifier | Pobiera identyfikator użytkownika. Domyślnie SignalR używa ClaimTypes.NameIdentifier elementu z skojarzonego ClaimsPrincipal z połączeniem jako identyfikatora użytkownika. |
User | ClaimsPrincipal Pobiera element skojarzony z bieżącym użytkownikiem. |
Items | Pobiera kolekcję klucz/wartość, która może służyć do udostępniania danych w zakresie tego połączenia. Dane mogą być przechowywane w tej kolekcji i będą utrwalane dla połączenia między różnymi wywołaniami metod centrum. |
Features | Pobiera kolekcję funkcji dostępnych w połączeniu. Na razie ta kolekcja nie jest potrzebna w większości scenariuszy, więc nie została jeszcze szczegółowo udokumentowana. |
ConnectionAborted | Pobiera element CancellationToken , który powiadamia o przerwaniu połączenia. |
Hub.Context Zawiera również następujące metody:
Metoda | opis |
---|---|
GetHttpContext | HttpContext Zwraca wartość dla połączenia lub null jeśli połączenie nie jest skojarzone z żądaniem HTTP. W przypadku połączeń HTTP użyj tej metody, aby uzyskać informacje, takie jak nagłówki HTTP i ciągi zapytania. |
Abort | Przerywa połączenie. |
Obiekt Klienci
Klasa Hub zawiera właściwość zawierającą Clients następujące właściwości komunikacji między serwerem a klientem:
Właściwości | opis |
---|---|
All | Wywołuje metodę na wszystkich połączonych klientach |
Caller | Wywołuje metodę na kliencie, który wywołał metodę centrum |
Others | Wywołuje metodę na wszystkich połączonych klientach z wyjątkiem klienta, który wywołał metodę |
Hub.Clients Zawiera również następujące metody:
Metoda | opis |
---|---|
AllExcept | Wywołuje metodę na wszystkich połączonych klientach z wyjątkiem określonych połączeń |
Client | Wywołuje metodę na określonym połączonym kliencie |
Clients | Wywołuje metodę dla określonych połączonych klientów |
Group | Wywołuje metodę dla wszystkich połączeń w określonej grupie |
GroupExcept | Wywołuje metodę dla wszystkich połączeń w określonej grupie, z wyjątkiem określonych połączeń |
Groups | Wywołuje metodę w wielu grupach połączeń |
OthersInGroup | Wywołuje metodę w grupie połączeń, z wyłączeniem klienta, który wywołał metodę centrum |
User | Wywołuje metodę dla wszystkich połączeń skojarzonych z określonym użytkownikiem |
Users | Wywołuje metodę dla wszystkich połączeń skojarzonych z określonymi użytkownikami |
Każda właściwość lub metoda w poprzednich tabelach zwraca obiekt z SendAsync
metodą . Metoda SendAsync
otrzymuje nazwę metody klienta do wywołania i wszystkich parametrów.
Wysyłanie komunikatów do klientów
Aby wykonywać wywołania do określonych klientów, użyj właściwości Clients
obiektu. W poniższym przykładzie istnieją trzy metody koncentratora:
SendMessage
wysyła komunikat do wszystkich połączonych klientów przy użyciu poleceniaClients.All
.SendMessageToCaller
wysyła wiadomość z powrotem do wywołującego przy użyciu poleceniaClients.Caller
.SendMessageToGroup
wysyła komunikat do wszystkich klientów wSignalR Users
grupie.
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);
Silnie typizowane koncentratory
Wadą użycia SendAsync
jest to, że opiera się na ciągu, aby określić metodę klienta do wywołania. Spowoduje to pozostawienie kodu otwartego na błędy środowiska uruchomieniowego, jeśli nazwa metody jest błędnie wpisać lub brakuje jej w kliencie.
Alternatywą do użycia SendAsync
jest silnie typizowanej Hub klasy za pomocą Hub<T>polecenia . W poniższym przykładzie ChatHub
metoda klienta została wyodrębniona do interfejsu o nazwie IChatClient
:
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Ten interfejs może służyć do refaktoryzacji poprzedniego ChatHub
przykładu, aby był silnie typowany:
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);
}
Użycie Hub<IChatClient>
umożliwia sprawdzanie czasu kompilacji metod klienta. Zapobiega to problemom spowodowanym używaniem ciągów, ponieważ Hub<T>
może zapewnić dostęp tylko do metod zdefiniowanych w interfejsie. Użycie silnie typizowanego Hub<T>
elementu wyłącza możliwość używania elementu SendAsync
.
Uwaga
Sufiks Async
nie jest usuwany z nazw metod. Chyba że metoda klienta jest zdefiniowana za .on('MyMethodAsync')
pomocą metody , nie używaj MyMethodAsync
jej jako nazwy.
Zmienianie nazwy metody centrum
Domyślnie nazwa metody centrum serwera to nazwa metody .NET. Aby zmienić to domyślne zachowanie dla określonej metody, użyj atrybutu HubMethodName . Klient powinien użyć tej nazwy zamiast nazwy metody .NET podczas wywoływania metody:
[HubMethodName("SendMessageToUser")]
public async Task DirectMessage(string user, string message)
=> await Clients.User(user).SendAsync("ReceiveMessage", user, message);
Obsługa zdarzeń dla połączenia
Interfejs SignalR API usługi Hubs udostępnia OnConnectedAsync metody i OnDisconnectedAsync wirtualne do zarządzania połączeniami i śledzenia ich. Zastąpij metodę wirtualną OnConnectedAsync
, aby wykonywać akcje, gdy klient łączy się z centrum, na przykład dodając ją do grupy:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Zastąpij metodę wirtualną OnDisconnectedAsync
, aby wykonywać akcje po rozłączeniu klienta. Jeśli klient rozłącza się celowo, na przykład przez wywołanie connection.stop()
metody , exception
parametr jest ustawiony na null
wartość . Jeśli jednak klient rozłącza się z powodu błędu, takiego jak awaria sieci, exception
parametr zawiera wyjątek opisujący błąd:
public override async Task OnDisconnectedAsync(Exception? exception)
{
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync nie musi być wywoływana w elemecie OnDisconnectedAsync, jest automatycznie obsługiwana.
Obsługa błędów
Wyjątki zgłaszane w metodach centrum są wysyłane do klienta, który wywołał metodę. Na kliencie invoke
JavaScript metoda zwraca kod JavaScript Promise
. Klienci mogą dołączyć procedurę catch
obsługi do zwróconej obietnicy lub użyć polecenia try
/catch
w async
/await
celu obsługi wyjątków:
try {
await connection.invoke("SendMessage", user, message);
} catch (err) {
console.error(err);
}
Połączenia nie są zamykane, gdy centrum zgłasza wyjątek. Domyślnie SignalR zwraca ogólny komunikat o błędzie do klienta, jak pokazano w poniższym przykładzie:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'SendMessage' on the server.
Nieoczekiwane wyjątki często zawierają poufne informacje, takie jak nazwa serwera bazy danych w wyjątku wyzwalanym w przypadku niepowodzenia połączenia z bazą danych. SignalR domyślnie nie ujawnia tych szczegółowych komunikatów o błędach jako środka zabezpieczeń. Aby uzyskać więcej informacji o tym, dlaczego szczegóły wyjątku są pomijane, zobacz Zagadnienia dotyczące zabezpieczeń w programie ASP.NET Core SignalR.
Jeśli do klienta należy propagować wyjątkowy warunek, użyj HubException klasy . Jeśli element HubException
jest zgłaszany w metodzie centrum, SignalRwysyła cały komunikat o wyjątku do klienta, niezmodyfikowany:
public Task ThrowException()
=> throw new HubException("This error will be sent to the client!");
Uwaga
SignalR wysyła Message
tylko właściwość wyjątku do klienta. Ślad stosu i inne właściwości wyjątku nie są dostępne dla klienta.
Dodatkowe zasoby
Przez Rachel Appel i Kevin Griffin
Wyświetl lub pobierz przykładowy kod (jak pobrać)
Co to jest SignalR koncentrator
Interfejs SignalR API usługi Hubs umożliwia połączonym klientom wywoływanie metod na serwerze, ułatwiając komunikację w czasie rzeczywistym. Serwer definiuje metody wywoływane przez klienta, a klient definiuje metody wywoływane przez serwer. SignalR Umożliwia również pośrednią komunikację między klientem a klientem, zawsze mediaowaną przez SignalR centrum, umożliwiając wysyłanie komunikatów między poszczególnymi klientami, grupami lub wszystkimi połączonymi klientami. SignalR dba o wszystko, co jest wymagane, aby umożliwić komunikację między klientem i klientem w czasie rzeczywistym.
Konfigurowanie SignalR koncentratorów
Oprogramowanie SignalR pośredniczące wymaga niektórych usług, które są konfigurowane przez wywołanie metody AddSignalR:
services.AddSignalR();
Podczas dodawania SignalR funkcji do aplikacji ASP.NET Core skonfiguruj SignalR trasy przez wywołanie MapHub Startup.Configure
zwrotne metody UseEndpoints :
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>("/chathub");
});
Uwaga
zestawy ASP.NET Core SignalR po stronie serwera są teraz instalowane przy użyciu zestawu .NET Core SDK. Aby uzyskać więcej informacji, zobacz SignalR zestawy w strukturze udostępnionej .
Tworzenie centrów i korzystanie z nich
Utwórz centrum, deklarując klasę dziedziczącą z Hubklasy i dodając do niej metody publiczne. Klienci mogą wywoływać metody zdefiniowane jako public
:
public class ChatHub : Hub
{
public Task SendMessage(string user, string message)
{
return Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
Można określić typ i parametry zwracane, w tym typy złożone i tablice, tak jak w dowolnej metodzie języka C#. SignalR obsługuje serializacji i deserializacji złożonych obiektów i tablic w parametrach i zwracanych wartościach.
Uwaga
Koncentratory są przejściowe:
- Nie przechowuj stanu we właściwości w klasie centrum. Każde wywołanie metody centrum jest wykonywane w nowym wystąpieniu centrum.
- Nie tworzy wystąpienia koncentratora bezpośrednio za pośrednictwem wstrzykiwania zależności. Aby wysyłać komunikaty do klienta z innego miejsca w aplikacji, użyj polecenia
IHubContext
. - Użyj
await
funkcji podczas wywoływania metod asynchronicznych, które zależą od centrum pozostającego przy życiu. Na przykład metoda taka jakClients.All.SendAsync(...)
może zakończyć się niepowodzeniem, jeśli zostanie wywołana bezawait
, a metoda centrum zostanie ukończona przed zakończeniemSendAsync
.
Obiekt Context
Klasa Hub ma właściwość zawierającą Context następujące właściwości z informacjami o połączeniu:
Właściwości | opis |
---|---|
ConnectionId | Pobiera unikatowy identyfikator połączenia przypisanego przez SignalR. Dla każdego połączenia istnieje jeden identyfikator połączenia. |
UserIdentifier | Pobiera identyfikator użytkownika. Domyślnie SignalR używa ClaimTypes.NameIdentifier elementu z skojarzonego ClaimsPrincipal z połączeniem jako identyfikatora użytkownika. |
User | ClaimsPrincipal Pobiera element skojarzony z bieżącym użytkownikiem. |
Items | Pobiera kolekcję klucz/wartość, która może służyć do udostępniania danych w zakresie tego połączenia. Dane mogą być przechowywane w tej kolekcji i będą utrwalane dla połączenia między różnymi wywołaniami metod centrum. |
Features | Pobiera kolekcję funkcji dostępnych w połączeniu. Na razie ta kolekcja nie jest potrzebna w większości scenariuszy, więc nie została jeszcze szczegółowo udokumentowana. |
ConnectionAborted | Pobiera element CancellationToken , który powiadamia o przerwaniu połączenia. |
Hub.Context Zawiera również następujące metody:
Metoda | opis |
---|---|
GetHttpContext | HttpContext Zwraca wartość dla połączenia lub null jeśli połączenie nie jest skojarzone z żądaniem HTTP. W przypadku połączeń HTTP można użyć tej metody, aby uzyskać informacje, takie jak nagłówki HTTP i ciągi zapytania. |
Abort | Przerywa połączenie. |
Obiekt Klienci
Klasa Hub ma właściwość zawierającą Clients następujące właściwości komunikacji między serwerem a klientem:
Właściwości | opis |
---|---|
All | Wywołuje metodę na wszystkich połączonych klientach |
Caller | Wywołuje metodę na kliencie, który wywołał metodę centrum |
Others | Wywołuje metodę na wszystkich połączonych klientach z wyjątkiem klienta, który wywołał metodę |
Hub.Clients Zawiera również następujące metody:
Metoda | opis |
---|---|
AllExcept | Wywołuje metodę na wszystkich połączonych klientach z wyjątkiem określonych połączeń |
Client | Wywołuje metodę na określonym połączonym kliencie |
Clients | Wywołuje metodę dla określonych połączonych klientów |
Group | Wywołuje metodę dla wszystkich połączeń w określonej grupie |
GroupExcept | Wywołuje metodę dla wszystkich połączeń w określonej grupie, z wyjątkiem określonych połączeń |
Groups | Wywołuje metodę w wielu grupach połączeń |
OthersInGroup | Wywołuje metodę w grupie połączeń, z wyłączeniem klienta, który wywołał metodę centrum |
User | Wywołuje metodę dla wszystkich połączeń skojarzonych z określonym użytkownikiem |
Users | Wywołuje metodę dla wszystkich połączeń skojarzonych z określonymi użytkownikami |
Każda właściwość lub metoda w poprzednich tabelach zwraca obiekt z SendAsync
metodą . Metoda SendAsync
umożliwia podanie nazwy i parametrów metody klienta do wywołania.
Wysyłanie komunikatów do klientów
Aby wykonywać wywołania do określonych klientów, użyj właściwości Clients
obiektu. W poniższym przykładzie istnieją trzy metody koncentratora:
SendMessage
wysyła komunikat do wszystkich połączonych klientów przy użyciu poleceniaClients.All
.SendMessageToCaller
wysyła wiadomość z powrotem do wywołującego przy użyciu poleceniaClients.Caller
.SendMessageToGroup
wysyła komunikat do wszystkich klientów wSignalR Users
grupie.
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);
}
Silnie typizowane koncentratory
Wadą użycia SendAsync
jest to, że opiera się na ciągu magicznym, aby określić metodę klienta do wywołania. Spowoduje to pozostawienie kodu otwartego na błędy środowiska uruchomieniowego, jeśli nazwa metody jest błędnie wpisać lub brakuje jej w kliencie.
Alternatywą do użycia SendAsync
jest silnie typizowane za Hub pomocą Hub<T>polecenia . W poniższym przykładzie ChatHub
metody klienta zostały wyodrębnione do interfejsu o nazwie IChatClient
.
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Ten interfejs może służyć do refaktoryzacji poprzedniego ChatHub
przykładu:
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);
}
}
Użycie Hub<IChatClient>
umożliwia sprawdzanie czasu kompilacji metod klienta. Zapobiega to problemom spowodowanym używaniem ciągów magicznych, ponieważ Hub<T>
może zapewnić dostęp tylko do metod zdefiniowanych w interfejsie.
Użycie silnie typizowanego Hub<T>
elementu wyłącza możliwość używania elementu SendAsync
. Wszystkie metody zdefiniowane w interfejsie mogą być nadal definiowane jako asynchroniczne. W rzeczywistości każda z tych metod powinna zwrócić wartość Task
. Ponieważ jest to interfejs, nie używaj słowa kluczowego async
. Na przykład:
public interface IClient
{
Task ClientMethod();
}
Uwaga
Sufiks Async
nie jest usuwany z nazwy metody. Jeśli metoda klienta nie jest zdefiniowana za pomocą .on('MyMethodAsync')
metody , nie należy używać MyMethodAsync
jej jako nazwy.
Zmienianie nazwy metody centrum
Domyślnie nazwa metody centrum serwera to nazwa metody .NET. Można jednak użyć atrybutu HubMethodName , aby zmienić to ustawienie domyślne i ręcznie określić nazwę metody. Klient powinien użyć tej nazwy zamiast nazwy metody .NET podczas wywoływania metody:
[HubMethodName("SendMessageToUser")]
public Task DirectMessage(string user, string message)
{
return Clients.User(user).SendAsync("ReceiveMessage", user, message);
}
Obsługa zdarzeń dla połączenia
Interfejs SignalR API usługi Hubs udostępnia OnConnectedAsync metody i OnDisconnectedAsync wirtualne do zarządzania połączeniami i śledzenia ich. Zastąpij metodę wirtualną OnConnectedAsync
, aby wykonywać akcje, gdy klient łączy się z centrum, na przykład dodając ją do grupy:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Zastąpij metodę wirtualną OnDisconnectedAsync
, aby wykonywać akcje po rozłączeniu klienta. Jeśli klient rozłącza się celowo (wywołując connection.stop()
na przykład exception
, parametr będzie mieć null
wartość . Jeśli jednak klient zostanie rozłączony z powodu błędu (takiego jak awaria sieci), exception
parametr będzie zawierać wyjątek opisujący błąd:
public override async Task OnDisconnectedAsync(Exception exception)
{
await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", "I", "disconnect");
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync nie musi być wywoływana w elemecie OnDisconnectedAsync, jest automatycznie obsługiwana.
Ostrzeżenie
Ostrzeżenie o zabezpieczeniach: Ujawnienie ConnectionId
może prowadzić do podszywania się pod złośliwy, jeśli SignalR serwer lub wersja klienta jest ASP.NET Core 2.2 lub starsze.
Obsługa błędów
Wyjątki zgłaszane w metodach centrum są wysyłane do klienta, który wywołał metodę. Na kliencie invoke
JavaScript metoda zwraca kod JavaScript Promise
. Gdy klient otrzymuje błąd z procedurą obsługi dołączoną do obietnicy przy użyciu metody catch
, jest wywoływany i przekazywany jako obiekt JavaScript Error
:
connection.invoke("SendMessage", user, message).catch(err => console.error(err));
Jeśli centrum zgłasza wyjątek, połączenia nie są zamykane. Domyślnie SignalR zwraca ogólny komunikat o błędzie do klienta. Na przykład:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'MethodName' on the server.
Nieoczekiwane wyjątki często zawierają poufne informacje, takie jak nazwa serwera bazy danych w wyjątku wyzwalanym w przypadku niepowodzenia połączenia z bazą danych. SignalR domyślnie nie ujawnia tych szczegółowych komunikatów o błędach jako środka zabezpieczeń. Aby uzyskać więcej informacji o tym, dlaczego szczegóły wyjątku są pomijane, zobacz Zagadnienia dotyczące zabezpieczeń w programie ASP.NET Core SignalR.
Jeśli masz wyjątkowy warunek, który chcesz propagować do klienta, możesz użyć HubException klasy . W przypadku zgłoszenia HubException
z metody SignalRcentrum cały komunikat zostanie wysłany do klienta, niezmodyfikowany:
public Task ThrowException()
{
throw new HubException("This error will be sent to the client!");
}
Uwaga
SignalR wysyła Message
tylko właściwość wyjątku do klienta. Ślad stosu i inne właściwości wyjątku nie są dostępne dla klienta.
Dodatkowe zasoby
Przez Rachel Appel i Kevin Griffin
Wyświetl lub pobierz przykładowy kod (jak pobrać)
Co to jest SignalR koncentrator
Interfejs SignalR API usługi Hubs umożliwia połączonym klientom wywoływanie metod na serwerze, ułatwiając komunikację w czasie rzeczywistym. Serwer definiuje metody wywoływane przez klienta, a klient definiuje metody wywoływane przez serwer. SignalR Umożliwia również pośrednią komunikację między klientem a klientem, zawsze mediaowaną przez SignalR centrum, umożliwiając wysyłanie komunikatów między poszczególnymi klientami, grupami lub wszystkimi połączonymi klientami. SignalR dba o wszystko, co jest wymagane, aby umożliwić komunikację między klientem i klientem w czasie rzeczywistym.
Konfigurowanie SignalR koncentratorów
Oprogramowanie SignalR pośredniczące wymaga niektórych usług, które są konfigurowane przez wywołanie metody AddSignalR:
services.AddSignalR();
Podczas dodawania SignalR funkcji do aplikacji ASP.NET Core skonfiguruj SignalR trasy przez wywołanie UseSignalR metody :Startup.Configure
app.UseSignalR(route =>
{
route.MapHub<ChatHub>("/chathub");
});
Tworzenie centrów i korzystanie z nich
Utwórz centrum, deklarując klasę dziedziczącą z Hubklasy i dodając do niej metody publiczne. Klienci mogą wywoływać metody zdefiniowane jako public
:
public class ChatHub : Hub
{
public Task SendMessage(string user, string message)
{
return Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
Można określić typ i parametry zwracane, w tym typy złożone i tablice, tak jak w dowolnej metodzie języka C#. SignalR obsługuje serializacji i deserializacji złożonych obiektów i tablic w parametrach i zwracanych wartościach.
Uwaga
Koncentratory są przejściowe:
- Nie przechowuj stanu we właściwości w klasie centrum. Każde wywołanie metody centrum jest wykonywane w nowym wystąpieniu centrum.
- Nie tworzy wystąpienia koncentratora bezpośrednio za pośrednictwem wstrzykiwania zależności. Aby wysyłać komunikaty do klienta z innego miejsca w aplikacji, użyj polecenia
IHubContext
. - Użyj
await
funkcji podczas wywoływania metod asynchronicznych, które zależą od centrum pozostającego przy życiu. Na przykład metoda taka jakClients.All.SendAsync(...)
może zakończyć się niepowodzeniem, jeśli zostanie wywołana bezawait
, a metoda centrum zostanie ukończona przed zakończeniemSendAsync
.
Obiekt Context
Klasa Hub ma właściwość zawierającą Context następujące właściwości z informacjami o połączeniu:
Właściwości | opis |
---|---|
ConnectionId | Pobiera unikatowy identyfikator połączenia przypisanego przez SignalR. Dla każdego połączenia istnieje jeden identyfikator połączenia. |
UserIdentifier | Pobiera identyfikator użytkownika. Domyślnie SignalR używa ClaimTypes.NameIdentifier elementu z skojarzonego ClaimsPrincipal z połączeniem jako identyfikatora użytkownika. |
User | ClaimsPrincipal Pobiera element skojarzony z bieżącym użytkownikiem. |
Items | Pobiera kolekcję klucz/wartość, która może służyć do udostępniania danych w zakresie tego połączenia. Dane mogą być przechowywane w tej kolekcji i będą utrwalane dla połączenia między różnymi wywołaniami metod centrum. |
Features | Pobiera kolekcję funkcji dostępnych w połączeniu. Na razie ta kolekcja nie jest potrzebna w większości scenariuszy, więc nie została jeszcze szczegółowo udokumentowana. |
ConnectionAborted | Pobiera element CancellationToken , który powiadamia o przerwaniu połączenia. |
Hub.Context Zawiera również następujące metody:
Metoda | opis |
---|---|
GetHttpContext | HttpContext Zwraca wartość dla połączenia lub null jeśli połączenie nie jest skojarzone z żądaniem HTTP. W przypadku połączeń HTTP można użyć tej metody, aby uzyskać informacje, takie jak nagłówki HTTP i ciągi zapytania. |
Abort | Przerywa połączenie. |
Obiekt Klienci
Klasa Hub ma właściwość zawierającą Clients następujące właściwości komunikacji między serwerem a klientem:
Właściwości | opis |
---|---|
All | Wywołuje metodę na wszystkich połączonych klientach |
Caller | Wywołuje metodę na kliencie, który wywołał metodę centrum |
Others | Wywołuje metodę na wszystkich połączonych klientach z wyjątkiem klienta, który wywołał metodę |
Hub.Clients Zawiera również następujące metody:
Metoda | opis |
---|---|
AllExcept | Wywołuje metodę na wszystkich połączonych klientach z wyjątkiem określonych połączeń |
Client | Wywołuje metodę na określonym połączonym kliencie |
Clients | Wywołuje metodę dla określonych połączonych klientów |
Group | Wywołuje metodę dla wszystkich połączeń w określonej grupie |
GroupExcept | Wywołuje metodę dla wszystkich połączeń w określonej grupie, z wyjątkiem określonych połączeń |
Groups | Wywołuje metodę w wielu grupach połączeń |
OthersInGroup | Wywołuje metodę w grupie połączeń, z wyłączeniem klienta, który wywołał metodę centrum |
User | Wywołuje metodę dla wszystkich połączeń skojarzonych z określonym użytkownikiem |
Users | Wywołuje metodę dla wszystkich połączeń skojarzonych z określonymi użytkownikami |
Każda właściwość lub metoda w poprzednich tabelach zwraca obiekt z SendAsync
metodą . Metoda SendAsync
umożliwia podanie nazwy i parametrów metody klienta do wywołania.
Wysyłanie komunikatów do klientów
Aby wykonywać wywołania do określonych klientów, użyj właściwości Clients
obiektu. W poniższym przykładzie istnieją trzy metody koncentratora:
SendMessage
wysyła komunikat do wszystkich połączonych klientów przy użyciu poleceniaClients.All
.SendMessageToCaller
wysyła wiadomość z powrotem do wywołującego przy użyciu poleceniaClients.Caller
.SendMessageToGroup
wysyła komunikat do wszystkich klientów wSignalR Users
grupie.
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);
}
Silnie typizowane koncentratory
Wadą użycia SendAsync
jest to, że opiera się na ciągu magicznym, aby określić metodę klienta do wywołania. Spowoduje to pozostawienie kodu otwartego na błędy środowiska uruchomieniowego, jeśli nazwa metody jest błędnie wpisać lub brakuje jej w kliencie.
Alternatywą do użycia SendAsync
jest silnie typizowane za Hub pomocą Hub<T>polecenia . W poniższym przykładzie ChatHub
metody klienta zostały wyodrębnione do interfejsu o nazwie IChatClient
.
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Ten interfejs może służyć do refaktoryzacji poprzedniego ChatHub
przykładu:
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);
}
}
Użycie Hub<IChatClient>
umożliwia sprawdzanie czasu kompilacji metod klienta. Zapobiega to problemom spowodowanym używaniem ciągów magicznych, ponieważ Hub<T>
może zapewnić dostęp tylko do metod zdefiniowanych w interfejsie.
Użycie silnie typizowanego Hub<T>
elementu wyłącza możliwość używania elementu SendAsync
. Wszystkie metody zdefiniowane w interfejsie mogą być nadal definiowane jako asynchroniczne. W rzeczywistości każda z tych metod powinna zwrócić wartość Task
. Ponieważ jest to interfejs, nie używaj słowa kluczowego async
. Na przykład:
public interface IClient
{
Task ClientMethod();
}
Uwaga
Sufiks Async
nie jest usuwany z nazwy metody. Jeśli metoda klienta nie jest zdefiniowana za pomocą .on('MyMethodAsync')
metody , nie należy używać MyMethodAsync
jej jako nazwy.
Zmienianie nazwy metody centrum
Domyślnie nazwa metody centrum serwera to nazwa metody .NET. Można jednak użyć atrybutu HubMethodName , aby zmienić to ustawienie domyślne i ręcznie określić nazwę metody. Klient powinien użyć tej nazwy zamiast nazwy metody .NET podczas wywoływania metody:
[HubMethodName("SendMessageToUser")]
public Task DirectMessage(string user, string message)
{
return Clients.User(user).SendAsync("ReceiveMessage", user, message);
}
Obsługa zdarzeń dla połączenia
Interfejs SignalR API usługi Hubs udostępnia OnConnectedAsync metody i OnDisconnectedAsync wirtualne do zarządzania połączeniami i śledzenia ich. Zastąpij metodę wirtualną OnConnectedAsync
, aby wykonywać akcje, gdy klient łączy się z centrum, na przykład dodając ją do grupy:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Zastąpij metodę wirtualną OnDisconnectedAsync
, aby wykonywać akcje po rozłączeniu klienta. Jeśli klient rozłącza się celowo (wywołując connection.stop()
na przykład exception
, parametr będzie mieć null
wartość . Jeśli jednak klient zostanie rozłączony z powodu błędu (takiego jak awaria sieci), exception
parametr będzie zawierać wyjątek opisujący błąd:
public override async Task OnDisconnectedAsync(Exception exception)
{
await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", "I", "disconnect");
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync nie musi być wywoływana w elemecie OnDisconnectedAsync, jest automatycznie obsługiwana.
Ostrzeżenie
Ostrzeżenie o zabezpieczeniach: Ujawnienie ConnectionId
może prowadzić do podszywania się pod złośliwy, jeśli SignalR serwer lub wersja klienta jest ASP.NET Core 2.2 lub starsze.
Obsługa błędów
Wyjątki zgłaszane w metodach centrum są wysyłane do klienta, który wywołał metodę. Na kliencie invoke
JavaScript metoda zwraca kod JavaScript Promise
. Gdy klient otrzymuje błąd z procedurą obsługi dołączoną do obietnicy przy użyciu metody catch
, jest wywoływany i przekazywany jako obiekt JavaScript Error
:
connection.invoke("SendMessage", user, message).catch(err => console.error(err));
Jeśli centrum zgłasza wyjątek, połączenia nie są zamykane. Domyślnie SignalR zwraca ogólny komunikat o błędzie do klienta. Na przykład:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'MethodName' on the server.
Nieoczekiwane wyjątki często zawierają poufne informacje, takie jak nazwa serwera bazy danych w wyjątku wyzwalanym w przypadku niepowodzenia połączenia z bazą danych. SignalR domyślnie nie ujawnia tych szczegółowych komunikatów o błędach jako środka zabezpieczeń. Aby uzyskać więcej informacji o tym, dlaczego szczegóły wyjątku są pomijane, zobacz Zagadnienia dotyczące zabezpieczeń w programie ASP.NET Core SignalR.
Jeśli masz wyjątkowy warunek, który chcesz propagować do klienta, możesz użyć HubException klasy . W przypadku zgłoszenia HubException
z metody SignalRcentrum cały komunikat zostanie wysłany do klienta, niezmodyfikowany:
public Task ThrowException()
{
throw new HubException("This error will be sent to the client!");
}
Uwaga
SignalR wysyła Message
tylko właściwość wyjątku do klienta. Ślad stosu i inne właściwości wyjątku nie są dostępne dla klienta.