Použití center SignalR pro ASP.NET Core
Od Rachel Appel a Kevin Griffin
Rozhraní SignalR API služby Hubs umožňuje připojeným klientům volat metody na serveru, což usnadňuje komunikaci v reálném čase. Server definuje metody, které volá klient, a klient definuje metody, které jsou volány serverem. SignalR umožňuje také nepřímou komunikaci mezi klienty a klienty, vždy zprostředkovanou centrem SignalR , což umožňuje odesílání zpráv mezi jednotlivými klienty, skupinami nebo všemi připojenými klienty. SignalR postará se o všechno potřebné k tomu, aby bylo možné komunikaci mezi klientem a klientem v reálném čase.
Konfigurace SignalR center
Pokud chcete zaregistrovat služby vyžadované SignalR rozbočovači, zavolejte AddSignalR do Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddSignalR();
Ke konfiguraci SignalR koncových bodů zavolejte MapHubtaké v Program.cs
:
app.MapRazorPages();
app.MapHub<ChatHub>("/Chat");
app.Run();
Poznámka:
ASP.NET sestavení na straně serveru se SignalR teď instalují se sadou .NET Core SDK. Další informace najdete SignalR v sestaveních ve sdíleném rozhraní .
Vytváření a používání center
Vytvoření centra deklarováním třídy, která dědí z Hub. Přidejte public
do třídy metody, které je volat z klientů:
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
=> await Clients.All.SendAsync("ReceiveMessage", user, message);
}
Poznámka:
Rozbočovače jsou přechodné:
- Neukládejte stav ve vlastnosti třídy centra. Každé volání metody centra se provádí v nové instanci centra.
- Vytvořte instanci centra přímo prostřednictvím injektáže závislostí. K odesílání zpráv klientovi z jiného prostředí aplikace použijte příkaz
IHubContext
. - Používá se
await
při volání asynchronních metod, které závisí na udržování centra. Například metodaClients.All.SendAsync(...)
může selhat, pokud je volána bezawait
a metoda centra se dokončí předSendAsync
dokončením.
Kontextový objekt
Třída Hub obsahuje Context vlastnost, která obsahuje následující vlastnosti s informacemi o připojení:
Vlastnost | Popis |
---|---|
ConnectionId | Získá jedinečné ID pro připojení přiřazeno SignalR. Pro každé připojení existuje jedno ID připojení. |
UserIdentifier | Získá identifikátor uživatele. Ve výchozím nastavení SignalR se jako identifikátor uživatele používá ClaimTypes.NameIdentifier z ClaimsPrincipal přidruženého připojení. |
User | ClaimsPrincipal Získá přidružené k aktuálnímu uživateli. |
Items | Získá kolekci klíč/hodnota, která se dá použít ke sdílení dat v rámci tohoto připojení. Data mohou být uložena v této kolekci a budou zachována pro připojení napříč různými vyvoláním metod centra. |
Features | Získá kolekci funkcí dostupných v připojení. Prozatím tato kolekce není ve většině scénářů potřebná, takže zatím není podrobně zdokumentovaná. |
ConnectionAborted | CancellationToken Získá upozornění, když je připojení přerušeno. |
Hub.Context obsahuje také následující metody:
metoda | Popis |
---|---|
GetHttpContext | HttpContext Vrátí pro připojení nebo null pokud připojení není přidružené k požadavku HTTP. Pro připojení HTTP použijte tuto metodu k získání informací, jako jsou hlavičky HTTP a řetězce dotazů. |
Abort | Přeruší připojení. |
Objekt Klienti
Třída Hub obsahuje Clients vlastnost, která obsahuje následující vlastnosti pro komunikaci mezi serverem a klientem:
Vlastnost | Popis |
---|---|
All | Volá metodu pro všechny připojené klienty. |
Caller | Volá metodu na klientovi, který vyvolal metodu centra. |
Others | Volá metodu pro všechny připojené klienty s výjimkou klienta, který vyvolal metodu. |
Hub.Clients obsahuje také následující metody:
metoda | Popis |
---|---|
AllExcept | Volá metodu pro všechny připojené klienty s výjimkou zadaných připojení. |
Client | Zavolá metodu pro konkrétního připojeného klienta. |
Clients | Volání metody pro konkrétní připojené klienty |
Group | Volá metodu pro všechna připojení v zadané skupině. |
GroupExcept | Volá metodu pro všechna připojení v zadané skupině s výjimkou zadaných připojení. |
Groups | Volá metodu pro více skupin připojení. |
OthersInGroup | Volá metodu ve skupině připojení s výjimkou klienta, který vyvolal metodu centra. |
User | Volá metodu pro všechna připojení přidružená ke konkrétnímu uživateli. |
Users | Volá metodu pro všechna připojení přidružená k zadaným uživatelům. |
Každá vlastnost nebo metoda v předchozích tabulkách vrací objekt s metodou SendAsync
. Metoda SendAsync
obdrží název klientské metody pro volání a všechny parametry.
Objekt vrácený Client
metodami a Caller
metody také obsahují metodu InvokeAsync
, kterou lze použít k čekání na výsledek z klienta.
Odesílání zpráv klientům
Pokud chcete volat konkrétní klienty, použijte vlastnosti objektu Clients
. V následujícím příkladu existují tři metody centra:
SendMessage
odešle zprávu všem připojeným klientům pomocí .Clients.All
SendMessageToCaller
odešle zprávu zpět volajícímu pomocí funkceClients.Caller
.SendMessageToGroup
odešle zprávu všem klientům ve skupiněSignalR Users
.
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);
Rozbočovače silného typu
Nevýhodou použití SendAsync
je, že spoléhá na řetězec k určení metody klienta, která se má volat. Pokud je název metody chybně napsaný nebo chybí v klientovi, ponechá kód otevřený chybám za běhu.
Alternativou k použití SendAsync
je silného Hub typu třídy s Hub<T>. V následujícím příkladu ChatHub
byla metoda klienta extrahována do rozhraní s názvem IChatClient
:
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Toto rozhraní lze použít k refaktoringu ChatHub
předchozího příkladu na silné typy:
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);
}
Použití Hub<IChatClient>
umožňuje kontrolu doby kompilace klientských metod. To brání problémům způsobeným používáním řetězců, protože Hub<T>
může poskytovat přístup pouze k metodám definovaným v rozhraní. Použití silného typu Hub<T>
zakáže možnost používat SendAsync
.
Poznámka:
Přípona Async
se neodebrala z názvů metod. Pokud není definovaná .on('MyMethodAsync')
metoda klienta , nepoužívejte MyMethodAsync
ji jako název.
Výsledky klienta
Kromě volání klientů může server požádat o výsledek klienta. To vyžaduje, aby server používal ISingleClientProxy.InvokeAsync
a klient vrátil výsledek z jeho .On
obslužné rutiny.
Existují dva způsoby použití rozhraní API na serveru, první je volání Client(...)
nebo Caller
vlastnosti Clients
v metodě centra:
public class ChatHub : Hub
{
public async Task<string> WaitForMessage(string connectionId)
{
var message = await Clients.Client(connectionId).InvokeAsync<string>(
"GetMessage");
return message;
}
}
Druhým způsobem je volání Client(...)
instance IHubContext<T>
:
async Task SomeMethod(IHubContext<MyHub> context)
{
string result = await context.Clients.Client(connectionID).InvokeAsync<string>(
"GetMessage");
}
Rozbočovače silného typu můžou také vracet hodnoty z metod rozhraní:
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;
}
}
Klienti vrací výsledky v jejich .On(...)
obslužných rutinách, jak je znázorněno níže:
Klient .NET
hubConnection.On("GetMessage", async () =>
{
Console.WriteLine("Enter message:");
var message = await Console.In.ReadLineAsync();
return message;
});
Klient TypeScriptu
hubConnection.on("GetMessage", async () => {
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("message");
}, 100);
});
return promise;
});
Java klient
hubConnection.onWithResult("GetMessage", () -> {
return Single.just("message");
});
Změna názvu metody centra
Ve výchozím nastavení je název metody centra serveru název metody .NET. Chcete-li změnit toto výchozí chování pro konkrétní metodu , použijte atribut HubMethodName . Při vyvolání metody by měl klient místo názvu metody .NET použít tento název:
[HubMethodName("SendMessageToUser")]
public async Task DirectMessage(string user, string message)
=> await Clients.User(user).SendAsync("ReceiveMessage", user, message);
Vložení služeb do centra
Konstruktory centra mohou přijímat služby z DI jako parametry, které mohou být uloženy ve vlastnostech třídy pro použití v metodě centra.
Při vkládání více služeb pro různé metody rozbočovače nebo jako alternativní způsob psaní kódu mohou metody centra také přijímat služby z DI. Ve výchozím nastavení se parametry metody centra kontrolují a v případě potřeby překládají z DI.
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);
}
}
Pokud není žádoucí implicitní rozlišení parametrů ze služeb, zakažte ho pomocí DisableImplicitFromServicesParameters.
Pokud chcete explicitně určit, které parametry se přeloží z DI v metodách centra, použijte možnost a použijte DisableImplicitFromServicesParameters
[FromServices]
atribut nebo vlastní atribut, který implementuje IFromServiceMetadata
parametry metody centra, které by se měly přeložit 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);
}
}
Poznámka:
Tato funkce využívá funkci IServiceProviderIsService, která je volitelně implementována implementacemi DI. Pokud kontejner DI aplikace tuto funkci nepodporuje, vložení služeb do metod centra se nepodporuje.
Podpora služeb s klíči v injektáži závislostí
Služby s klíči odkazují na mechanismus registrace a načítání služeb injektáže závislostí (DI) pomocí klíčů. Služba je přidružena ke klíči voláním AddKeyedSingleton (nebo AddKeyedScoped
AddKeyedTransient
) k jeho registraci. Přístup k registrované službě zadáním klíče s atributem [FromKeyedServices]
. Následující kód ukazuje, jak používat služby s klíči:
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"));
}
}
Zpracování událostí pro připojení
Rozhraní SignalR API služby Hubs poskytuje OnConnectedAsync a OnDisconnectedAsync virtuální metody pro správu a sledování připojení. Přepište virtuální metodu OnConnectedAsync
, aby prováděla akce, když se klient připojí k centru, jako je například jeho přidání do skupiny:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Přepište virtuální metodu OnDisconnectedAsync
, aby prováděla akce, když se klient odpojí. Pokud se klient záměrně odpojí, například voláním connection.stop()
, exception
parametr je nastaven na null
hodnotu . Pokud se však klient odpojí kvůli chybě, například kvůli selhání sítě, obsahuje parametr výjimku, exception
která popisuje selhání:
public override async Task OnDisconnectedAsync(Exception? exception)
{
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync nemusí být volána , OnDisconnectedAsyncje automaticky zpracována za vás.
Zpracování chyb
Výjimky vyvolané metodami centra se odesílají klientovi, který metodu vyvolal. V javascriptovém klientovi invoke
vrátí metoda JavaScript Promise
. Klienti můžou ke vráceným příslibům připojit obslužnou rutinu catch
nebo ji použít async
await
try
/catch
/ke zpracování výjimek:
try {
await connection.invoke("SendMessage", user, message);
} catch (err) {
console.error(err);
}
Připojení se nezavřou, když rozbočovač vyvolá výjimku. Ve výchozím nastavení SignalR vrátí klientovi obecnou chybovou zprávu, jak je znázorněno v následujícím příkladu:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'SendMessage' on the server.
Neočekávané výjimky často obsahují citlivé informace, například název databázového serveru v výjimce aktivované v případě selhání připojení k databázi. SignalR nezpřístupňuje tyto podrobné chybové zprávy ve výchozím nastavení jako bezpečnostní opatření. Další informace o tom, proč jsou podrobnosti o výjimce potlačeny, najdete v tématu Aspekty zabezpečení v ASP.NET Core SignalR.
Pokud je nutné do klienta rozšířit výjimečný stav, použijte HubException třídu. HubException
Pokud je vyvolán v metodě centra, SignalRodešle klientovi celou zprávu o výjimce, která nenímodifikovaná:
public Task ThrowException()
=> throw new HubException("This error will be sent to the client!");
Poznámka:
SignalR odešle Message
vlastnost výjimky pouze klientovi. Trasování zásobníku a další vlastnosti výjimky nejsou klientovi k dispozici.
Další materiály
Od Rachel Appel a Kevin Griffin
Rozhraní SignalR API služby Hubs umožňuje připojeným klientům volat metody na serveru, což usnadňuje komunikaci v reálném čase. Server definuje metody, které volá klient, a klient definuje metody, které jsou volány serverem. SignalR umožňuje také nepřímou komunikaci mezi klienty a klienty, vždy zprostředkovanou centrem SignalR , což umožňuje odesílání zpráv mezi jednotlivými klienty, skupinami nebo všemi připojenými klienty. SignalR postará se o všechno potřebné k tomu, aby bylo možné komunikaci mezi klientem a klientem v reálném čase.
Konfigurace SignalR center
Pokud chcete zaregistrovat služby vyžadované SignalR rozbočovači, zavolejte AddSignalR do Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddSignalR();
Ke konfiguraci SignalR koncových bodů zavolejte MapHubtaké v Program.cs
:
app.MapRazorPages();
app.MapHub<ChatHub>("/Chat");
app.Run();
Poznámka:
ASP.NET sestavení na straně serveru se SignalR teď instalují se sadou .NET Core SDK. Další informace najdete SignalR v sestaveních ve sdíleném rozhraní .
Vytváření a používání center
Vytvoření centra deklarováním třídy, která dědí z Hub. Přidejte public
do třídy metody, které je volat z klientů:
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
=> await Clients.All.SendAsync("ReceiveMessage", user, message);
}
Poznámka:
Rozbočovače jsou přechodné:
- Neukládejte stav ve vlastnosti třídy centra. Každé volání metody centra se provádí v nové instanci centra.
- Vytvořte instanci centra přímo prostřednictvím injektáže závislostí. K odesílání zpráv klientovi z jiného prostředí aplikace použijte příkaz
IHubContext
. - Používá se
await
při volání asynchronních metod, které závisí na udržování centra. Například metodaClients.All.SendAsync(...)
může selhat, pokud je volána bezawait
a metoda centra se dokončí předSendAsync
dokončením.
Kontextový objekt
Třída Hub obsahuje Context vlastnost, která obsahuje následující vlastnosti s informacemi o připojení:
Vlastnost | Popis |
---|---|
ConnectionId | Získá jedinečné ID pro připojení přiřazeno SignalR. Pro každé připojení existuje jedno ID připojení. |
UserIdentifier | Získá identifikátor uživatele. Ve výchozím nastavení SignalR se jako identifikátor uživatele používá ClaimTypes.NameIdentifier z ClaimsPrincipal přidruženého připojení. |
User | ClaimsPrincipal Získá přidružené k aktuálnímu uživateli. |
Items | Získá kolekci klíč/hodnota, která se dá použít ke sdílení dat v rámci tohoto připojení. Data mohou být uložena v této kolekci a budou zachována pro připojení napříč různými vyvoláním metod centra. |
Features | Získá kolekci funkcí dostupných v připojení. Prozatím tato kolekce není ve většině scénářů potřebná, takže zatím není podrobně zdokumentovaná. |
ConnectionAborted | CancellationToken Získá upozornění, když je připojení přerušeno. |
Hub.Context obsahuje také následující metody:
metoda | Popis |
---|---|
GetHttpContext | HttpContext Vrátí pro připojení nebo null pokud připojení není přidružené k požadavku HTTP. Pro připojení HTTP použijte tuto metodu k získání informací, jako jsou hlavičky HTTP a řetězce dotazů. |
Abort | Přeruší připojení. |
Objekt Klienti
Třída Hub obsahuje Clients vlastnost, která obsahuje následující vlastnosti pro komunikaci mezi serverem a klientem:
Vlastnost | Popis |
---|---|
All | Volá metodu pro všechny připojené klienty. |
Caller | Volá metodu na klientovi, který vyvolal metodu centra. |
Others | Volá metodu pro všechny připojené klienty s výjimkou klienta, který vyvolal metodu. |
Hub.Clients obsahuje také následující metody:
metoda | Popis |
---|---|
AllExcept | Volá metodu pro všechny připojené klienty s výjimkou zadaných připojení. |
Client | Zavolá metodu pro konkrétního připojeného klienta. |
Clients | Volání metody pro konkrétní připojené klienty |
Group | Volá metodu pro všechna připojení v zadané skupině. |
GroupExcept | Volá metodu pro všechna připojení v zadané skupině s výjimkou zadaných připojení. |
Groups | Volá metodu pro více skupin připojení. |
OthersInGroup | Volá metodu ve skupině připojení s výjimkou klienta, který vyvolal metodu centra. |
User | Volá metodu pro všechna připojení přidružená ke konkrétnímu uživateli. |
Users | Volá metodu pro všechna připojení přidružená k zadaným uživatelům. |
Každá vlastnost nebo metoda v předchozích tabulkách vrací objekt s metodou SendAsync
. Metoda SendAsync
obdrží název klientské metody pro volání a všechny parametry.
Objekt vrácený Client
metodami a Caller
metody také obsahují metodu InvokeAsync
, kterou lze použít k čekání na výsledek z klienta.
Odesílání zpráv klientům
Pokud chcete volat konkrétní klienty, použijte vlastnosti objektu Clients
. V následujícím příkladu existují tři metody centra:
SendMessage
odešle zprávu všem připojeným klientům pomocí .Clients.All
SendMessageToCaller
odešle zprávu zpět volajícímu pomocí funkceClients.Caller
.SendMessageToGroup
odešle zprávu všem klientům ve skupiněSignalR Users
.
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);
Rozbočovače silného typu
Nevýhodou použití SendAsync
je, že spoléhá na řetězec k určení metody klienta, která se má volat. Pokud je název metody chybně napsaný nebo chybí v klientovi, ponechá kód otevřený chybám za běhu.
Alternativou k použití SendAsync
je silného Hub typu třídy s Hub<T>. V následujícím příkladu ChatHub
byla metoda klienta extrahována do rozhraní s názvem IChatClient
:
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Toto rozhraní lze použít k refaktoringu ChatHub
předchozího příkladu na silné typy:
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);
}
Použití Hub<IChatClient>
umožňuje kontrolu doby kompilace klientských metod. To brání problémům způsobeným používáním řetězců, protože Hub<T>
může poskytovat přístup pouze k metodám definovaným v rozhraní. Použití silného typu Hub<T>
zakáže možnost používat SendAsync
.
Poznámka:
Přípona Async
se neodebrala z názvů metod. Pokud není definovaná .on('MyMethodAsync')
metoda klienta , nepoužívejte MyMethodAsync
ji jako název.
Výsledky klienta
Kromě volání klientů může server požádat o výsledek klienta. To vyžaduje, aby server používal ISingleClientProxy.InvokeAsync
a klient vrátil výsledek z jeho .On
obslužné rutiny.
Existují dva způsoby použití rozhraní API na serveru, první je volání Client(...)
nebo Caller
vlastnosti Clients
v metodě centra:
public class ChatHub : Hub
{
public async Task<string> WaitForMessage(string connectionId)
{
var message = await Clients.Client(connectionId).InvokeAsync<string>(
"GetMessage");
return message;
}
}
Druhým způsobem je volání Client(...)
instance IHubContext<T>
:
async Task SomeMethod(IHubContext<MyHub> context)
{
string result = await context.Clients.Client(connectionID).InvokeAsync<string>(
"GetMessage");
}
Rozbočovače silného typu můžou také vracet hodnoty z metod rozhraní:
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;
}
}
Klienti vrací výsledky v jejich .On(...)
obslužných rutinách, jak je znázorněno níže:
Klient .NET
hubConnection.On("GetMessage", async () =>
{
Console.WriteLine("Enter message:");
var message = await Console.In.ReadLineAsync();
return message;
});
Klient TypeScriptu
hubConnection.on("GetMessage", async () => {
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("message");
}, 100);
});
return promise;
});
Java klient
hubConnection.onWithResult("GetMessage", () -> {
return Single.just("message");
});
Změna názvu metody centra
Ve výchozím nastavení je název metody centra serveru název metody .NET. Chcete-li změnit toto výchozí chování pro konkrétní metodu , použijte atribut HubMethodName . Při vyvolání metody by měl klient místo názvu metody .NET použít tento název:
[HubMethodName("SendMessageToUser")]
public async Task DirectMessage(string user, string message)
=> await Clients.User(user).SendAsync("ReceiveMessage", user, message);
Vložení služeb do centra
Konstruktory centra mohou přijímat služby z DI jako parametry, které mohou být uloženy ve vlastnostech třídy pro použití v metodě centra.
Při vkládání více služeb pro různé metody rozbočovače nebo jako alternativní způsob psaní kódu mohou metody centra také přijímat služby z DI. Ve výchozím nastavení se parametry metody centra kontrolují a v případě potřeby překládají z DI.
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);
}
}
Pokud není žádoucí implicitní rozlišení parametrů ze služeb, zakažte ho pomocí DisableImplicitFromServicesParameters.
Pokud chcete explicitně určit, které parametry se přeloží z DI v metodách centra, použijte možnost a použijte DisableImplicitFromServicesParameters
[FromServices]
atribut nebo vlastní atribut, který implementuje IFromServiceMetadata
parametry metody centra, které by se měly přeložit 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);
}
}
Poznámka:
Tato funkce využívá funkci IServiceProviderIsService, která je volitelně implementována implementacemi DI. Pokud kontejner DI aplikace tuto funkci nepodporuje, vložení služeb do metod centra se nepodporuje.
Zpracování událostí pro připojení
Rozhraní SignalR API služby Hubs poskytuje OnConnectedAsync a OnDisconnectedAsync virtuální metody pro správu a sledování připojení. Přepište virtuální metodu OnConnectedAsync
, aby prováděla akce, když se klient připojí k centru, jako je například jeho přidání do skupiny:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Přepište virtuální metodu OnDisconnectedAsync
, aby prováděla akce, když se klient odpojí. Pokud se klient záměrně odpojí, například voláním connection.stop()
, exception
parametr je nastaven na null
hodnotu . Pokud se však klient odpojí kvůli chybě, například kvůli selhání sítě, obsahuje parametr výjimku, exception
která popisuje selhání:
public override async Task OnDisconnectedAsync(Exception? exception)
{
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync nemusí být volána , OnDisconnectedAsyncje automaticky zpracována za vás.
Zpracování chyb
Výjimky vyvolané metodami centra se odesílají klientovi, který metodu vyvolal. V javascriptovém klientovi invoke
vrátí metoda JavaScript Promise
. Klienti můžou ke vráceným příslibům připojit obslužnou rutinu catch
nebo ji použít async
await
try
/catch
/ke zpracování výjimek:
try {
await connection.invoke("SendMessage", user, message);
} catch (err) {
console.error(err);
}
Připojení se nezavřou, když rozbočovač vyvolá výjimku. Ve výchozím nastavení SignalR vrátí klientovi obecnou chybovou zprávu, jak je znázorněno v následujícím příkladu:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'SendMessage' on the server.
Neočekávané výjimky často obsahují citlivé informace, například název databázového serveru v výjimce aktivované v případě selhání připojení k databázi. SignalR nezpřístupňuje tyto podrobné chybové zprávy ve výchozím nastavení jako bezpečnostní opatření. Další informace o tom, proč jsou podrobnosti o výjimce potlačeny, najdete v tématu Aspekty zabezpečení v ASP.NET Core SignalR.
Pokud je nutné do klienta rozšířit výjimečný stav, použijte HubException třídu. HubException
Pokud je vyvolán v metodě centra, SignalRodešle klientovi celou zprávu o výjimce, která nenímodifikovaná:
public Task ThrowException()
=> throw new HubException("This error will be sent to the client!");
Poznámka:
SignalR odešle Message
vlastnost výjimky pouze klientovi. Trasování zásobníku a další vlastnosti výjimky nejsou klientovi k dispozici.
Další materiály
Od Rachel Appel a Kevin Griffin
Rozhraní SignalR API služby Hubs umožňuje připojeným klientům volat metody na serveru, což usnadňuje komunikaci v reálném čase. Server definuje metody, které volá klient, a klient definuje metody, které jsou volány serverem. SignalR umožňuje také nepřímou komunikaci mezi klienty a klienty, vždy zprostředkovanou centrem SignalR , což umožňuje odesílání zpráv mezi jednotlivými klienty, skupinami nebo všemi připojenými klienty. SignalR postará se o všechno potřebné k tomu, aby bylo možné komunikaci mezi klientem a klientem v reálném čase.
Konfigurace SignalR center
Pokud chcete zaregistrovat služby vyžadované SignalR rozbočovači, zavolejte AddSignalR do Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddSignalR();
Ke konfiguraci SignalR koncových bodů zavolejte MapHubtaké v Program.cs
:
app.MapRazorPages();
app.MapHub<ChatHub>("/Chat");
app.Run();
Poznámka:
ASP.NET sestavení na straně serveru se SignalR teď instalují se sadou .NET Core SDK. Další informace najdete SignalR v sestaveních ve sdíleném rozhraní .
Vytváření a používání center
Vytvoření centra deklarováním třídy, která dědí z Hub. Přidejte public
do třídy metody, které je volat z klientů:
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
=> await Clients.All.SendAsync("ReceiveMessage", user, message);
}
Poznámka:
Rozbočovače jsou přechodné:
- Neukládejte stav ve vlastnosti třídy centra. Každé volání metody centra se provádí v nové instanci centra.
- Vytvořte instanci centra přímo prostřednictvím injektáže závislostí. K odesílání zpráv klientovi z jiného prostředí aplikace použijte příkaz
IHubContext
. - Používá se
await
při volání asynchronních metod, které závisí na udržování centra. Například metodaClients.All.SendAsync(...)
může selhat, pokud je volána bezawait
a metoda centra se dokončí předSendAsync
dokončením.
Kontextový objekt
Třída Hub obsahuje Context vlastnost, která obsahuje následující vlastnosti s informacemi o připojení:
Vlastnost | Popis |
---|---|
ConnectionId | Získá jedinečné ID pro připojení přiřazeno SignalR. Pro každé připojení existuje jedno ID připojení. |
UserIdentifier | Získá identifikátor uživatele. Ve výchozím nastavení SignalR se jako identifikátor uživatele používá ClaimTypes.NameIdentifier z ClaimsPrincipal přidruženého připojení. |
User | ClaimsPrincipal Získá přidružené k aktuálnímu uživateli. |
Items | Získá kolekci klíč/hodnota, která se dá použít ke sdílení dat v rámci tohoto připojení. Data mohou být uložena v této kolekci a budou zachována pro připojení napříč různými vyvoláním metod centra. |
Features | Získá kolekci funkcí dostupných v připojení. Prozatím tato kolekce není ve většině scénářů potřebná, takže zatím není podrobně zdokumentovaná. |
ConnectionAborted | CancellationToken Získá upozornění, když je připojení přerušeno. |
Hub.Context obsahuje také následující metody:
metoda | Popis |
---|---|
GetHttpContext | HttpContext Vrátí pro připojení nebo null pokud připojení není přidružené k požadavku HTTP. Pro připojení HTTP použijte tuto metodu k získání informací, jako jsou hlavičky HTTP a řetězce dotazů. |
Abort | Přeruší připojení. |
Objekt Klienti
Třída Hub obsahuje Clients vlastnost, která obsahuje následující vlastnosti pro komunikaci mezi serverem a klientem:
Vlastnost | Popis |
---|---|
All | Volá metodu pro všechny připojené klienty. |
Caller | Volá metodu na klientovi, který vyvolal metodu centra. |
Others | Volá metodu pro všechny připojené klienty s výjimkou klienta, který vyvolal metodu. |
Hub.Clients obsahuje také následující metody:
metoda | Popis |
---|---|
AllExcept | Volá metodu pro všechny připojené klienty s výjimkou zadaných připojení. |
Client | Zavolá metodu pro konkrétního připojeného klienta. |
Clients | Volání metody pro konkrétní připojené klienty |
Group | Volá metodu pro všechna připojení v zadané skupině. |
GroupExcept | Volá metodu pro všechna připojení v zadané skupině s výjimkou zadaných připojení. |
Groups | Volá metodu pro více skupin připojení. |
OthersInGroup | Volá metodu ve skupině připojení s výjimkou klienta, který vyvolal metodu centra. |
User | Volá metodu pro všechna připojení přidružená ke konkrétnímu uživateli. |
Users | Volá metodu pro všechna připojení přidružená k zadaným uživatelům. |
Každá vlastnost nebo metoda v předchozích tabulkách vrací objekt s metodou SendAsync
. Metoda SendAsync
obdrží název klientské metody pro volání a všechny parametry.
Odesílání zpráv klientům
Pokud chcete volat konkrétní klienty, použijte vlastnosti objektu Clients
. V následujícím příkladu existují tři metody centra:
SendMessage
odešle zprávu všem připojeným klientům pomocí .Clients.All
SendMessageToCaller
odešle zprávu zpět volajícímu pomocí funkceClients.Caller
.SendMessageToGroup
odešle zprávu všem klientům ve skupiněSignalR Users
.
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);
Rozbočovače silného typu
Nevýhodou použití SendAsync
je, že spoléhá na řetězec k určení metody klienta, která se má volat. Pokud je název metody chybně napsaný nebo chybí v klientovi, ponechá kód otevřený chybám za běhu.
Alternativou k použití SendAsync
je silného Hub typu třídy s Hub<T>. V následujícím příkladu ChatHub
byla metoda klienta extrahována do rozhraní s názvem IChatClient
:
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Toto rozhraní lze použít k refaktoringu ChatHub
předchozího příkladu na silné typy:
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);
}
Použití Hub<IChatClient>
umožňuje kontrolu doby kompilace klientských metod. To brání problémům způsobeným používáním řetězců, protože Hub<T>
může poskytovat přístup pouze k metodám definovaným v rozhraní. Použití silného typu Hub<T>
zakáže možnost používat SendAsync
.
Poznámka:
Přípona Async
se neodebrala z názvů metod. Pokud není definovaná .on('MyMethodAsync')
metoda klienta , nepoužívejte MyMethodAsync
ji jako název.
Změna názvu metody centra
Ve výchozím nastavení je název metody centra serveru název metody .NET. Chcete-li změnit toto výchozí chování pro konkrétní metodu , použijte atribut HubMethodName . Při vyvolání metody by měl klient místo názvu metody .NET použít tento název:
[HubMethodName("SendMessageToUser")]
public async Task DirectMessage(string user, string message)
=> await Clients.User(user).SendAsync("ReceiveMessage", user, message);
Zpracování událostí pro připojení
Rozhraní SignalR API služby Hubs poskytuje OnConnectedAsync a OnDisconnectedAsync virtuální metody pro správu a sledování připojení. Přepište virtuální metodu OnConnectedAsync
, aby prováděla akce, když se klient připojí k centru, jako je například jeho přidání do skupiny:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Přepište virtuální metodu OnDisconnectedAsync
, aby prováděla akce, když se klient odpojí. Pokud se klient záměrně odpojí, například voláním connection.stop()
, exception
parametr je nastaven na null
hodnotu . Pokud se však klient odpojí kvůli chybě, například kvůli selhání sítě, obsahuje parametr výjimku, exception
která popisuje selhání:
public override async Task OnDisconnectedAsync(Exception? exception)
{
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync nemusí být volána , OnDisconnectedAsyncje automaticky zpracována za vás.
Zpracování chyb
Výjimky vyvolané metodami centra se odesílají klientovi, který metodu vyvolal. V javascriptovém klientovi invoke
vrátí metoda JavaScript Promise
. Klienti můžou ke vráceným příslibům připojit obslužnou rutinu catch
nebo ji použít async
await
try
/catch
/ke zpracování výjimek:
try {
await connection.invoke("SendMessage", user, message);
} catch (err) {
console.error(err);
}
Připojení se nezavřou, když rozbočovač vyvolá výjimku. Ve výchozím nastavení SignalR vrátí klientovi obecnou chybovou zprávu, jak je znázorněno v následujícím příkladu:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'SendMessage' on the server.
Neočekávané výjimky často obsahují citlivé informace, například název databázového serveru v výjimce aktivované v případě selhání připojení k databázi. SignalR nezpřístupňuje tyto podrobné chybové zprávy ve výchozím nastavení jako bezpečnostní opatření. Další informace o tom, proč jsou podrobnosti o výjimce potlačeny, najdete v tématu Aspekty zabezpečení v ASP.NET Core SignalR.
Pokud je nutné do klienta rozšířit výjimečný stav, použijte HubException třídu. HubException
Pokud je vyvolán v metodě centra, SignalRodešle klientovi celou zprávu o výjimce, která nenímodifikovaná:
public Task ThrowException()
=> throw new HubException("This error will be sent to the client!");
Poznámka:
SignalR odešle Message
vlastnost výjimky pouze klientovi. Trasování zásobníku a další vlastnosti výjimky nejsou klientovi k dispozici.
Další materiály
Od Rachel Appel a Kevin Griffin
Zobrazení nebo stažení ukázkového kódu (postup stažení)
Co je SignalR centrum
Rozhraní SignalR API služby Hubs umožňuje připojeným klientům volat metody na serveru, což usnadňuje komunikaci v reálném čase. Server definuje metody, které volá klient, a klient definuje metody, které jsou volány serverem. SignalR umožňuje také nepřímou komunikaci mezi klienty a klienty, vždy zprostředkovanou centrem SignalR , což umožňuje odesílání zpráv mezi jednotlivými klienty, skupinami nebo všemi připojenými klienty. SignalR postará se o všechno potřebné k tomu, aby bylo možné komunikaci mezi klientem a klientem v reálném čase.
Konfigurace SignalR center
Middleware SignalR vyžaduje některé služby, které jsou nakonfigurovány voláním AddSignalR:
services.AddSignalR();
Při přidávání SignalR funkcí do aplikace ASP.NET Core nastavte SignalR trasy voláním zpětného Startup.Configure
UseEndpoints volání MapHub metody:
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>("/chathub");
});
Poznámka:
ASP.NET sestavení na straně serveru se SignalR teď instalují se sadou .NET Core SDK. Další informace najdete SignalR v sestaveních ve sdíleném rozhraní .
Vytváření a používání center
Vytvořte centrum deklarováním třídy, která dědí z Hub, a přidejte do ní veřejné metody. Klienti mohou volat metody definované takto public
:
public class ChatHub : Hub
{
public Task SendMessage(string user, string message)
{
return Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
Můžete zadat návratový typ a parametry, včetně komplexních typů a polí, stejně jako v jakékoli metodě jazyka C#. SignalR zpracovává serializaci a deserializaci složitých objektů a polí v parametrech a návratových hodnotách.
Poznámka:
Rozbočovače jsou přechodné:
- Neukládejte stav ve vlastnosti třídy centra. Každé volání metody centra se provádí v nové instanci centra.
- Vytvořte instanci centra přímo prostřednictvím injektáže závislostí. K odesílání zpráv klientovi z jiného prostředí aplikace použijte příkaz
IHubContext
. - Používá se
await
při volání asynchronních metod, které závisí na udržování centra. Například metodaClients.All.SendAsync(...)
může selhat, pokud je volána bezawait
a metoda centra se dokončí předSendAsync
dokončením.
Kontextový objekt
Třída Hub má Context vlastnost, která obsahuje následující vlastnosti s informacemi o připojení:
Vlastnost | Popis |
---|---|
ConnectionId | Získá jedinečné ID pro připojení přiřazeno SignalR. Pro každé připojení existuje jedno ID připojení. |
UserIdentifier | Získá identifikátor uživatele. Ve výchozím nastavení SignalR se jako identifikátor uživatele používá ClaimTypes.NameIdentifier z ClaimsPrincipal přidruženého připojení. |
User | ClaimsPrincipal Získá přidružené k aktuálnímu uživateli. |
Items | Získá kolekci klíč/hodnota, která se dá použít ke sdílení dat v rámci tohoto připojení. Data mohou být uložena v této kolekci a budou zachována pro připojení napříč různými vyvoláním metod centra. |
Features | Získá kolekci funkcí dostupných v připojení. Prozatím tato kolekce není ve většině scénářů potřebná, takže zatím není podrobně zdokumentovaná. |
ConnectionAborted | CancellationToken Získá upozornění, když je připojení přerušeno. |
Hub.Context obsahuje také následující metody:
metoda | Popis |
---|---|
GetHttpContext | HttpContext Vrátí pro připojení nebo null pokud připojení není přidružené k požadavku HTTP. Pro připojení HTTP můžete pomocí této metody získat informace, jako jsou hlavičky HTTP a řetězce dotazů. |
Abort | Přeruší připojení. |
Objekt Klienti
Třída Hub má Clients vlastnost, která obsahuje následující vlastnosti pro komunikaci mezi serverem a klientem:
Vlastnost | Popis |
---|---|
All | Volá metodu pro všechny připojené klienty. |
Caller | Volá metodu na klientovi, který vyvolal metodu centra. |
Others | Volá metodu pro všechny připojené klienty s výjimkou klienta, který vyvolal metodu. |
Hub.Clients obsahuje také následující metody:
metoda | Popis |
---|---|
AllExcept | Volá metodu pro všechny připojené klienty s výjimkou zadaných připojení. |
Client | Zavolá metodu pro konkrétního připojeného klienta. |
Clients | Volání metody pro konkrétní připojené klienty |
Group | Volá metodu pro všechna připojení v zadané skupině. |
GroupExcept | Volá metodu pro všechna připojení v zadané skupině s výjimkou zadaných připojení. |
Groups | Volá metodu pro více skupin připojení. |
OthersInGroup | Volá metodu ve skupině připojení s výjimkou klienta, který vyvolal metodu centra. |
User | Volá metodu pro všechna připojení přidružená ke konkrétnímu uživateli. |
Users | Volá metodu pro všechna připojení přidružená k zadaným uživatelům. |
Každá vlastnost nebo metoda v předchozích tabulkách vrací objekt s metodou SendAsync
. Tato SendAsync
metoda umožňuje zadat název a parametry klientské metody, které se mají volat.
Odesílání zpráv klientům
Pokud chcete volat konkrétní klienty, použijte vlastnosti objektu Clients
. V následujícím příkladu existují tři metody centra:
SendMessage
odešle zprávu všem připojeným klientům pomocí .Clients.All
SendMessageToCaller
odešle zprávu zpět volajícímu pomocí funkceClients.Caller
.SendMessageToGroup
odešle zprávu všem klientům ve skupiněSignalR Users
.
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);
}
Rozbočovače silného typu
Nevýhodou použití SendAsync
je, že spoléhá na magický řetězec k určení klientské metody, která se má volat. Pokud je název metody chybně napsaný nebo chybí v klientovi, ponechá kód otevřený chybám za běhu.
Alternativou k použití SendAsync
je silného typu s Hub Hub<T>. V následujícím příkladu ChatHub
byly klientské metody extrahovány do rozhraní s názvem IChatClient
.
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Toto rozhraní lze použít k refaktoringu ChatHub
předchozího příkladu:
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);
}
}
Použití Hub<IChatClient>
umožňuje kontrolu doby kompilace klientských metod. To brání problémům způsobeným používáním magických řetězců, protože Hub<T>
může poskytovat přístup pouze k metodám definovaným v rozhraní.
Použití silného typu Hub<T>
zakáže možnost používat SendAsync
. Všechny metody definované v rozhraní mohou být stále definovány jako asynchronní. Ve skutečnosti by každá z těchto metod měla vrátit Task
hodnotu . Vzhledem k tomu, že se jedná o rozhraní, nepoužívejte async
klíčové slovo. Příklad:
public interface IClient
{
Task ClientMethod();
}
Poznámka:
Přípona Async
není z názvu metody odebrána. Pokud není .on('MyMethodAsync')
definovaná vaše metoda klienta , neměli byste ji používat MyMethodAsync
jako název.
Změna názvu metody centra
Ve výchozím nastavení je název metody centra serveru název metody .NET. Můžete však použít HubMethodName atribut změnit toto výchozí a ručně zadat název metody. Při vyvolání metody by měl klient místo názvu metody .NET použít tento název:
[HubMethodName("SendMessageToUser")]
public Task DirectMessage(string user, string message)
{
return Clients.User(user).SendAsync("ReceiveMessage", user, message);
}
Zpracování událostí pro připojení
Rozhraní SignalR API služby Hubs poskytuje OnConnectedAsync a OnDisconnectedAsync virtuální metody pro správu a sledování připojení. Přepište virtuální metodu OnConnectedAsync
, aby prováděla akce, když se klient připojí k centru, jako je například jeho přidání do skupiny:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Přepište virtuální metodu OnDisconnectedAsync
, aby prováděla akce, když se klient odpojí. Pokud se klient záměrně odpojí (například voláním connection.stop()
), exception
parametr bude null
. Pokud se ale klient odpojí kvůli chybě (například selhání sítě), exception
parametr bude obsahovat výjimku popisující selhání:
public override async Task OnDisconnectedAsync(Exception exception)
{
await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", "I", "disconnect");
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync nemusí být volána , OnDisconnectedAsyncje automaticky zpracována za vás.
Upozorňující
Upozornění zabezpečení: Zveřejnění ConnectionId
může vést k zosobnění se zlými úmysly, pokud SignalR je server nebo verze klienta ASP.NET Core 2.2 nebo starší.
Zpracování chyb
Výjimky vyvolané metodami centra se odesílají klientovi, který metodu vyvolal. V javascriptovém klientovi invoke
vrátí metoda JavaScript Promise
. Když se klientovi zobrazí chyba s obslužnou rutinou připojenou k příslibu pomocí catch
, vyvolá se a předá jako javascriptový Error
objekt:
connection.invoke("SendMessage", user, message).catch(err => console.error(err));
Pokud vaše centrum vyvolá výjimku, připojení se nezavřou. Ve výchozím nastavení SignalR vrátí klientovi obecnou chybovou zprávu. Příklad:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'MethodName' on the server.
Neočekávané výjimky často obsahují citlivé informace, například název databázového serveru v výjimce aktivované v případě selhání připojení k databázi. SignalR nezpřístupňuje tyto podrobné chybové zprávy ve výchozím nastavení jako bezpečnostní opatření. Další informace o tom, proč jsou podrobnosti o výjimce potlačeny, najdete v tématu Aspekty zabezpečení v ASP.NET Core SignalR.
Pokud máte výjimečný stav, který chcete rozšířit do klienta, můžete použít HubException třídu. Pokud vyvoláte metodu HubException
centra, SignalR odešlete klientovi celou zprávu, která nenímodifikovaná:
public Task ThrowException()
{
throw new HubException("This error will be sent to the client!");
}
Poznámka:
SignalR odešle Message
vlastnost výjimky pouze klientovi. Trasování zásobníku a další vlastnosti výjimky nejsou klientovi k dispozici.
Další materiály
Od Rachel Appel a Kevin Griffin
Zobrazení nebo stažení ukázkového kódu (postup stažení)
Co je SignalR centrum
Rozhraní SignalR API služby Hubs umožňuje připojeným klientům volat metody na serveru, což usnadňuje komunikaci v reálném čase. Server definuje metody, které volá klient, a klient definuje metody, které jsou volány serverem. SignalR umožňuje také nepřímou komunikaci mezi klienty a klienty, vždy zprostředkovanou centrem SignalR , což umožňuje odesílání zpráv mezi jednotlivými klienty, skupinami nebo všemi připojenými klienty. SignalR postará se o všechno potřebné k tomu, aby bylo možné komunikaci mezi klientem a klientem v reálném čase.
Konfigurace SignalR center
Middleware SignalR vyžaduje některé služby, které jsou nakonfigurovány voláním AddSignalR:
services.AddSignalR();
Při přidávání SignalR funkcí do aplikace ASP.NET Core nastavte SignalR trasy voláním UseSignalR metody Startup.Configure
:
app.UseSignalR(route =>
{
route.MapHub<ChatHub>("/chathub");
});
Vytváření a používání center
Vytvořte centrum deklarováním třídy, která dědí z Hub, a přidejte do ní veřejné metody. Klienti mohou volat metody definované takto public
:
public class ChatHub : Hub
{
public Task SendMessage(string user, string message)
{
return Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
Můžete zadat návratový typ a parametry, včetně komplexních typů a polí, stejně jako v jakékoli metodě jazyka C#. SignalR zpracovává serializaci a deserializaci složitých objektů a polí v parametrech a návratových hodnotách.
Poznámka:
Rozbočovače jsou přechodné:
- Neukládejte stav ve vlastnosti třídy centra. Každé volání metody centra se provádí v nové instanci centra.
- Vytvořte instanci centra přímo prostřednictvím injektáže závislostí. K odesílání zpráv klientovi z jiného prostředí aplikace použijte příkaz
IHubContext
. - Používá se
await
při volání asynchronních metod, které závisí na udržování centra. Například metodaClients.All.SendAsync(...)
může selhat, pokud je volána bezawait
a metoda centra se dokončí předSendAsync
dokončením.
Kontextový objekt
Třída Hub má Context vlastnost, která obsahuje následující vlastnosti s informacemi o připojení:
Vlastnost | Popis |
---|---|
ConnectionId | Získá jedinečné ID pro připojení přiřazeno SignalR. Pro každé připojení existuje jedno ID připojení. |
UserIdentifier | Získá identifikátor uživatele. Ve výchozím nastavení SignalR se jako identifikátor uživatele používá ClaimTypes.NameIdentifier z ClaimsPrincipal přidruženého připojení. |
User | ClaimsPrincipal Získá přidružené k aktuálnímu uživateli. |
Items | Získá kolekci klíč/hodnota, která se dá použít ke sdílení dat v rámci tohoto připojení. Data mohou být uložena v této kolekci a budou zachována pro připojení napříč různými vyvoláním metod centra. |
Features | Získá kolekci funkcí dostupných v připojení. Prozatím tato kolekce není ve většině scénářů potřebná, takže zatím není podrobně zdokumentovaná. |
ConnectionAborted | CancellationToken Získá upozornění, když je připojení přerušeno. |
Hub.Context obsahuje také následující metody:
metoda | Popis |
---|---|
GetHttpContext | HttpContext Vrátí pro připojení nebo null pokud připojení není přidružené k požadavku HTTP. Pro připojení HTTP můžete pomocí této metody získat informace, jako jsou hlavičky HTTP a řetězce dotazů. |
Abort | Přeruší připojení. |
Objekt Klienti
Třída Hub má Clients vlastnost, která obsahuje následující vlastnosti pro komunikaci mezi serverem a klientem:
Vlastnost | Popis |
---|---|
All | Volá metodu pro všechny připojené klienty. |
Caller | Volá metodu na klientovi, který vyvolal metodu centra. |
Others | Volá metodu pro všechny připojené klienty s výjimkou klienta, který vyvolal metodu. |
Hub.Clients obsahuje také následující metody:
metoda | Popis |
---|---|
AllExcept | Volá metodu pro všechny připojené klienty s výjimkou zadaných připojení. |
Client | Zavolá metodu pro konkrétního připojeného klienta. |
Clients | Volání metody pro konkrétní připojené klienty |
Group | Volá metodu pro všechna připojení v zadané skupině. |
GroupExcept | Volá metodu pro všechna připojení v zadané skupině s výjimkou zadaných připojení. |
Groups | Volá metodu pro více skupin připojení. |
OthersInGroup | Volá metodu ve skupině připojení s výjimkou klienta, který vyvolal metodu centra. |
User | Volá metodu pro všechna připojení přidružená ke konkrétnímu uživateli. |
Users | Volá metodu pro všechna připojení přidružená k zadaným uživatelům. |
Každá vlastnost nebo metoda v předchozích tabulkách vrací objekt s metodou SendAsync
. Tato SendAsync
metoda umožňuje zadat název a parametry klientské metody, které se mají volat.
Odesílání zpráv klientům
Pokud chcete volat konkrétní klienty, použijte vlastnosti objektu Clients
. V následujícím příkladu existují tři metody centra:
SendMessage
odešle zprávu všem připojeným klientům pomocí .Clients.All
SendMessageToCaller
odešle zprávu zpět volajícímu pomocí funkceClients.Caller
.SendMessageToGroup
odešle zprávu všem klientům ve skupiněSignalR Users
.
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);
}
Rozbočovače silného typu
Nevýhodou použití SendAsync
je, že spoléhá na magický řetězec k určení klientské metody, která se má volat. Pokud je název metody chybně napsaný nebo chybí v klientovi, ponechá kód otevřený chybám za běhu.
Alternativou k použití SendAsync
je silného typu s Hub Hub<T>. V následujícím příkladu ChatHub
byly klientské metody extrahovány do rozhraní s názvem IChatClient
.
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Toto rozhraní lze použít k refaktoringu ChatHub
předchozího příkladu:
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);
}
}
Použití Hub<IChatClient>
umožňuje kontrolu doby kompilace klientských metod. To brání problémům způsobeným používáním magických řetězců, protože Hub<T>
může poskytovat přístup pouze k metodám definovaným v rozhraní.
Použití silného typu Hub<T>
zakáže možnost používat SendAsync
. Všechny metody definované v rozhraní mohou být stále definovány jako asynchronní. Ve skutečnosti by každá z těchto metod měla vrátit Task
hodnotu . Vzhledem k tomu, že se jedná o rozhraní, nepoužívejte async
klíčové slovo. Příklad:
public interface IClient
{
Task ClientMethod();
}
Poznámka:
Přípona Async
není z názvu metody odebrána. Pokud není .on('MyMethodAsync')
definovaná vaše metoda klienta , neměli byste ji používat MyMethodAsync
jako název.
Změna názvu metody centra
Ve výchozím nastavení je název metody centra serveru název metody .NET. Můžete však použít HubMethodName atribut změnit toto výchozí a ručně zadat název metody. Při vyvolání metody by měl klient místo názvu metody .NET použít tento název:
[HubMethodName("SendMessageToUser")]
public Task DirectMessage(string user, string message)
{
return Clients.User(user).SendAsync("ReceiveMessage", user, message);
}
Zpracování událostí pro připojení
Rozhraní SignalR API služby Hubs poskytuje OnConnectedAsync a OnDisconnectedAsync virtuální metody pro správu a sledování připojení. Přepište virtuální metodu OnConnectedAsync
, aby prováděla akce, když se klient připojí k centru, jako je například jeho přidání do skupiny:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Přepište virtuální metodu OnDisconnectedAsync
, aby prováděla akce, když se klient odpojí. Pokud se klient záměrně odpojí (například voláním connection.stop()
), exception
parametr bude null
. Pokud se ale klient odpojí kvůli chybě (například selhání sítě), exception
parametr bude obsahovat výjimku popisující selhání:
public override async Task OnDisconnectedAsync(Exception exception)
{
await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", "I", "disconnect");
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync nemusí být volána , OnDisconnectedAsyncje automaticky zpracována za vás.
Upozorňující
Upozornění zabezpečení: Zveřejnění ConnectionId
může vést k zosobnění se zlými úmysly, pokud SignalR je server nebo verze klienta ASP.NET Core 2.2 nebo starší.
Zpracování chyb
Výjimky vyvolané metodami centra se odesílají klientovi, který metodu vyvolal. V javascriptovém klientovi invoke
vrátí metoda JavaScript Promise
. Když se klientovi zobrazí chyba s obslužnou rutinou připojenou k příslibu pomocí catch
, vyvolá se a předá jako javascriptový Error
objekt:
connection.invoke("SendMessage", user, message).catch(err => console.error(err));
Pokud vaše centrum vyvolá výjimku, připojení se nezavřou. Ve výchozím nastavení SignalR vrátí klientovi obecnou chybovou zprávu. Příklad:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'MethodName' on the server.
Neočekávané výjimky často obsahují citlivé informace, například název databázového serveru v výjimce aktivované v případě selhání připojení k databázi. SignalR nezpřístupňuje tyto podrobné chybové zprávy ve výchozím nastavení jako bezpečnostní opatření. Další informace o tom, proč jsou podrobnosti o výjimce potlačeny, najdete v tématu Aspekty zabezpečení v ASP.NET Core SignalR.
Pokud máte výjimečný stav, který chcete rozšířit do klienta, můžete použít HubException třídu. Pokud vyvoláte metodu HubException
centra, SignalR odešlete klientovi celou zprávu, která nenímodifikovaná:
public Task ThrowException()
{
throw new HubException("This error will be sent to the client!");
}
Poznámka:
SignalR odešle Message
vlastnost výjimky pouze klientovi. Trasování zásobníku a další vlastnosti výjimky nejsou klientovi k dispozici.