Delen via


Gebruik hubs in SignalR voor ASP.NET Core

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 await bij het aanroepen van asynchrone methoden die afhankelijk zijn van het in leven blijven van de hub. Een methode zoals Clients.All.SendAsync(...) kan bijvoorbeeld mislukken als deze wordt aangeroepen zonder await en de hubmethode voltooid wordt voordat SendAsync klaar 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:

  • SendMessage verzendt een bericht naar alle verbonden clients met behulp van Clients.All.
  • SendMessageToCaller stuurt een bericht terug naar de beller met behulp van Clients.Caller.
  • SendMessageToGroup verzendt een bericht naar alle clients in de SignalR Users groep.
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 await bij het aanroepen van asynchrone methoden die afhankelijk zijn van het in leven blijven van de hub. Een methode zoals Clients.All.SendAsync(...) kan bijvoorbeeld mislukken als deze wordt aangeroepen zonder await en de hubmethode voltooid wordt voordat SendAsync klaar 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:

  • SendMessage verzendt een bericht naar alle verbonden clients met behulp van Clients.All.
  • SendMessageToCaller stuurt een bericht terug naar de beller met behulp van Clients.Caller.
  • SendMessageToGroup verzendt een bericht naar alle clients in de SignalR Users groep.
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 await bij het aanroepen van asynchrone methoden die afhankelijk zijn van het in leven blijven van de hub. Een methode zoals Clients.All.SendAsync(...) kan bijvoorbeeld mislukken als deze wordt aangeroepen zonder await en de hubmethode voltooid wordt voordat SendAsync klaar 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:

  • SendMessage verzendt een bericht naar alle verbonden clients met behulp van Clients.All.
  • SendMessageToCaller stuurt een bericht terug naar de beller met behulp van Clients.Caller.
  • SendMessageToGroup verzendt een bericht naar alle clients in de SignalR Users groep.
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 await bij het aanroepen van asynchrone methoden die afhankelijk zijn van het in leven blijven van de hub. Een methode zoals Clients.All.SendAsync(...) kan bijvoorbeeld mislukken als deze wordt aangeroepen zonder await en de hubmethode voltooid wordt voordat SendAsync klaar 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:

  • SendMessage verzendt een bericht naar alle verbonden clients met behulp van Clients.All.
  • SendMessageToCaller stuurt een bericht terug naar de beller met behulp van Clients.Caller.
  • SendMessageToGroup verzendt een bericht naar alle clients in de SignalR Users groep.
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 await bij het aanroepen van asynchrone methoden die afhankelijk zijn van het in leven blijven van de hub. Een methode zoals Clients.All.SendAsync(...) kan bijvoorbeeld mislukken als deze wordt aangeroepen zonder await en de hubmethode voltooid wordt voordat SendAsync klaar 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:

  • SendMessage verzendt een bericht naar alle verbonden clients met behulp van Clients.All.
  • SendMessageToCaller stuurt een bericht terug naar de beller met behulp van Clients.Caller.
  • SendMessageToGroup verzendt een bericht naar alle clients in de SignalR Users groep.
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