Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Door Rachel Appel en Kevin Griffin
Met de SignalR Hubs-API kunnen verbonden clients methoden op de server aanroepen, waardoor realtime communicatie wordt vergemakkelijkt. De server definieert methoden die door de client worden aangeroepen en de client definieert methoden die door de server worden aangeroepen. SignalR maakt ook indirecte client-naar-client-communicatie mogelijk, altijd gemediateerd door de SignalR Hub, zodat berichten kunnen worden verzonden tussen afzonderlijke clients, groepen of naar alle verbonden clients. SignalR zorgt ervoor dat realtime client-naar-server- en server-naar-clientcommunicatie mogelijk is.
Hubs configureren SignalR
Om de vereiste services voor SignalR hubs te registreren, belt u AddSignalR in Program.cs.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddSignalR();
Als u eindpunten wilt configureren SignalR, roept u MapHub aan, ook in Program.cs:
app.MapRazorPages();
app.MapHub<ChatHub>("/Chat");
app.Run();
Note
ASP.NET Core SignalR assembly's aan de serverzijde zijn nu geïnstalleerd met de .NET Core SDK. Zie SignalR assembly's in een gedeeld framework voor meer informatie.
Hubs maken en gebruiken
Maak een hub door een klasse te declareren die overerft van Hub. Voeg public methoden toe aan de klasse om ze aan te roepen vanaf clients:
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
=> await Clients.All.SendAsync("ReceiveMessage", user, message);
}
Note
Hubs zijn vergankelijk:
- Sla de status niet op in een eigenschap van de hubklasse. Elke aanroep van de hubmethode wordt uitgevoerd op een nieuw hub-exemplaar.
- Instantieer een hub niet rechtstreeks via afhankelijkheidsinjectie. Als u berichten wilt verzenden naar een client vanaf een andere locatie in uw toepassing, gebruikt u een
IHubContext. - Gebruik
awaitbij het aanroepen van asynchrone methoden die afhankelijk zijn van het in leven blijven van de hub. Een methode zoalsClients.All.SendAsync(...)kan bijvoorbeeld mislukken als deze wordt aangeroepen zonderawaiten de hubmethode voltooid wordt voordatSendAsyncklaar is.
Het Context-object
De Hub klasse bevat een Context eigenschap die de volgende eigenschappen bevat met informatie over de verbinding:
| Property | Description |
|---|---|
| ConnectionId | Hiermee haalt u de unieke id voor de verbinding op, toegewezen door SignalR. Er is één verbindings-id voor elke verbinding. |
| UserIdentifier | Hiermee haalt u de gebruikers-id op. Standaard gebruikt SignalR de ClaimTypes.NameIdentifier uit de ClaimsPrincipal die gekoppeld is aan de verbinding als de gebruikers-id. |
| User | Hiermee wordt de ClaimsPrincipal gekoppelde aan de huidige gebruiker. |
| Items | Hiermee haalt u een sleutel/waardeverzameling op die kan worden gebruikt voor het delen van gegevens binnen het bereik van deze verbinding. Gegevens kunnen worden opgeslagen in deze verzameling en blijven behouden voor de verbinding tussen verschillende hubmethodeaanroepen. |
| Features | Hiermee haalt u de verzameling functies op die beschikbaar zijn voor de verbinding. Deze verzameling is momenteel niet nodig in de meeste scenario's, dus deze is nog niet gedetailleerd gedocumenteerd. |
| ConnectionAborted | Hiermee wordt een CancellationToken bericht weergegeven wanneer de verbinding wordt afgebroken. |
Hub.Context bevat ook de volgende methoden:
| Method | Description |
|---|---|
| GetHttpContext | Retourneert de HttpContext voor de verbinding of null als de verbinding niet is gekoppeld aan een HTTP-aanvraag. Gebruik deze methode voor HTTP-verbindingen om informatie op te halen, zoals HTTP-headers en queryreeksen. |
| Abort | Hiermee wordt de verbinding afgebroken. |
Klantenobject
De Hub klasse bevat een Clients eigenschap die de volgende eigenschappen bevat voor communicatie tussen server en client:
| Property | Description |
|---|---|
| All | Roept een methode aan op alle verbonden clients |
| Caller | Roept een methode aan op de client die de hubmethode heeft aangeroepen |
| Others | Roept een methode aan op alle verbonden clients, met uitzondering van de client die de methode heeft aangeroepen |
Hub.Clients bevat ook de volgende methoden:
| Method | Description |
|---|---|
| AllExcept | Roept een methode aan op alle verbonden clients, met uitzondering van de opgegeven verbindingen |
| Client | Roept een methode aan op een specifieke verbonden client |
| Clients | Roept een methode aan op specifieke verbonden clients |
| Group | Roept een methode aan voor alle verbindingen in de opgegeven groep |
| GroupExcept | Roept een methode aan voor alle verbindingen in de opgegeven groep, met uitzondering van de opgegeven verbindingen |
| Groups | Roept een methode aan voor meerdere groepen verbindingen |
| OthersInGroup | Roept een methode aan voor een groep verbindingen, met uitzondering van de client die de hubmethode heeft aangeroepen |
| User | Roept een methode aan voor alle verbindingen die zijn gekoppeld aan een specifieke gebruiker |
| Users | Roept een methode aan voor alle verbindingen die zijn gekoppeld aan de opgegeven gebruikers |
Elke eigenschap of methode in de voorgaande tabellen retourneert een object met een SendAsync methode. De SendAsync methode ontvangt de naam van de clientmethode die moet worden aangeroepen en parameters.
Het object dat door de Client en Caller methoden wordt geretourneerd, bevat ook een InvokeAsync methode, die kan worden gebruikt om te wachten op een resultaat van de client.
Berichten verzenden naar klanten
Gebruik de eigenschappen van het Clients object om aanroepen te doen naar specifieke clients. In het volgende voorbeeld zijn er drie hubmethoden:
-
SendMessageverzendt een bericht naar alle verbonden clients met behulp vanClients.All. -
SendMessageToCallerstuurt een bericht terug naar de beller met behulp vanClients.Caller. -
SendMessageToGroupverzendt een bericht naar alle clients in deSignalR Usersgroep.
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);
Sterk getypeerde hubs
Een nadeel van het gebruik SendAsync is dat het afhankelijk is van een tekenreeks om de clientmethode op te geven die moet worden aangeroepen. Hierdoor blijft code open voor runtime-fouten als de naam van de methode onjuist is gespeld of ontbreekt in de client.
Een alternatief voor het gebruik SendAsync is om de Hub klasse sterk te typen met Hub<T>. In het volgende voorbeeld is de ChatHub clientmethode geëxtraheerd naar een interface genaamd IChatClient.
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Deze interface kan worden gebruikt om het voorgaande ChatHub voorbeeld te herstructureren zodat het sterk getypeerd is.
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);
}
Door gebruik van Hub<IChatClient> maakt het mogelijk compileertijdcontrole van de clientmethoden. Dit voorkomt problemen die worden veroorzaakt door het gebruik van tekenreeksen, omdat Hub<T> ze alleen toegang kunnen bieden tot de methoden die in de interface zijn gedefinieerd. Als u een sterk getypte Hub<T> gebruikt, wordt de mogelijkheid om SendAsync te gebruiken uitgeschakeld.
Note
Het Async achtervoegsel is niet verwijderd uit methodenamen. Tenzij een clientmethode is gedefinieerd met .on('MyMethodAsync'), gebruikt MyMethodAsync u deze niet als de naam.
Clientresultaten
Naast het aanroepen van clients, kan de server een resultaat aanvragen van een client. Hiervoor moet de server ISingleClientProxy.InvokeAsync gebruiken en moet de client een resultaat retourneren van de .On handler.
Er zijn twee manieren om de API op de server te gebruiken, het eerste is het aanroepen Client(...) of Caller op de Clients eigenschap in een Hub-methode:
public class ChatHub : Hub
{
public async Task<string> WaitForMessage(string connectionId)
{
var message = await Clients.Client(connectionId).InvokeAsync<string>(
"GetMessage");
return message;
}
}
De tweede manier is om Client(...) aan te roepen op een instantie van IHubContext<T>.
async Task SomeMethod(IHubContext<MyHub> context)
{
string result = await context.Clients.Client(connectionID).InvokeAsync<string>(
"GetMessage");
}
Sterk getypte hubs kunnen ook waarden retourneren van interfacemethoden:
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;
}
}
Clients retourneren resultaten in hun .On(...) handlers, zoals hieronder wordt weergegeven:
.NET-client
hubConnection.On("GetMessage", async () =>
{
Console.WriteLine("Enter message:");
var message = await Console.In.ReadLineAsync();
return message;
});
Typescript-client
hubConnection.on("GetMessage", async () => {
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("message");
}, 100);
});
return promise;
});
Java-client
hubConnection.onWithResult("GetMessage", () -> {
return Single.just("message");
});
De naam van een hubmethode wijzigen
Standaard is de naam van een serverhubmethode de naam van de .NET-methode. Als u dit standaardgedrag voor een specifieke methode wilt wijzigen, gebruikt u het kenmerk HubMethodName . De client moet deze naam gebruiken in plaats van de .NET-methodenaam bij het aanroepen van de methode:
[HubMethodName("SendMessageToUser")]
public async Task DirectMessage(string user, string message)
=> await Clients.User(user).SendAsync("ReceiveMessage", user, message);
Services in een hub injecteren
Hubconstructors kunnen services van DI accepteren als parameters, die kunnen worden opgeslagen in eigenschappen in de klasse voor gebruik in een hubmethode.
Bij het injecteren van meerdere services voor verschillende hubmethoden of als alternatieve manier om code te schrijven, kunnen hubmethoden ook services van DI accepteren. Standaard worden hubmethodeparameters geïnspecteerd en omgezet vanuit DI, indien mogelijk.
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);
}
}
Als impliciete resolutie van parameters van services niet gewenst is, schakelt u deze uit met DisableImplicitFromServicesParameters.
Als u expliciet wilt opgeven welke parameters worden omgezet vanuit DI in hubmethoden, gebruikt u de DisableImplicitFromServicesParameters optie en gebruikt u het [FromServices] kenmerk of een aangepast kenmerk dat wordt geïmplementeerd IFromServiceMetadata op de hubmethodeparameters die moeten worden omgezet vanuit 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);
}
}
Note
Deze functie maakt gebruik van IServiceProviderIsService, die optioneel wordt geïmplementeerd door DI-implementaties. Als de DI-container van de app deze functie niet ondersteunt, wordt het injecteren van services in hubmethoden niet ondersteund.
Ondersteuning voor gekeyde diensten in afhankelijkheidsinjectie
Keyed Services verwijst naar een mechanisme voor het registreren en ophalen van afhankelijkheidsinjectieservices (DI) met behulp van sleutels. Een service is gekoppeld aan een sleutel door AddKeyedSingleton (of AddKeyedScoped of AddKeyedTransient) aan te roepen om deze te registreren. Open een geregistreerde service door de sleutel op te geven met het kenmerk [FromKeyedServices]. De volgende code laat zien hoe u sleutelservices gebruikt:
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"));
}
}
Gebeurtenissen voor een verbinding verwerken
De SignalR Hubs API biedt de OnConnectedAsync en OnDisconnectedAsync virtuele methoden om verbindingen te beheren en bij te houden. Overschrijf de OnConnectedAsync virtuele methode om acties uit te voeren wanneer een client verbinding maakt met de hub, zoals het toevoegen aan een groep:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Overschrijf de OnDisconnectedAsync virtuele methode om acties uit te voeren wanneer een client de verbinding verbreekt. Als de cliënt de verbinding opzettelijk verbreekt, bijvoorbeeld door te bellen connection.stop(), wordt de exception-parameter ingesteld op null. Als de client echter wordt verbroken vanwege een fout, zoals een netwerkfout, bevat de exception parameter een uitzondering die de fout beschrijft:
public override async Task OnDisconnectedAsync(Exception? exception)
{
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync hoeft niet te worden aangeroepen in OnDisconnectedAsync, het wordt automatisch voor u afgehandeld.
Afhandeling van fouten
Uitzonderingen die worden gegenereerd in hubmethoden, worden verzonden naar de client die de methode heeft aangeroepen. Op de JavaScript-client retourneert de invoke methode een JavaScript Promise. Clients kunnen een catch handler koppelen aan de geretourneerde belofte of gebruiken try/catchom async/await uitzonderingen af te handelen:
try {
await connection.invoke("SendMessage", user, message);
} catch (err) {
console.error(err);
}
Verbindingen worden niet gesloten wanneer een hub een uitzondering genereert. Retourneert standaard SignalR een algemeen foutbericht naar de client, zoals wordt weergegeven in het volgende voorbeeld:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'SendMessage' on the server.
Onverwachte uitzonderingen bevatten vaak gevoelige informatie, zoals de naam van een databaseserver in een uitzondering die wordt geactiveerd wanneer de databaseverbinding mislukt. SignalR bevat deze gedetailleerde foutberichten niet standaard als een beveiligingsmaatregel. Zie Beveiligingsoverwegingen in ASP.NET Core SignalRvoor meer informatie over waarom uitzonderingsdetails worden onderdrukt.
Als een uitzonderlijke voorwaarde moet worden doorgegeven aan de client, gebruikt u de HubException klasse. Als er een HubException wordt gegenereerd in een hubmethode, SignalRverzendt u het volledige uitzonderingsbericht naar de client, ongewijzigd:
public Task ThrowException()
=> throw new HubException("This error will be sent to the client!");
Note
SignalR verzendt alleen de Message eigenschap van de uitzondering naar de client. De stacktrace en andere eigenschappen van de uitzondering zijn niet beschikbaar voor de client.
Aanvullende bronnen
Door Rachel Appel en Kevin Griffin
Met de SignalR Hubs-API kunnen verbonden clients methoden op de server aanroepen, waardoor realtime communicatie wordt vergemakkelijkt. De server definieert methoden die door de client worden aangeroepen en de client definieert methoden die door de server worden aangeroepen. SignalR maakt ook indirecte client-naar-client-communicatie mogelijk, altijd gemediateerd door de SignalR Hub, zodat berichten kunnen worden verzonden tussen afzonderlijke clients, groepen of naar alle verbonden clients. SignalR zorgt ervoor dat realtime client-naar-server- en server-naar-clientcommunicatie mogelijk is.
Hubs configureren SignalR
Om de vereiste services voor SignalR hubs te registreren, belt u AddSignalR in Program.cs.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddSignalR();
Als u eindpunten wilt configureren SignalR, roept u MapHub aan, ook in Program.cs:
app.MapRazorPages();
app.MapHub<ChatHub>("/Chat");
app.Run();
Note
ASP.NET Core SignalR assembly's aan de serverzijde zijn nu geïnstalleerd met de .NET Core SDK. Zie SignalR assembly's in een gedeeld framework voor meer informatie.
Hubs maken en gebruiken
Maak een hub door een klasse te declareren die overerft van Hub. Voeg public methoden toe aan de klasse om ze aan te roepen vanaf clients:
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
=> await Clients.All.SendAsync("ReceiveMessage", user, message);
}
Note
Hubs zijn vergankelijk:
- Sla de status niet op in een eigenschap van de hubklasse. Elke aanroep van de hubmethode wordt uitgevoerd op een nieuw hub-exemplaar.
- Instantieer een hub niet rechtstreeks via afhankelijkheidsinjectie. Als u berichten wilt verzenden naar een client vanaf een andere locatie in uw toepassing, gebruikt u een
IHubContext. - Gebruik
awaitbij het aanroepen van asynchrone methoden die afhankelijk zijn van het in leven blijven van de hub. Een methode zoalsClients.All.SendAsync(...)kan bijvoorbeeld mislukken als deze wordt aangeroepen zonderawaiten de hubmethode voltooid wordt voordatSendAsyncklaar is.
Het Context-object
De Hub klasse bevat een Context eigenschap die de volgende eigenschappen bevat met informatie over de verbinding:
| Property | Description |
|---|---|
| ConnectionId | Hiermee haalt u de unieke id voor de verbinding op, toegewezen door SignalR. Er is één verbindings-id voor elke verbinding. |
| UserIdentifier | Hiermee haalt u de gebruikers-id op. Standaard gebruikt SignalR de ClaimTypes.NameIdentifier uit de ClaimsPrincipal die gekoppeld is aan de verbinding als de gebruikers-id. |
| User | Hiermee wordt de ClaimsPrincipal gekoppelde aan de huidige gebruiker. |
| Items | Hiermee haalt u een sleutel/waardeverzameling op die kan worden gebruikt voor het delen van gegevens binnen het bereik van deze verbinding. Gegevens kunnen worden opgeslagen in deze verzameling en blijven behouden voor de verbinding tussen verschillende hubmethodeaanroepen. |
| Features | Hiermee haalt u de verzameling functies op die beschikbaar zijn voor de verbinding. Deze verzameling is momenteel niet nodig in de meeste scenario's, dus deze is nog niet gedetailleerd gedocumenteerd. |
| ConnectionAborted | Hiermee wordt een CancellationToken bericht weergegeven wanneer de verbinding wordt afgebroken. |
Hub.Context bevat ook de volgende methoden:
| Method | Description |
|---|---|
| GetHttpContext | Retourneert de HttpContext voor de verbinding of null als de verbinding niet is gekoppeld aan een HTTP-aanvraag. Gebruik deze methode voor HTTP-verbindingen om informatie op te halen, zoals HTTP-headers en queryreeksen. |
| Abort | Hiermee wordt de verbinding afgebroken. |
Klantenobject
De Hub klasse bevat een Clients eigenschap die de volgende eigenschappen bevat voor communicatie tussen server en client:
| Property | Description |
|---|---|
| All | Roept een methode aan op alle verbonden clients |
| Caller | Roept een methode aan op de client die de hubmethode heeft aangeroepen |
| Others | Roept een methode aan op alle verbonden clients, met uitzondering van de client die de methode heeft aangeroepen |
Hub.Clients bevat ook de volgende methoden:
| Method | Description |
|---|---|
| AllExcept | Roept een methode aan op alle verbonden clients, met uitzondering van de opgegeven verbindingen |
| Client | Roept een methode aan op een specifieke verbonden client |
| Clients | Roept een methode aan op specifieke verbonden clients |
| Group | Roept een methode aan voor alle verbindingen in de opgegeven groep |
| GroupExcept | Roept een methode aan voor alle verbindingen in de opgegeven groep, met uitzondering van de opgegeven verbindingen |
| Groups | Roept een methode aan voor meerdere groepen verbindingen |
| OthersInGroup | Roept een methode aan voor een groep verbindingen, met uitzondering van de client die de hubmethode heeft aangeroepen |
| User | Roept een methode aan voor alle verbindingen die zijn gekoppeld aan een specifieke gebruiker |
| Users | Roept een methode aan voor alle verbindingen die zijn gekoppeld aan de opgegeven gebruikers |
Elke eigenschap of methode in de voorgaande tabellen retourneert een object met een SendAsync methode. De SendAsync methode ontvangt de naam van de clientmethode die moet worden aangeroepen en parameters.
Het object dat door de Client en Caller methoden wordt geretourneerd, bevat ook een InvokeAsync methode, die kan worden gebruikt om te wachten op een resultaat van de client.
Berichten verzenden naar klanten
Gebruik de eigenschappen van het Clients object om aanroepen te doen naar specifieke clients. In het volgende voorbeeld zijn er drie hubmethoden:
-
SendMessageverzendt een bericht naar alle verbonden clients met behulp vanClients.All. -
SendMessageToCallerstuurt een bericht terug naar de beller met behulp vanClients.Caller. -
SendMessageToGroupverzendt een bericht naar alle clients in deSignalR Usersgroep.
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);
Sterk getypeerde hubs
Een nadeel van het gebruik SendAsync is dat het afhankelijk is van een tekenreeks om de clientmethode op te geven die moet worden aangeroepen. Hierdoor blijft code open voor runtime-fouten als de naam van de methode onjuist is gespeld of ontbreekt in de client.
Een alternatief voor het gebruik SendAsync is om de Hub klasse sterk te typen met Hub<T>. In het volgende voorbeeld is de ChatHub clientmethode geëxtraheerd naar een interface genaamd IChatClient.
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Deze interface kan worden gebruikt om het voorgaande ChatHub voorbeeld te herstructureren zodat het sterk getypeerd is.
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);
}
Door gebruik van Hub<IChatClient> maakt het mogelijk compileertijdcontrole van de clientmethoden. Dit voorkomt problemen die worden veroorzaakt door het gebruik van tekenreeksen, omdat Hub<T> ze alleen toegang kunnen bieden tot de methoden die in de interface zijn gedefinieerd. Als u een sterk getypte Hub<T> gebruikt, wordt de mogelijkheid om SendAsync te gebruiken uitgeschakeld.
Note
Het Async achtervoegsel is niet verwijderd uit methodenamen. Tenzij een clientmethode is gedefinieerd met .on('MyMethodAsync'), gebruikt MyMethodAsync u deze niet als de naam.
Clientresultaten
Naast het aanroepen van clients, kan de server een resultaat aanvragen van een client. Hiervoor moet de server ISingleClientProxy.InvokeAsync gebruiken en moet de client een resultaat retourneren van de .On handler.
Er zijn twee manieren om de API op de server te gebruiken, het eerste is het aanroepen Client(...) of Caller op de Clients eigenschap in een Hub-methode:
public class ChatHub : Hub
{
public async Task<string> WaitForMessage(string connectionId)
{
var message = await Clients.Client(connectionId).InvokeAsync<string>(
"GetMessage");
return message;
}
}
De tweede manier is om Client(...) aan te roepen op een instantie van IHubContext<T>.
async Task SomeMethod(IHubContext<MyHub> context)
{
string result = await context.Clients.Client(connectionID).InvokeAsync<string>(
"GetMessage");
}
Sterk getypte hubs kunnen ook waarden retourneren van interfacemethoden:
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;
}
}
Clients retourneren resultaten in hun .On(...) handlers, zoals hieronder wordt weergegeven:
.NET-client
hubConnection.On("GetMessage", async () =>
{
Console.WriteLine("Enter message:");
var message = await Console.In.ReadLineAsync();
return message;
});
Typescript-client
hubConnection.on("GetMessage", async () => {
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("message");
}, 100);
});
return promise;
});
Java-client
hubConnection.onWithResult("GetMessage", () -> {
return Single.just("message");
});
De naam van een hubmethode wijzigen
Standaard is de naam van een serverhubmethode de naam van de .NET-methode. Als u dit standaardgedrag voor een specifieke methode wilt wijzigen, gebruikt u het kenmerk HubMethodName . De client moet deze naam gebruiken in plaats van de .NET-methodenaam bij het aanroepen van de methode:
[HubMethodName("SendMessageToUser")]
public async Task DirectMessage(string user, string message)
=> await Clients.User(user).SendAsync("ReceiveMessage", user, message);
Services in een hub injecteren
Hubconstructors kunnen services van DI accepteren als parameters, die kunnen worden opgeslagen in eigenschappen in de klasse voor gebruik in een hubmethode.
Bij het injecteren van meerdere services voor verschillende hubmethoden of als alternatieve manier om code te schrijven, kunnen hubmethoden ook services van DI accepteren. Standaard worden hubmethodeparameters geïnspecteerd en omgezet vanuit DI, indien mogelijk.
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);
}
}
Als impliciete resolutie van parameters van services niet gewenst is, schakelt u deze uit met DisableImplicitFromServicesParameters.
Als u expliciet wilt opgeven welke parameters worden omgezet vanuit DI in hubmethoden, gebruikt u de DisableImplicitFromServicesParameters optie en gebruikt u het [FromServices] kenmerk of een aangepast kenmerk dat wordt geïmplementeerd IFromServiceMetadata op de hubmethodeparameters die moeten worden omgezet vanuit 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);
}
}
Note
Deze functie maakt gebruik van IServiceProviderIsService, die optioneel wordt geïmplementeerd door DI-implementaties. Als de DI-container van de app deze functie niet ondersteunt, wordt het injecteren van services in hubmethoden niet ondersteund.
Gebeurtenissen voor een verbinding verwerken
De SignalR Hubs API biedt de OnConnectedAsync en OnDisconnectedAsync virtuele methoden om verbindingen te beheren en bij te houden. Overschrijf de OnConnectedAsync virtuele methode om acties uit te voeren wanneer een client verbinding maakt met de hub, zoals het toevoegen aan een groep:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Overschrijf de OnDisconnectedAsync virtuele methode om acties uit te voeren wanneer een client de verbinding verbreekt. Als de cliënt de verbinding opzettelijk verbreekt, bijvoorbeeld door te bellen connection.stop(), wordt de exception-parameter ingesteld op null. Als de client echter wordt verbroken vanwege een fout, zoals een netwerkfout, bevat de exception parameter een uitzondering die de fout beschrijft:
public override async Task OnDisconnectedAsync(Exception? exception)
{
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync hoeft niet aangeroepen te worden in OnDisconnectedAsync, het wordt automatisch voor u afgehandeld.
Afhandeling van fouten
Uitzonderingen die worden gegenereerd in hubmethoden, worden verzonden naar de client die de methode heeft aangeroepen. Op de JavaScript-client retourneert de invoke methode een JavaScript Promise. Clients kunnen een catch handler koppelen aan de geretourneerde belofte of gebruiken try/catchom async/await uitzonderingen af te handelen:
try {
await connection.invoke("SendMessage", user, message);
} catch (err) {
console.error(err);
}
Verbindingen worden niet gesloten wanneer een hub een uitzondering genereert. Retourneert standaard SignalR een algemeen foutbericht naar de client, zoals wordt weergegeven in het volgende voorbeeld:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'SendMessage' on the server.
Onverwachte uitzonderingen bevatten vaak gevoelige informatie, zoals de naam van een databaseserver in een uitzondering die wordt geactiveerd wanneer de databaseverbinding mislukt. SignalR bevat deze gedetailleerde foutberichten niet standaard als een beveiligingsmaatregel. Zie Beveiligingsoverwegingen in ASP.NET Core SignalRvoor meer informatie over waarom uitzonderingsdetails worden onderdrukt.
Als een uitzonderlijke voorwaarde moet worden doorgegeven aan de client, gebruikt u de HubException klasse. Als er een HubException wordt gegenereerd in een hubmethode, SignalRverzendt u het volledige uitzonderingsbericht naar de client, ongewijzigd:
public Task ThrowException()
=> throw new HubException("This error will be sent to the client!");
Note
SignalR verzendt alleen de Message eigenschap van de uitzondering naar de client. De stacktrace en andere eigenschappen van de uitzondering zijn niet beschikbaar voor de client.
Aanvullende bronnen
Door Rachel Appel en Kevin Griffin
Met de SignalR Hubs-API kunnen verbonden clients methoden op de server aanroepen, waardoor realtime communicatie wordt vergemakkelijkt. De server definieert methoden die door de client worden aangeroepen en de client definieert methoden die door de server worden aangeroepen. SignalR maakt ook indirecte client-naar-client-communicatie mogelijk, altijd gemediateerd door de SignalR Hub, zodat berichten kunnen worden verzonden tussen afzonderlijke clients, groepen of naar alle verbonden clients. SignalR zorgt ervoor dat realtime client-naar-server- en server-naar-clientcommunicatie mogelijk is.
Hubs configureren SignalR
Om de vereiste services voor SignalR hubs te registreren, belt u AddSignalR in Program.cs.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddSignalR();
Als u eindpunten wilt configureren SignalR, roept u MapHub aan, ook in Program.cs:
app.MapRazorPages();
app.MapHub<ChatHub>("/Chat");
app.Run();
Note
ASP.NET Core SignalR assembly's aan de serverzijde zijn nu geïnstalleerd met de .NET Core SDK. Zie SignalR assembly's in een gedeeld framework voor meer informatie.
Hubs maken en gebruiken
Maak een hub door een klasse te declareren die overerft van Hub. Voeg public methoden toe aan de klasse om ze aan te roepen vanaf clients:
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
=> await Clients.All.SendAsync("ReceiveMessage", user, message);
}
Note
Hubs zijn vergankelijk:
- Sla de status niet op in een eigenschap van de hubklasse. Elke aanroep van de hubmethode wordt uitgevoerd op een nieuw hub-exemplaar.
- Instantieer een hub niet rechtstreeks via afhankelijkheidsinjectie. Als u berichten wilt verzenden naar een client vanaf een andere locatie in uw toepassing, gebruikt u een
IHubContext. - Gebruik
awaitbij het aanroepen van asynchrone methoden die afhankelijk zijn van het in leven blijven van de hub. Een methode zoalsClients.All.SendAsync(...)kan bijvoorbeeld mislukken als deze wordt aangeroepen zonderawaiten de hubmethode voltooid wordt voordatSendAsyncklaar is.
Het Context-object
De Hub klasse bevat een Context eigenschap die de volgende eigenschappen bevat met informatie over de verbinding:
| Property | Description |
|---|---|
| ConnectionId | Hiermee haalt u de unieke id voor de verbinding op, toegewezen door SignalR. Er is één verbindings-id voor elke verbinding. |
| UserIdentifier | Hiermee haalt u de gebruikers-id op. Standaard gebruikt SignalR de ClaimTypes.NameIdentifier uit de ClaimsPrincipal die gekoppeld is aan de verbinding als de gebruikers-id. |
| User | Hiermee wordt de ClaimsPrincipal gekoppelde aan de huidige gebruiker. |
| Items | Hiermee haalt u een sleutel/waardeverzameling op die kan worden gebruikt voor het delen van gegevens binnen het bereik van deze verbinding. Gegevens kunnen worden opgeslagen in deze verzameling en blijven behouden voor de verbinding tussen verschillende hubmethodeaanroepen. |
| Features | Hiermee haalt u de verzameling functies op die beschikbaar zijn voor de verbinding. Deze verzameling is momenteel niet nodig in de meeste scenario's, dus deze is nog niet gedetailleerd gedocumenteerd. |
| ConnectionAborted | Hiermee wordt een CancellationToken bericht weergegeven wanneer de verbinding wordt afgebroken. |
Hub.Context bevat ook de volgende methoden:
| Method | Description |
|---|---|
| GetHttpContext | Retourneert de HttpContext voor de verbinding of null als de verbinding niet is gekoppeld aan een HTTP-aanvraag. Gebruik deze methode voor HTTP-verbindingen om informatie op te halen, zoals HTTP-headers en queryreeksen. |
| Abort | Hiermee wordt de verbinding afgebroken. |
Klantenobject
De Hub klasse bevat een Clients eigenschap die de volgende eigenschappen bevat voor communicatie tussen server en client:
| Property | Description |
|---|---|
| All | Roept een methode aan op alle verbonden clients |
| Caller | Roept een methode aan op de client die de hubmethode heeft aangeroepen |
| Others | Roept een methode aan op alle verbonden clients, met uitzondering van de client die de methode heeft aangeroepen |
Hub.Clients bevat ook de volgende methoden:
| Method | Description |
|---|---|
| AllExcept | Roept een methode aan op alle verbonden clients, met uitzondering van de opgegeven verbindingen |
| Client | Roept een methode aan op een specifieke verbonden client |
| Clients | Roept een methode aan op specifieke verbonden clients |
| Group | Roept een methode aan voor alle verbindingen in de opgegeven groep |
| GroupExcept | Roept een methode aan voor alle verbindingen in de opgegeven groep, met uitzondering van de opgegeven verbindingen |
| Groups | Roept een methode aan voor meerdere groepen verbindingen |
| OthersInGroup | Roept een methode aan voor een groep verbindingen, met uitzondering van de client die de hubmethode heeft aangeroepen |
| User | Roept een methode aan voor alle verbindingen die zijn gekoppeld aan een specifieke gebruiker |
| Users | Roept een methode aan voor alle verbindingen die zijn gekoppeld aan de opgegeven gebruikers |
Elke eigenschap of methode in de voorgaande tabellen retourneert een object met een SendAsync methode. De SendAsync methode ontvangt de naam van de clientmethode die moet worden aangeroepen en parameters.
Berichten verzenden naar klanten
Gebruik de eigenschappen van het Clients object om aanroepen te doen naar specifieke clients. In het volgende voorbeeld zijn er drie hubmethoden:
-
SendMessageverzendt een bericht naar alle verbonden clients met behulp vanClients.All. -
SendMessageToCallerstuurt een bericht terug naar de beller met behulp vanClients.Caller. -
SendMessageToGroupverzendt een bericht naar alle clients in deSignalR Usersgroep.
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);
Sterk getypeerde hubs
Een nadeel van het gebruik SendAsync is dat het afhankelijk is van een tekenreeks om de clientmethode op te geven die moet worden aangeroepen. Hierdoor blijft code open voor runtime-fouten als de naam van de methode onjuist is gespeld of ontbreekt in de client.
Een alternatief voor het gebruik SendAsync is om de Hub klasse sterk te typen met Hub<T>. In het volgende voorbeeld is de ChatHub clientmethode geëxtraheerd naar een interface genaamd IChatClient.
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Deze interface kan worden gebruikt om het voorgaande ChatHub voorbeeld te herstructureren zodat het sterk getypeerd is.
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);
}
Door gebruik van Hub<IChatClient> maakt het mogelijk compileertijdcontrole van de clientmethoden. Dit voorkomt problemen die worden veroorzaakt door het gebruik van tekenreeksen, omdat Hub<T> ze alleen toegang kunnen bieden tot de methoden die in de interface zijn gedefinieerd. Als u een sterk getypte Hub<T> gebruikt, wordt de mogelijkheid om SendAsync te gebruiken uitgeschakeld.
Note
Het Async achtervoegsel is niet verwijderd uit methodenamen. Tenzij een clientmethode is gedefinieerd met .on('MyMethodAsync'), gebruikt MyMethodAsync u deze niet als de naam.
De naam van een hubmethode wijzigen
Standaard is de naam van een serverhubmethode de naam van de .NET-methode. Als u dit standaardgedrag voor een specifieke methode wilt wijzigen, gebruikt u het kenmerk HubMethodName . De client moet deze naam gebruiken in plaats van de .NET-methodenaam bij het aanroepen van de methode:
[HubMethodName("SendMessageToUser")]
public async Task DirectMessage(string user, string message)
=> await Clients.User(user).SendAsync("ReceiveMessage", user, message);
Gebeurtenissen voor een verbinding verwerken
De SignalR Hubs API biedt de OnConnectedAsync en OnDisconnectedAsync virtuele methoden om verbindingen te beheren en bij te houden. Overschrijf de OnConnectedAsync virtuele methode om acties uit te voeren wanneer een client verbinding maakt met de hub, zoals het toevoegen aan een groep:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Overschrijf de OnDisconnectedAsync virtuele methode om acties uit te voeren wanneer een client de verbinding verbreekt. Als de cliënt de verbinding opzettelijk verbreekt, bijvoorbeeld door te bellen connection.stop(), wordt de exception-parameter ingesteld op null. Als de client echter wordt verbroken vanwege een fout, zoals een netwerkfout, bevat de exception parameter een uitzondering die de fout beschrijft:
public override async Task OnDisconnectedAsync(Exception? exception)
{
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync hoeft niet aangeroepen te worden in OnDisconnectedAsync, het wordt automatisch voor u afgehandeld.
Afhandeling van fouten
Uitzonderingen die worden gegenereerd in hubmethoden, worden verzonden naar de client die de methode heeft aangeroepen. Op de JavaScript-client retourneert de invoke methode een JavaScript Promise. Clients kunnen een catch handler koppelen aan de geretourneerde belofte of gebruiken try/catchom async/await uitzonderingen af te handelen:
try {
await connection.invoke("SendMessage", user, message);
} catch (err) {
console.error(err);
}
Verbindingen worden niet gesloten wanneer een hub een uitzondering genereert. Retourneert standaard SignalR een algemeen foutbericht naar de client, zoals wordt weergegeven in het volgende voorbeeld:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'SendMessage' on the server.
Onverwachte uitzonderingen bevatten vaak gevoelige informatie, zoals de naam van een databaseserver in een uitzondering die wordt geactiveerd wanneer de databaseverbinding mislukt. SignalR bevat deze gedetailleerde foutberichten niet standaard als een beveiligingsmaatregel. Zie Beveiligingsoverwegingen in ASP.NET Core SignalRvoor meer informatie over waarom uitzonderingsdetails worden onderdrukt.
Als een uitzonderlijke voorwaarde moet worden doorgegeven aan de client, gebruikt u de HubException klasse. Als er een HubException wordt gegenereerd in een hubmethode, SignalRverzendt u het volledige uitzonderingsbericht naar de client, ongewijzigd:
public Task ThrowException()
=> throw new HubException("This error will be sent to the client!");
Note
SignalR verzendt alleen de Message eigenschap van de uitzondering naar de client. De stacktrace en andere eigenschappen van de uitzondering zijn niet beschikbaar voor de client.
Aanvullende bronnen
Door Rachel Appel en Kevin Griffin
Voorbeeldcode weergeven of downloaden(hoe te downloaden)
Wat is een SignalR hub?
Met de SignalR Hubs-API kunnen verbonden clients methoden op de server aanroepen, waardoor realtime communicatie wordt vergemakkelijkt. De server definieert methoden die door de client worden aangeroepen en de client definieert methoden die door de server worden aangeroepen. SignalR maakt ook indirecte client-naar-client-communicatie mogelijk, altijd gemediateerd door de SignalR Hub, zodat berichten kunnen worden verzonden tussen afzonderlijke clients, groepen of naar alle verbonden clients. SignalR zorgt ervoor dat realtime client-naar-server- en server-naar-clientcommunicatie mogelijk is.
Hubs configureren SignalR
Voor de SignalR middleware zijn enkele services vereist die zijn geconfigureerd door het aanroepen van AddSignalR:
services.AddSignalR();
Wanneer u functionaliteit toevoegt SignalR aan een ASP.NET Core-app, moet u routes instellen SignalR door de callback van MapHub de Startup.Configure methode aan te roepenUseEndpoints:
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>("/chathub");
});
Note
ASP.NET Core SignalR assembly's aan de serverzijde zijn nu geïnstalleerd met de .NET Core SDK. Zie SignalR assembly's in een gedeeld framework voor meer informatie.
Hubs maken en gebruiken
Maak een hub door een klasse te declareren van Huben openbare methoden eraan toe te voegen. Clients kunnen methoden aanroepen die zijn gedefinieerd als public:
public class ChatHub : Hub
{
public Task SendMessage(string user, string message)
{
return Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
U kunt een retourtype en parameters opgeven, inclusief complexe typen en matrices, zoals in elke C#-methode. SignalR verwerkt de serialisatie en deserialisatie van complexe objecten en matrices in uw parameters en retourwaarden.
Note
Hubs zijn tijdelijk:
- Sla de status niet op in een eigenschap in de hubklasse. Elke hubmethode-aanroep wordt uitgevoerd op een nieuw hub-exemplaar.
- Instantieer een hub niet rechtstreeks via afhankelijkheidsinjectie. Als u berichten wilt verzenden naar een client vanaf een andere locatie in uw toepassing, gebruikt u een
IHubContext. - Gebruik
awaitbij het aanroepen van asynchrone methoden die afhankelijk zijn van het in leven blijven van de hub. Een methode zoalsClients.All.SendAsync(...)kan bijvoorbeeld mislukken als deze wordt aangeroepen zonderawaiten de hubmethode voltooid wordt voordatSendAsyncklaar is.
Het Context-object
De Hub klasse heeft een Context eigenschap die de volgende eigenschappen bevat met informatie over de verbinding:
| Property | Description |
|---|---|
| ConnectionId | Hiermee haalt u de unieke id voor de verbinding op, toegewezen door SignalR. Er is één verbindings-id voor elke verbinding. |
| UserIdentifier | Hiermee haalt u de gebruikers-id op. Standaard gebruikt SignalR de ClaimTypes.NameIdentifier uit de ClaimsPrincipal die gekoppeld is aan de verbinding als de gebruikers-id. |
| User | Hiermee wordt de ClaimsPrincipal gekoppelde aan de huidige gebruiker. |
| Items | Hiermee haalt u een sleutel/waardeverzameling op die kan worden gebruikt voor het delen van gegevens binnen het bereik van deze verbinding. Gegevens kunnen worden opgeslagen in deze verzameling en blijven behouden voor de verbinding tussen verschillende hubmethodeaanroepen. |
| Features | Hiermee haalt u de verzameling functies op die beschikbaar zijn voor de verbinding. Deze verzameling is momenteel niet nodig in de meeste scenario's, dus deze is nog niet gedetailleerd gedocumenteerd. |
| ConnectionAborted | Hiermee wordt een CancellationToken bericht weergegeven wanneer de verbinding wordt afgebroken. |
Hub.Context bevat ook de volgende methoden:
| Method | Description |
|---|---|
| GetHttpContext | Retourneert de HttpContext voor de verbinding of null als de verbinding niet is gekoppeld aan een HTTP-aanvraag. Voor HTTP-verbindingen kunt u deze methode gebruiken om informatie op te halen, zoals HTTP-headers en queryreeksen. |
| Abort | Hiermee wordt de verbinding afgebroken. |
Klantenobject
De Hub klasse heeft een Clients eigenschap die de volgende eigenschappen bevat voor communicatie tussen server en client:
| Property | Description |
|---|---|
| All | Roept een methode aan op alle verbonden clients |
| Caller | Roept een methode aan op de client die de hubmethode heeft aangeroepen |
| Others | Roept een methode aan op alle verbonden clients, met uitzondering van de client die de methode heeft aangeroepen |
Hub.Clients bevat ook de volgende methoden:
| Method | Description |
|---|---|
| AllExcept | Roept een methode aan op alle verbonden clients, met uitzondering van de opgegeven verbindingen |
| Client | Roept een methode aan op een specifieke verbonden client |
| Clients | Roept een methode aan op specifieke verbonden clients |
| Group | Roept een methode aan voor alle verbindingen in de opgegeven groep |
| GroupExcept | Roept een methode aan voor alle verbindingen in de opgegeven groep, met uitzondering van de opgegeven verbindingen |
| Groups | Roept een methode aan voor meerdere groepen verbindingen |
| OthersInGroup | Roept een methode aan voor een groep verbindingen, met uitzondering van de client die de hubmethode heeft aangeroepen |
| User | Roept een methode aan voor alle verbindingen die zijn gekoppeld aan een specifieke gebruiker |
| Users | Roept een methode aan voor alle verbindingen die zijn gekoppeld aan de opgegeven gebruikers |
Elke eigenschap of methode in de voorgaande tabellen retourneert een object met een SendAsync methode. Met SendAsync de methode kunt u de naam en parameters van de clientmethode opgeven die u wilt aanroepen.
Berichten verzenden naar klanten
Gebruik de eigenschappen van het Clients object om aanroepen te doen naar specifieke clients. In het volgende voorbeeld zijn er drie Hub-methoden:
-
SendMessageverzendt een bericht naar alle verbonden clients met behulp vanClients.All. -
SendMessageToCallerstuurt een bericht terug naar de beller met behulp vanClients.Caller. -
SendMessageToGroupverzendt een bericht naar alle clients in deSignalR Usersgroep.
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);
}
Sterk getypeerde hubs
Een nadeel van het gebruik SendAsync is dat het afhankelijk is van een magic-tekenreeks om de clientmethode op te geven die moet worden aangeroepen. Hierdoor blijft code open voor runtime-fouten als de naam van de methode onjuist is gespeld of ontbreekt in de client.
Een alternatief voor het gebruik SendAsync is om het Hub sterk te typen met Hub<T>. In het volgende voorbeeld zijn de clientmethoden geëxtraheerd in een interface met de ChatHub naam IChatClient.
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Deze interface kan worden gebruikt om het voorgaande ChatHub voorbeeld te herstructureren:
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);
}
}
Door gebruik van Hub<IChatClient> maakt het mogelijk compileertijdcontrole van de clientmethoden. Dit voorkomt problemen die worden veroorzaakt door het gebruik van magic-tekenreeksen, omdat Hub<T> ze alleen toegang kunnen bieden tot de methoden die in de interface zijn gedefinieerd.
Als u een sterk getypte Hub<T> gebruikt, wordt de mogelijkheid om SendAsync te gebruiken uitgeschakeld. Methoden die op de interface zijn gedefinieerd, kunnen nog steeds als asynchroon worden gedefinieerd. In feite moet elk van deze methoden een Task. Omdat het een interface is, gebruikt u het async trefwoord niet. Voorbeeld:
public interface IClient
{
Task ClientMethod();
}
Note
Het Async achtervoegsel is niet verwijderd uit de naam van de methode. Tenzij uw clientmethode is gedefinieerd met .on('MyMethodAsync'), moet u deze niet gebruiken MyMethodAsync als een naam.
De naam van een hubmethode wijzigen
Standaard is de naam van een serverhubmethode de naam van de .NET-methode. U kunt echter het kenmerk HubMethodName gebruiken om deze standaardinstelling te wijzigen en handmatig een naam voor de methode op te geven. De client moet deze naam gebruiken in plaats van de naam van de .NET-methode bij het aanroepen van de methode:
[HubMethodName("SendMessageToUser")]
public Task DirectMessage(string user, string message)
{
return Clients.User(user).SendAsync("ReceiveMessage", user, message);
}
Gebeurtenissen voor een verbinding verwerken
De SignalR Hubs API biedt de OnConnectedAsync en OnDisconnectedAsync virtuele methoden om verbindingen te beheren en bij te houden. Overschrijf de OnConnectedAsync virtuele methode om acties uit te voeren wanneer een client verbinding maakt met de hub, zoals het toevoegen aan een groep:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Overschrijf de OnDisconnectedAsync virtuele methode om acties uit te voeren wanneer een client de verbinding verbreekt. Als de client opzettelijk wordt verbroken (door bijvoorbeeld aan te roepenconnection.stop()), is exceptionde null parameter. Als de verbinding met de client echter is verbroken vanwege een fout (zoals een netwerkfout), bevat de exception parameter een uitzondering waarin de fout wordt beschreven:
public override async Task OnDisconnectedAsync(Exception exception)
{
await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", "I", "disconnect");
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync hoeft niet aangeroepen te worden in OnDisconnectedAsync, het wordt automatisch voor u afgehandeld.
Warning
Beveiligingswaarschuwing: exposeren ConnectionId kan leiden tot schadelijke imitatie als de SignalR server- of clientversie ASP.NET Core 2.2 of eerder is.
Afhandeling van fouten
Uitzonderingen die zijn opgetreden in uw hubmethoden, worden verzonden naar de client die de methode heeft aangeroepen. Op de JavaScript-client retourneert de invoke methode een JavaScript Promise. Wanneer de client een fout ontvangt met een handler die is gekoppeld aan de belofte, catchwordt deze aangeroepen en doorgegeven als een JavaScript-object Error :
connection.invoke("SendMessage", user, message).catch(err => console.error(err));
Als uw Hub een uitzondering genereert, worden verbindingen niet gesloten. Retourneert standaard SignalR een algemeen foutbericht naar de client. Voorbeeld:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'MethodName' on the server.
Onverwachte uitzonderingen bevatten vaak gevoelige informatie, zoals de naam van een databaseserver in een uitzondering die wordt geactiveerd wanneer de databaseverbinding mislukt. SignalR bevat deze gedetailleerde foutberichten niet standaard als een beveiligingsmaatregel. Zie Beveiligingsoverwegingen in ASP.NET Core SignalRvoor meer informatie over waarom uitzonderingsdetails worden onderdrukt.
Als u een uitzonderlijke voorwaarde hebt die u wilt doorgeven aan de client, kunt u de HubException klasse gebruiken. Als u een HubException vanuit uw hubmethode gooit, SignalRstuurt het hele bericht naar de client, ongewijzigd.
public Task ThrowException()
{
throw new HubException("This error will be sent to the client!");
}
Note
SignalR verzendt alleen de Message eigenschap van de uitzondering naar de client. De stacktrace en andere eigenschappen van de uitzondering zijn niet beschikbaar voor de client.
Aanvullende bronnen
Door Rachel Appel en Kevin Griffin
Voorbeeldcode weergeven of downloaden(hoe te downloaden)
Wat is een SignalR hub?
Met de SignalR Hubs-API kunnen verbonden clients methoden op de server aanroepen, waardoor realtime communicatie wordt vergemakkelijkt. De server definieert methoden die door de client worden aangeroepen en de client definieert methoden die door de server worden aangeroepen. SignalR maakt ook indirecte client-naar-client-communicatie mogelijk, altijd gemediateerd door de SignalR Hub, zodat berichten kunnen worden verzonden tussen afzonderlijke clients, groepen of naar alle verbonden clients. SignalR zorgt ervoor dat realtime client-naar-server- en server-naar-clientcommunicatie mogelijk is.
Hubs configureren SignalR
Voor de SignalR middleware zijn enkele services vereist die zijn geconfigureerd door het aanroepen van AddSignalR:
services.AddSignalR();
Wanneer u functionaliteit SignalR toevoegt aan een ASP.NET Core-applicatie, stelt u de routes SignalR in door UseSignalR aan te roepen in de Startup.Configure-methode.
app.UseSignalR(route =>
{
route.MapHub<ChatHub>("/chathub");
});
Hubs maken en gebruiken
Maak een hub door een klasse te declareren van Huben openbare methoden eraan toe te voegen. Clients kunnen methoden aanroepen die zijn gedefinieerd als public:
public class ChatHub : Hub
{
public Task SendMessage(string user, string message)
{
return Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
U kunt een retourtype en parameters opgeven, inclusief complexe typen en matrices, zoals in elke C#-methode. SignalR verwerkt de serialisatie en deserialisatie van complexe objecten en matrices in uw parameters en retourwaarden.
Note
Hubs zijn tijdelijk:
- Sla de status niet op in een eigenschap in de hubklasse. Elke hubmethode-aanroep wordt uitgevoerd op een nieuw hub-exemplaar.
- Instantieer een hub niet rechtstreeks via afhankelijkheidsinjectie. Als u berichten wilt verzenden naar een client vanaf een andere locatie in uw toepassing, gebruikt u een
IHubContext. - Gebruik
awaitbij het aanroepen van asynchrone methoden die afhankelijk zijn van het in leven blijven van de hub. Een methode zoalsClients.All.SendAsync(...)kan bijvoorbeeld mislukken als deze wordt aangeroepen zonderawaiten de hubmethode voltooid wordt voordatSendAsyncklaar is.
Het Context-object
De Hub klasse heeft een Context eigenschap die de volgende eigenschappen bevat met informatie over de verbinding:
| Property | Description |
|---|---|
| ConnectionId | Hiermee haalt u de unieke id voor de verbinding op, toegewezen door SignalR. Er is één verbindings-id voor elke verbinding. |
| UserIdentifier | Hiermee haalt u de gebruikers-id op. Standaard gebruikt SignalR de ClaimTypes.NameIdentifier uit de ClaimsPrincipal die gekoppeld is aan de verbinding als de gebruikers-id. |
| User | Hiermee wordt de ClaimsPrincipal gekoppelde aan de huidige gebruiker. |
| Items | Hiermee haalt u een sleutel/waardeverzameling op die kan worden gebruikt voor het delen van gegevens binnen het bereik van deze verbinding. Gegevens kunnen worden opgeslagen in deze verzameling en blijven behouden voor de verbinding tussen verschillende hubmethodeaanroepen. |
| Features | Hiermee haalt u de verzameling functies op die beschikbaar zijn voor de verbinding. Deze verzameling is momenteel niet nodig in de meeste scenario's, dus deze is nog niet gedetailleerd gedocumenteerd. |
| ConnectionAborted | Hiermee wordt een CancellationToken bericht weergegeven wanneer de verbinding wordt afgebroken. |
Hub.Context bevat ook de volgende methoden:
| Method | Description |
|---|---|
| GetHttpContext | Retourneert de HttpContext voor de verbinding of null als de verbinding niet is gekoppeld aan een HTTP-aanvraag. Voor HTTP-verbindingen kunt u deze methode gebruiken om informatie op te halen, zoals HTTP-headers en queryreeksen. |
| Abort | Hiermee wordt de verbinding afgebroken. |
Klantenobject
De Hub klasse heeft een Clients eigenschap die de volgende eigenschappen bevat voor communicatie tussen server en client:
| Property | Description |
|---|---|
| All | Roept een methode aan op alle verbonden clients |
| Caller | Roept een methode aan op de client die de hubmethode heeft aangeroepen |
| Others | Roept een methode aan op alle verbonden clients, met uitzondering van de client die de methode heeft aangeroepen |
Hub.Clients bevat ook de volgende methoden:
| Method | Description |
|---|---|
| AllExcept | Roept een methode aan op alle verbonden clients, met uitzondering van de opgegeven verbindingen |
| Client | Roept een methode aan op een specifieke verbonden client |
| Clients | Roept een methode aan op specifieke verbonden clients |
| Group | Roept een methode aan voor alle verbindingen in de opgegeven groep |
| GroupExcept | Roept een methode aan voor alle verbindingen in de opgegeven groep, met uitzondering van de opgegeven verbindingen |
| Groups | Roept een methode aan voor meerdere groepen verbindingen |
| OthersInGroup | Roept een methode aan voor een groep verbindingen, met uitzondering van de client die de hubmethode heeft aangeroepen |
| User | Roept een methode aan voor alle verbindingen die zijn gekoppeld aan een specifieke gebruiker |
| Users | Roept een methode aan voor alle verbindingen die zijn gekoppeld aan de opgegeven gebruikers |
Elke eigenschap of methode in de voorgaande tabellen retourneert een object met een SendAsync methode. Met SendAsync de methode kunt u de naam en parameters van de clientmethode opgeven die u wilt aanroepen.
Berichten verzenden naar klanten
Gebruik de eigenschappen van het Clients object om aanroepen te doen naar specifieke clients. In het volgende voorbeeld zijn er drie Hub-methoden:
-
SendMessageverzendt een bericht naar alle verbonden clients met behulp vanClients.All. -
SendMessageToCallerstuurt een bericht terug naar de beller met behulp vanClients.Caller. -
SendMessageToGroupverzendt een bericht naar alle clients in deSignalR Usersgroep.
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);
}
Sterk getypeerde hubs
Een nadeel van het gebruik SendAsync is dat het afhankelijk is van een magic-tekenreeks om de clientmethode op te geven die moet worden aangeroepen. Hierdoor blijft code open voor runtime-fouten als de naam van de methode onjuist is gespeld of ontbreekt in de client.
Een alternatief voor het gebruik SendAsync is om het Hub sterk te typen met Hub<T>. In het volgende voorbeeld zijn de clientmethoden geëxtraheerd in een interface met de ChatHub naam IChatClient.
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Deze interface kan worden gebruikt om het voorgaande ChatHub voorbeeld te herstructureren:
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);
}
}
Door gebruik van Hub<IChatClient> maakt het mogelijk compileertijdcontrole van de clientmethoden. Dit voorkomt problemen die worden veroorzaakt door het gebruik van magic-tekenreeksen, omdat Hub<T> ze alleen toegang kunnen bieden tot de methoden die in de interface zijn gedefinieerd.
Als u een sterk getypte Hub<T> gebruikt, wordt de mogelijkheid om SendAsync te gebruiken uitgeschakeld. Methoden die op de interface zijn gedefinieerd, kunnen nog steeds als asynchroon worden gedefinieerd. In feite moet elk van deze methoden een Task. Omdat het een interface is, gebruikt u het async trefwoord niet. Voorbeeld:
public interface IClient
{
Task ClientMethod();
}
Note
Het Async achtervoegsel is niet verwijderd uit de naam van de methode. Tenzij uw clientmethode is gedefinieerd met .on('MyMethodAsync'), moet u deze niet gebruiken MyMethodAsync als een naam.
De naam van een hubmethode wijzigen
Standaard is de naam van een serverhubmethode de naam van de .NET-methode. U kunt echter het kenmerk HubMethodName gebruiken om deze standaardinstelling te wijzigen en handmatig een naam voor de methode op te geven. De client moet deze naam gebruiken in plaats van de naam van de .NET-methode bij het aanroepen van de methode:
[HubMethodName("SendMessageToUser")]
public Task DirectMessage(string user, string message)
{
return Clients.User(user).SendAsync("ReceiveMessage", user, message);
}
Gebeurtenissen voor een verbinding verwerken
De SignalR Hubs API biedt de OnConnectedAsync en OnDisconnectedAsync virtuele methoden om verbindingen te beheren en bij te houden. Overschrijf de OnConnectedAsync virtuele methode om acties uit te voeren wanneer een client verbinding maakt met de hub, zoals het toevoegen aan een groep:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Overschrijf de OnDisconnectedAsync virtuele methode om acties uit te voeren wanneer een client de verbinding verbreekt. Als de client opzettelijk wordt verbroken (door bijvoorbeeld aan te roepenconnection.stop()), is exceptionde null parameter. Als de verbinding met de client echter is verbroken vanwege een fout (zoals een netwerkfout), bevat de exception parameter een uitzondering waarin de fout wordt beschreven:
public override async Task OnDisconnectedAsync(Exception exception)
{
await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", "I", "disconnect");
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync hoeft niet aangeroepen te worden in OnDisconnectedAsync, het wordt automatisch voor u afgehandeld.
Warning
Beveiligingswaarschuwing: exposeren ConnectionId kan leiden tot schadelijke imitatie als de SignalR server- of clientversie ASP.NET Core 2.2 of eerder is.
Afhandeling van fouten
Uitzonderingen die zijn opgetreden in uw hubmethoden, worden verzonden naar de client die de methode heeft aangeroepen. Op de JavaScript-client retourneert de invoke methode een JavaScript Promise. Wanneer de client een fout ontvangt met een handler die is gekoppeld aan de belofte, catchwordt deze aangeroepen en doorgegeven als een JavaScript-object Error :
connection.invoke("SendMessage", user, message).catch(err => console.error(err));
Als uw Hub een uitzondering genereert, worden verbindingen niet gesloten. Retourneert standaard SignalR een algemeen foutbericht naar de client. Voorbeeld:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'MethodName' on the server.
Onverwachte uitzonderingen bevatten vaak gevoelige informatie, zoals de naam van een databaseserver in een uitzondering die wordt geactiveerd wanneer de databaseverbinding mislukt. SignalR bevat deze gedetailleerde foutberichten niet standaard als een beveiligingsmaatregel. Zie Beveiligingsoverwegingen in ASP.NET Core SignalRvoor meer informatie over waarom uitzonderingsdetails worden onderdrukt.
Als u een uitzonderlijke voorwaarde hebt die u wilt doorgeven aan de client, kunt u de HubException klasse gebruiken. Als u een HubException vanuit uw hubmethode gooit, SignalRstuurt het hele bericht naar de client, ongewijzigd.
public Task ThrowException()
{
throw new HubException("This error will be sent to the client!");
}
Note
SignalR verzendt alleen de Message eigenschap van de uitzondering naar de client. De stacktrace en andere eigenschappen van de uitzondering zijn niet beschikbaar voor de client.