Sdílet prostřednictvím


Použití center SignalR pro ASP.NET Core

Od Rachel Appel a Kevin Griffin

Rozhraní SignalR API služby Hubs umožňuje připojeným klientům volat metody na serveru, což usnadňuje komunikaci v reálném čase. Server definuje metody, které volá klient, a klient definuje metody, které jsou volány serverem. SignalR umožňuje také nepřímou komunikaci mezi klienty a klienty, vždy zprostředkovanou centrem SignalR , což umožňuje odesílání zpráv mezi jednotlivými klienty, skupinami nebo všemi připojenými klienty. SignalR postará se o všechno potřebné k tomu, aby bylo možné komunikaci mezi klientem a klientem v reálném čase.

Konfigurace SignalR center

Pokud chcete zaregistrovat služby vyžadované SignalR rozbočovači, zavolejte AddSignalR do Program.cs:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddSignalR();

Ke konfiguraci SignalR koncových bodů zavolejte MapHubtaké v Program.cs:

app.MapRazorPages();
app.MapHub<ChatHub>("/Chat");

app.Run();

Poznámka:

ASP.NET sestavení na straně serveru se SignalR teď instalují se sadou .NET Core SDK. Další informace najdete SignalR v sestaveních ve sdíleném rozhraní .

Vytváření a používání center

Vytvoření centra deklarováním třídy, která dědí z Hub. Přidejte public do třídy metody, které je volat z klientů:

public class ChatHub : Hub
{
    public async Task SendMessage(string user, string message)
        => await Clients.All.SendAsync("ReceiveMessage", user, message);
}

Poznámka:

Rozbočovače jsou přechodné:

  • Neukládejte stav ve vlastnosti třídy centra. Každé volání metody centra se provádí v nové instanci centra.
  • Vytvořte instanci centra přímo prostřednictvím injektáže závislostí. K odesílání zpráv klientovi z jiného prostředí aplikace použijte příkaz IHubContext.
  • Používá se await při volání asynchronních metod, které závisí na udržování centra. Například metoda Clients.All.SendAsync(...) může selhat, pokud je volána bez await a metoda centra se dokončí před SendAsync dokončením.

Kontextový objekt

Třída Hub obsahuje Context vlastnost, která obsahuje následující vlastnosti s informacemi o připojení:

Vlastnost Popis
ConnectionId Získá jedinečné ID pro připojení přiřazeno SignalR. Pro každé připojení existuje jedno ID připojení.
UserIdentifier Získá identifikátor uživatele. Ve výchozím nastavení SignalR se jako identifikátor uživatele používá ClaimTypes.NameIdentifier z ClaimsPrincipal přidruženého připojení.
User ClaimsPrincipal Získá přidružené k aktuálnímu uživateli.
Items Získá kolekci klíč/hodnota, která se dá použít ke sdílení dat v rámci tohoto připojení. Data mohou být uložena v této kolekci a budou zachována pro připojení napříč různými vyvoláním metod centra.
Features Získá kolekci funkcí dostupných v připojení. Prozatím tato kolekce není ve většině scénářů potřebná, takže zatím není podrobně zdokumentovaná.
ConnectionAborted CancellationToken Získá upozornění, když je připojení přerušeno.

Hub.Context obsahuje také následující metody:

metoda Popis
GetHttpContext HttpContext Vrátí pro připojení nebo null pokud připojení není přidružené k požadavku HTTP. Pro připojení HTTP použijte tuto metodu k získání informací, jako jsou hlavičky HTTP a řetězce dotazů.
Abort Přeruší připojení.

Objekt Klienti

Třída Hub obsahuje Clients vlastnost, která obsahuje následující vlastnosti pro komunikaci mezi serverem a klientem:

Vlastnost Popis
All Volá metodu pro všechny připojené klienty.
Caller Volá metodu na klientovi, který vyvolal metodu centra.
Others Volá metodu pro všechny připojené klienty s výjimkou klienta, který vyvolal metodu.

Hub.Clients obsahuje také následující metody:

metoda Popis
AllExcept Volá metodu pro všechny připojené klienty s výjimkou zadaných připojení.
Client Zavolá metodu pro konkrétního připojeného klienta.
Clients Volání metody pro konkrétní připojené klienty
Group Volá metodu pro všechna připojení v zadané skupině.
GroupExcept Volá metodu pro všechna připojení v zadané skupině s výjimkou zadaných připojení.
Groups Volá metodu pro více skupin připojení.
OthersInGroup Volá metodu ve skupině připojení s výjimkou klienta, který vyvolal metodu centra.
User Volá metodu pro všechna připojení přidružená ke konkrétnímu uživateli.
Users Volá metodu pro všechna připojení přidružená k zadaným uživatelům.

Každá vlastnost nebo metoda v předchozích tabulkách vrací objekt s metodou SendAsync . Metoda SendAsync obdrží název klientské metody pro volání a všechny parametry.

Objekt vrácený Client metodami a Caller metody také obsahují metodu InvokeAsync , kterou lze použít k čekání na výsledek z klienta.

Odesílání zpráv klientům

Pokud chcete volat konkrétní klienty, použijte vlastnosti objektu Clients . V následujícím příkladu existují tři metody centra:

  • SendMessageodešle zprávu všem připojeným klientům pomocí .Clients.All
  • SendMessageToCaller odešle zprávu zpět volajícímu pomocí funkce Clients.Caller.
  • SendMessageToGroup odešle zprávu všem klientům ve skupině SignalR Users .
public async Task SendMessage(string user, string message)
    => await Clients.All.SendAsync("ReceiveMessage", user, message);

public async Task SendMessageToCaller(string user, string message)
    => await Clients.Caller.SendAsync("ReceiveMessage", user, message);

public async Task SendMessageToGroup(string user, string message)
    => await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);

Rozbočovače silného typu

Nevýhodou použití SendAsync je, že spoléhá na řetězec k určení metody klienta, která se má volat. Pokud je název metody chybně napsaný nebo chybí v klientovi, ponechá kód otevřený chybám za běhu.

Alternativou k použití SendAsync je silného Hub typu třídy s Hub<T>. V následujícím příkladu ChatHub byla metoda klienta extrahována do rozhraní s názvem IChatClient:

public interface IChatClient
{
    Task ReceiveMessage(string user, string message);
}

Toto rozhraní lze použít k refaktoringu ChatHub předchozího příkladu na silné typy:

public class StronglyTypedChatHub : Hub<IChatClient>
{
    public async Task SendMessage(string user, string message)
        => await Clients.All.ReceiveMessage(user, message);

    public async Task SendMessageToCaller(string user, string message)
        => await Clients.Caller.ReceiveMessage(user, message);

    public async Task SendMessageToGroup(string user, string message)
        => await Clients.Group("SignalR Users").ReceiveMessage(user, message);
}

Použití Hub<IChatClient> umožňuje kontrolu doby kompilace klientských metod. To brání problémům způsobeným používáním řetězců, protože Hub<T> může poskytovat přístup pouze k metodám definovaným v rozhraní. Použití silného typu Hub<T> zakáže možnost používat SendAsync.

Poznámka:

Přípona Async se neodebrala z názvů metod. Pokud není definovaná .on('MyMethodAsync')metoda klienta , nepoužívejte MyMethodAsync ji jako název.

Výsledky klienta

Kromě volání klientů může server požádat o výsledek klienta. To vyžaduje, aby server používal ISingleClientProxy.InvokeAsync a klient vrátil výsledek z jeho .On obslužné rutiny.

Existují dva způsoby použití rozhraní API na serveru, první je volání Client(...) nebo Caller vlastnosti Clients v metodě centra:

public class ChatHub : Hub
{
    public async Task<string> WaitForMessage(string connectionId)
    {
        var message = await Clients.Client(connectionId).InvokeAsync<string>(
            "GetMessage");
        return message;
    }
}

Druhým způsobem je volání Client(...) instance IHubContext<T>:

async Task SomeMethod(IHubContext<MyHub> context)
{
    string result = await context.Clients.Client(connectionID).InvokeAsync<string>(
        "GetMessage");
}

Rozbočovače silného typu můžou také vracet hodnoty z metod rozhraní:

public interface IClient
{
    Task<string> GetMessage();
}

public class ChatHub : Hub<IClient>
{
    public async Task<string> WaitForMessage(string connectionId)
    {
        string message = await Clients.Client(connectionId).GetMessage();
        return message;
    }
}

Klienti vrací výsledky v jejich .On(...) obslužných rutinách, jak je znázorněno níže:

Klient .NET

hubConnection.On("GetMessage", async () =>
{
    Console.WriteLine("Enter message:");
    var message = await Console.In.ReadLineAsync();
    return message;
});

Klient TypeScriptu

hubConnection.on("GetMessage", async () => {
    let promise = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("message");
        }, 100);
    });
    return promise;
});

Java klient

hubConnection.onWithResult("GetMessage", () -> {
    return Single.just("message");
});

Změna názvu metody centra

Ve výchozím nastavení je název metody centra serveru název metody .NET. Chcete-li změnit toto výchozí chování pro konkrétní metodu , použijte atribut HubMethodName . Při vyvolání metody by měl klient místo názvu metody .NET použít tento název:

[HubMethodName("SendMessageToUser")]
public async Task DirectMessage(string user, string message)
    => await Clients.User(user).SendAsync("ReceiveMessage", user, message);

Vložení služeb do centra

Konstruktory centra mohou přijímat služby z DI jako parametry, které mohou být uloženy ve vlastnostech třídy pro použití v metodě centra.

Při vkládání více služeb pro různé metody rozbočovače nebo jako alternativní způsob psaní kódu mohou metody centra také přijímat služby z DI. Ve výchozím nastavení se parametry metody centra kontrolují a v případě potřeby překládají z DI.

services.AddSingleton<IDatabaseService, DatabaseServiceImpl>();

// ...

public class ChatHub : Hub
{
    public Task SendMessage(string user, string message, IDatabaseService dbService)
    {
        var userName = dbService.GetUserName(user);
        return Clients.All.SendAsync("ReceiveMessage", userName, message);
    }
}

Pokud není žádoucí implicitní rozlišení parametrů ze služeb, zakažte ho pomocí DisableImplicitFromServicesParameters. Pokud chcete explicitně určit, které parametry se přeloží z DI v metodách centra, použijte možnost a použijte DisableImplicitFromServicesParameters [FromServices] atribut nebo vlastní atribut, který implementuje IFromServiceMetadata parametry metody centra, které by se měly přeložit z DI.

services.AddSingleton<IDatabaseService, DatabaseServiceImpl>();
services.AddSignalR(options =>
{
    options.DisableImplicitFromServicesParameters = true;
});

// ...

public class ChatHub : Hub
{
    public Task SendMessage(string user, string message,
        [FromServices] IDatabaseService dbService)
    {
        var userName = dbService.GetUserName(user);
        return Clients.All.SendAsync("ReceiveMessage", userName, message);
    }
}

Poznámka:

Tato funkce využívá funkci IServiceProviderIsService, která je volitelně implementována implementacemi DI. Pokud kontejner DI aplikace tuto funkci nepodporuje, vložení služeb do metod centra se nepodporuje.

Podpora služeb s klíči v injektáži závislostí

Služby s klíči odkazují na mechanismus registrace a načítání služeb injektáže závislostí (DI) pomocí klíčů. Služba je přidružena ke klíči voláním AddKeyedSingleton (nebo AddKeyedScoped AddKeyedTransient) k jeho registraci. Přístup k registrované službě zadáním klíče s atributem [FromKeyedServices] . Následující kód ukazuje, jak používat služby s klíči:

using Microsoft.AspNetCore.SignalR;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddKeyedSingleton<ICache, BigCache>("big");
builder.Services.AddKeyedSingleton<ICache, SmallCache>("small");

builder.Services.AddRazorPages();
builder.Services.AddSignalR();

var app = builder.Build();

app.MapRazorPages();
app.MapHub<MyHub>("/myHub");

app.Run();

public interface ICache
{
    object Get(string key);
}
public class BigCache : ICache
{
    public object Get(string key) => $"Resolving {key} from big cache.";
}

public class SmallCache : ICache
{
    public object Get(string key) => $"Resolving {key} from small cache.";
}

public class MyHub : Hub
{
    public void SmallCacheMethod([FromKeyedServices("small")] ICache cache)
    {
        Console.WriteLine(cache.Get("signalr"));
    }

    public void BigCacheMethod([FromKeyedServices("big")] ICache cache)
    {
        Console.WriteLine(cache.Get("signalr"));
    }
}

Zpracování událostí pro připojení

Rozhraní SignalR API služby Hubs poskytuje OnConnectedAsync a OnDisconnectedAsync virtuální metody pro správu a sledování připojení. Přepište virtuální metodu OnConnectedAsync , aby prováděla akce, když se klient připojí k centru, jako je například jeho přidání do skupiny:

public override async Task OnConnectedAsync()
{
    await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
    await base.OnConnectedAsync();
}

Přepište virtuální metodu OnDisconnectedAsync , aby prováděla akce, když se klient odpojí. Pokud se klient záměrně odpojí, například voláním connection.stop(), exception parametr je nastaven na nullhodnotu . Pokud se však klient odpojí kvůli chybě, například kvůli selhání sítě, obsahuje parametr výjimku, exception která popisuje selhání:

public override async Task OnDisconnectedAsync(Exception? exception)
{
    await base.OnDisconnectedAsync(exception);
}

RemoveFromGroupAsync nemusí být volána , OnDisconnectedAsyncje automaticky zpracována za vás.

Zpracování chyb

Výjimky vyvolané metodami centra se odesílají klientovi, který metodu vyvolal. V javascriptovém klientovi invoke vrátí metoda JavaScript Promise. Klienti můžou ke vráceným příslibům připojit obslužnou rutinu catch nebo ji použít asyncawait try/catch/ke zpracování výjimek:

try {
  await connection.invoke("SendMessage", user, message);
} catch (err) {
  console.error(err);
}

Připojení se nezavřou, když rozbočovač vyvolá výjimku. Ve výchozím nastavení SignalR vrátí klientovi obecnou chybovou zprávu, jak je znázorněno v následujícím příkladu:

Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'SendMessage' on the server.

Neočekávané výjimky často obsahují citlivé informace, například název databázového serveru v výjimce aktivované v případě selhání připojení k databázi. SignalR nezpřístupňuje tyto podrobné chybové zprávy ve výchozím nastavení jako bezpečnostní opatření. Další informace o tom, proč jsou podrobnosti o výjimce potlačeny, najdete v tématu Aspekty zabezpečení v ASP.NET Core SignalR.

Pokud je nutné do klienta rozšířit výjimečný stav, použijte HubException třídu. HubException Pokud je vyvolán v metodě centra, SignalRodešle klientovi celou zprávu o výjimce, která nenímodifikovaná:

public Task ThrowException()
    => throw new HubException("This error will be sent to the client!");

Poznámka:

SignalR odešle Message vlastnost výjimky pouze klientovi. Trasování zásobníku a další vlastnosti výjimky nejsou klientovi k dispozici.

Další materiály

Od Rachel Appel a Kevin Griffin

Rozhraní SignalR API služby Hubs umožňuje připojeným klientům volat metody na serveru, což usnadňuje komunikaci v reálném čase. Server definuje metody, které volá klient, a klient definuje metody, které jsou volány serverem. SignalR umožňuje také nepřímou komunikaci mezi klienty a klienty, vždy zprostředkovanou centrem SignalR , což umožňuje odesílání zpráv mezi jednotlivými klienty, skupinami nebo všemi připojenými klienty. SignalR postará se o všechno potřebné k tomu, aby bylo možné komunikaci mezi klientem a klientem v reálném čase.

Konfigurace SignalR center

Pokud chcete zaregistrovat služby vyžadované SignalR rozbočovači, zavolejte AddSignalR do Program.cs:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddSignalR();

Ke konfiguraci SignalR koncových bodů zavolejte MapHubtaké v Program.cs:

app.MapRazorPages();
app.MapHub<ChatHub>("/Chat");

app.Run();

Poznámka:

ASP.NET sestavení na straně serveru se SignalR teď instalují se sadou .NET Core SDK. Další informace najdete SignalR v sestaveních ve sdíleném rozhraní .

Vytváření a používání center

Vytvoření centra deklarováním třídy, která dědí z Hub. Přidejte public do třídy metody, které je volat z klientů:

public class ChatHub : Hub
{
    public async Task SendMessage(string user, string message)
        => await Clients.All.SendAsync("ReceiveMessage", user, message);
}

Poznámka:

Rozbočovače jsou přechodné:

  • Neukládejte stav ve vlastnosti třídy centra. Každé volání metody centra se provádí v nové instanci centra.
  • Vytvořte instanci centra přímo prostřednictvím injektáže závislostí. K odesílání zpráv klientovi z jiného prostředí aplikace použijte příkaz IHubContext.
  • Používá se await při volání asynchronních metod, které závisí na udržování centra. Například metoda Clients.All.SendAsync(...) může selhat, pokud je volána bez await a metoda centra se dokončí před SendAsync dokončením.

Kontextový objekt

Třída Hub obsahuje Context vlastnost, která obsahuje následující vlastnosti s informacemi o připojení:

Vlastnost Popis
ConnectionId Získá jedinečné ID pro připojení přiřazeno SignalR. Pro každé připojení existuje jedno ID připojení.
UserIdentifier Získá identifikátor uživatele. Ve výchozím nastavení SignalR se jako identifikátor uživatele používá ClaimTypes.NameIdentifier z ClaimsPrincipal přidruženého připojení.
User ClaimsPrincipal Získá přidružené k aktuálnímu uživateli.
Items Získá kolekci klíč/hodnota, která se dá použít ke sdílení dat v rámci tohoto připojení. Data mohou být uložena v této kolekci a budou zachována pro připojení napříč různými vyvoláním metod centra.
Features Získá kolekci funkcí dostupných v připojení. Prozatím tato kolekce není ve většině scénářů potřebná, takže zatím není podrobně zdokumentovaná.
ConnectionAborted CancellationToken Získá upozornění, když je připojení přerušeno.

Hub.Context obsahuje také následující metody:

metoda Popis
GetHttpContext HttpContext Vrátí pro připojení nebo null pokud připojení není přidružené k požadavku HTTP. Pro připojení HTTP použijte tuto metodu k získání informací, jako jsou hlavičky HTTP a řetězce dotazů.
Abort Přeruší připojení.

Objekt Klienti

Třída Hub obsahuje Clients vlastnost, která obsahuje následující vlastnosti pro komunikaci mezi serverem a klientem:

Vlastnost Popis
All Volá metodu pro všechny připojené klienty.
Caller Volá metodu na klientovi, který vyvolal metodu centra.
Others Volá metodu pro všechny připojené klienty s výjimkou klienta, který vyvolal metodu.

Hub.Clients obsahuje také následující metody:

metoda Popis
AllExcept Volá metodu pro všechny připojené klienty s výjimkou zadaných připojení.
Client Zavolá metodu pro konkrétního připojeného klienta.
Clients Volání metody pro konkrétní připojené klienty
Group Volá metodu pro všechna připojení v zadané skupině.
GroupExcept Volá metodu pro všechna připojení v zadané skupině s výjimkou zadaných připojení.
Groups Volá metodu pro více skupin připojení.
OthersInGroup Volá metodu ve skupině připojení s výjimkou klienta, který vyvolal metodu centra.
User Volá metodu pro všechna připojení přidružená ke konkrétnímu uživateli.
Users Volá metodu pro všechna připojení přidružená k zadaným uživatelům.

Každá vlastnost nebo metoda v předchozích tabulkách vrací objekt s metodou SendAsync . Metoda SendAsync obdrží název klientské metody pro volání a všechny parametry.

Objekt vrácený Client metodami a Caller metody také obsahují metodu InvokeAsync , kterou lze použít k čekání na výsledek z klienta.

Odesílání zpráv klientům

Pokud chcete volat konkrétní klienty, použijte vlastnosti objektu Clients . V následujícím příkladu existují tři metody centra:

  • SendMessageodešle zprávu všem připojeným klientům pomocí .Clients.All
  • SendMessageToCaller odešle zprávu zpět volajícímu pomocí funkce Clients.Caller.
  • SendMessageToGroup odešle zprávu všem klientům ve skupině SignalR Users .
public async Task SendMessage(string user, string message)
    => await Clients.All.SendAsync("ReceiveMessage", user, message);

public async Task SendMessageToCaller(string user, string message)
    => await Clients.Caller.SendAsync("ReceiveMessage", user, message);

public async Task SendMessageToGroup(string user, string message)
    => await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);

Rozbočovače silného typu

Nevýhodou použití SendAsync je, že spoléhá na řetězec k určení metody klienta, která se má volat. Pokud je název metody chybně napsaný nebo chybí v klientovi, ponechá kód otevřený chybám za běhu.

Alternativou k použití SendAsync je silného Hub typu třídy s Hub<T>. V následujícím příkladu ChatHub byla metoda klienta extrahována do rozhraní s názvem IChatClient:

public interface IChatClient
{
    Task ReceiveMessage(string user, string message);
}

Toto rozhraní lze použít k refaktoringu ChatHub předchozího příkladu na silné typy:

public class StronglyTypedChatHub : Hub<IChatClient>
{
    public async Task SendMessage(string user, string message)
        => await Clients.All.ReceiveMessage(user, message);

    public async Task SendMessageToCaller(string user, string message)
        => await Clients.Caller.ReceiveMessage(user, message);

    public async Task SendMessageToGroup(string user, string message)
        => await Clients.Group("SignalR Users").ReceiveMessage(user, message);
}

Použití Hub<IChatClient> umožňuje kontrolu doby kompilace klientských metod. To brání problémům způsobeným používáním řetězců, protože Hub<T> může poskytovat přístup pouze k metodám definovaným v rozhraní. Použití silného typu Hub<T> zakáže možnost používat SendAsync.

Poznámka:

Přípona Async se neodebrala z názvů metod. Pokud není definovaná .on('MyMethodAsync')metoda klienta , nepoužívejte MyMethodAsync ji jako název.

Výsledky klienta

Kromě volání klientů může server požádat o výsledek klienta. To vyžaduje, aby server používal ISingleClientProxy.InvokeAsync a klient vrátil výsledek z jeho .On obslužné rutiny.

Existují dva způsoby použití rozhraní API na serveru, první je volání Client(...) nebo Caller vlastnosti Clients v metodě centra:

public class ChatHub : Hub
{
    public async Task<string> WaitForMessage(string connectionId)
    {
        var message = await Clients.Client(connectionId).InvokeAsync<string>(
            "GetMessage");
        return message;
    }
}

Druhým způsobem je volání Client(...) instance IHubContext<T>:

async Task SomeMethod(IHubContext<MyHub> context)
{
    string result = await context.Clients.Client(connectionID).InvokeAsync<string>(
        "GetMessage");
}

Rozbočovače silného typu můžou také vracet hodnoty z metod rozhraní:

public interface IClient
{
    Task<string> GetMessage();
}

public class ChatHub : Hub<IClient>
{
    public async Task<string> WaitForMessage(string connectionId)
    {
        string message = await Clients.Client(connectionId).GetMessage();
        return message;
    }
}

Klienti vrací výsledky v jejich .On(...) obslužných rutinách, jak je znázorněno níže:

Klient .NET

hubConnection.On("GetMessage", async () =>
{
    Console.WriteLine("Enter message:");
    var message = await Console.In.ReadLineAsync();
    return message;
});

Klient TypeScriptu

hubConnection.on("GetMessage", async () => {
    let promise = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("message");
        }, 100);
    });
    return promise;
});

Java klient

hubConnection.onWithResult("GetMessage", () -> {
    return Single.just("message");
});

Změna názvu metody centra

Ve výchozím nastavení je název metody centra serveru název metody .NET. Chcete-li změnit toto výchozí chování pro konkrétní metodu , použijte atribut HubMethodName . Při vyvolání metody by měl klient místo názvu metody .NET použít tento název:

[HubMethodName("SendMessageToUser")]
public async Task DirectMessage(string user, string message)
    => await Clients.User(user).SendAsync("ReceiveMessage", user, message);

Vložení služeb do centra

Konstruktory centra mohou přijímat služby z DI jako parametry, které mohou být uloženy ve vlastnostech třídy pro použití v metodě centra.

Při vkládání více služeb pro různé metody rozbočovače nebo jako alternativní způsob psaní kódu mohou metody centra také přijímat služby z DI. Ve výchozím nastavení se parametry metody centra kontrolují a v případě potřeby překládají z DI.

services.AddSingleton<IDatabaseService, DatabaseServiceImpl>();

// ...

public class ChatHub : Hub
{
    public Task SendMessage(string user, string message, IDatabaseService dbService)
    {
        var userName = dbService.GetUserName(user);
        return Clients.All.SendAsync("ReceiveMessage", userName, message);
    }
}

Pokud není žádoucí implicitní rozlišení parametrů ze služeb, zakažte ho pomocí DisableImplicitFromServicesParameters. Pokud chcete explicitně určit, které parametry se přeloží z DI v metodách centra, použijte možnost a použijte DisableImplicitFromServicesParameters [FromServices] atribut nebo vlastní atribut, který implementuje IFromServiceMetadata parametry metody centra, které by se měly přeložit z DI.

services.AddSingleton<IDatabaseService, DatabaseServiceImpl>();
services.AddSignalR(options =>
{
    options.DisableImplicitFromServicesParameters = true;
});

// ...

public class ChatHub : Hub
{
    public Task SendMessage(string user, string message,
        [FromServices] IDatabaseService dbService)
    {
        var userName = dbService.GetUserName(user);
        return Clients.All.SendAsync("ReceiveMessage", userName, message);
    }
}

Poznámka:

Tato funkce využívá funkci IServiceProviderIsService, která je volitelně implementována implementacemi DI. Pokud kontejner DI aplikace tuto funkci nepodporuje, vložení služeb do metod centra se nepodporuje.

Zpracování událostí pro připojení

Rozhraní SignalR API služby Hubs poskytuje OnConnectedAsync a OnDisconnectedAsync virtuální metody pro správu a sledování připojení. Přepište virtuální metodu OnConnectedAsync , aby prováděla akce, když se klient připojí k centru, jako je například jeho přidání do skupiny:

public override async Task OnConnectedAsync()
{
    await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
    await base.OnConnectedAsync();
}

Přepište virtuální metodu OnDisconnectedAsync , aby prováděla akce, když se klient odpojí. Pokud se klient záměrně odpojí, například voláním connection.stop(), exception parametr je nastaven na nullhodnotu . Pokud se však klient odpojí kvůli chybě, například kvůli selhání sítě, obsahuje parametr výjimku, exception která popisuje selhání:

public override async Task OnDisconnectedAsync(Exception? exception)
{
    await base.OnDisconnectedAsync(exception);
}

RemoveFromGroupAsync nemusí být volána , OnDisconnectedAsyncje automaticky zpracována za vás.

Zpracování chyb

Výjimky vyvolané metodami centra se odesílají klientovi, který metodu vyvolal. V javascriptovém klientovi invoke vrátí metoda JavaScript Promise. Klienti můžou ke vráceným příslibům připojit obslužnou rutinu catch nebo ji použít asyncawait try/catch/ke zpracování výjimek:

try {
  await connection.invoke("SendMessage", user, message);
} catch (err) {
  console.error(err);
}

Připojení se nezavřou, když rozbočovač vyvolá výjimku. Ve výchozím nastavení SignalR vrátí klientovi obecnou chybovou zprávu, jak je znázorněno v následujícím příkladu:

Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'SendMessage' on the server.

Neočekávané výjimky často obsahují citlivé informace, například název databázového serveru v výjimce aktivované v případě selhání připojení k databázi. SignalR nezpřístupňuje tyto podrobné chybové zprávy ve výchozím nastavení jako bezpečnostní opatření. Další informace o tom, proč jsou podrobnosti o výjimce potlačeny, najdete v tématu Aspekty zabezpečení v ASP.NET Core SignalR.

Pokud je nutné do klienta rozšířit výjimečný stav, použijte HubException třídu. HubException Pokud je vyvolán v metodě centra, SignalRodešle klientovi celou zprávu o výjimce, která nenímodifikovaná:

public Task ThrowException()
    => throw new HubException("This error will be sent to the client!");

Poznámka:

SignalR odešle Message vlastnost výjimky pouze klientovi. Trasování zásobníku a další vlastnosti výjimky nejsou klientovi k dispozici.

Další materiály

Od Rachel Appel a Kevin Griffin

Rozhraní SignalR API služby Hubs umožňuje připojeným klientům volat metody na serveru, což usnadňuje komunikaci v reálném čase. Server definuje metody, které volá klient, a klient definuje metody, které jsou volány serverem. SignalR umožňuje také nepřímou komunikaci mezi klienty a klienty, vždy zprostředkovanou centrem SignalR , což umožňuje odesílání zpráv mezi jednotlivými klienty, skupinami nebo všemi připojenými klienty. SignalR postará se o všechno potřebné k tomu, aby bylo možné komunikaci mezi klientem a klientem v reálném čase.

Konfigurace SignalR center

Pokud chcete zaregistrovat služby vyžadované SignalR rozbočovači, zavolejte AddSignalR do Program.cs:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddSignalR();

Ke konfiguraci SignalR koncových bodů zavolejte MapHubtaké v Program.cs:

app.MapRazorPages();
app.MapHub<ChatHub>("/Chat");

app.Run();

Poznámka:

ASP.NET sestavení na straně serveru se SignalR teď instalují se sadou .NET Core SDK. Další informace najdete SignalR v sestaveních ve sdíleném rozhraní .

Vytváření a používání center

Vytvoření centra deklarováním třídy, která dědí z Hub. Přidejte public do třídy metody, které je volat z klientů:

public class ChatHub : Hub
{
    public async Task SendMessage(string user, string message)
        => await Clients.All.SendAsync("ReceiveMessage", user, message);
}

Poznámka:

Rozbočovače jsou přechodné:

  • Neukládejte stav ve vlastnosti třídy centra. Každé volání metody centra se provádí v nové instanci centra.
  • Vytvořte instanci centra přímo prostřednictvím injektáže závislostí. K odesílání zpráv klientovi z jiného prostředí aplikace použijte příkaz IHubContext.
  • Používá se await při volání asynchronních metod, které závisí na udržování centra. Například metoda Clients.All.SendAsync(...) může selhat, pokud je volána bez await a metoda centra se dokončí před SendAsync dokončením.

Kontextový objekt

Třída Hub obsahuje Context vlastnost, která obsahuje následující vlastnosti s informacemi o připojení:

Vlastnost Popis
ConnectionId Získá jedinečné ID pro připojení přiřazeno SignalR. Pro každé připojení existuje jedno ID připojení.
UserIdentifier Získá identifikátor uživatele. Ve výchozím nastavení SignalR se jako identifikátor uživatele používá ClaimTypes.NameIdentifier z ClaimsPrincipal přidruženého připojení.
User ClaimsPrincipal Získá přidružené k aktuálnímu uživateli.
Items Získá kolekci klíč/hodnota, která se dá použít ke sdílení dat v rámci tohoto připojení. Data mohou být uložena v této kolekci a budou zachována pro připojení napříč různými vyvoláním metod centra.
Features Získá kolekci funkcí dostupných v připojení. Prozatím tato kolekce není ve většině scénářů potřebná, takže zatím není podrobně zdokumentovaná.
ConnectionAborted CancellationToken Získá upozornění, když je připojení přerušeno.

Hub.Context obsahuje také následující metody:

metoda Popis
GetHttpContext HttpContext Vrátí pro připojení nebo null pokud připojení není přidružené k požadavku HTTP. Pro připojení HTTP použijte tuto metodu k získání informací, jako jsou hlavičky HTTP a řetězce dotazů.
Abort Přeruší připojení.

Objekt Klienti

Třída Hub obsahuje Clients vlastnost, která obsahuje následující vlastnosti pro komunikaci mezi serverem a klientem:

Vlastnost Popis
All Volá metodu pro všechny připojené klienty.
Caller Volá metodu na klientovi, který vyvolal metodu centra.
Others Volá metodu pro všechny připojené klienty s výjimkou klienta, který vyvolal metodu.

Hub.Clients obsahuje také následující metody:

metoda Popis
AllExcept Volá metodu pro všechny připojené klienty s výjimkou zadaných připojení.
Client Zavolá metodu pro konkrétního připojeného klienta.
Clients Volání metody pro konkrétní připojené klienty
Group Volá metodu pro všechna připojení v zadané skupině.
GroupExcept Volá metodu pro všechna připojení v zadané skupině s výjimkou zadaných připojení.
Groups Volá metodu pro více skupin připojení.
OthersInGroup Volá metodu ve skupině připojení s výjimkou klienta, který vyvolal metodu centra.
User Volá metodu pro všechna připojení přidružená ke konkrétnímu uživateli.
Users Volá metodu pro všechna připojení přidružená k zadaným uživatelům.

Každá vlastnost nebo metoda v předchozích tabulkách vrací objekt s metodou SendAsync . Metoda SendAsync obdrží název klientské metody pro volání a všechny parametry.

Odesílání zpráv klientům

Pokud chcete volat konkrétní klienty, použijte vlastnosti objektu Clients . V následujícím příkladu existují tři metody centra:

  • SendMessageodešle zprávu všem připojeným klientům pomocí .Clients.All
  • SendMessageToCaller odešle zprávu zpět volajícímu pomocí funkce Clients.Caller.
  • SendMessageToGroup odešle zprávu všem klientům ve skupině SignalR Users .
public async Task SendMessage(string user, string message)
    => await Clients.All.SendAsync("ReceiveMessage", user, message);

public async Task SendMessageToCaller(string user, string message)
    => await Clients.Caller.SendAsync("ReceiveMessage", user, message);

public async Task SendMessageToGroup(string user, string message)
    => await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);

Rozbočovače silného typu

Nevýhodou použití SendAsync je, že spoléhá na řetězec k určení metody klienta, která se má volat. Pokud je název metody chybně napsaný nebo chybí v klientovi, ponechá kód otevřený chybám za běhu.

Alternativou k použití SendAsync je silného Hub typu třídy s Hub<T>. V následujícím příkladu ChatHub byla metoda klienta extrahována do rozhraní s názvem IChatClient:

public interface IChatClient
{
    Task ReceiveMessage(string user, string message);
}

Toto rozhraní lze použít k refaktoringu ChatHub předchozího příkladu na silné typy:

public class StronglyTypedChatHub : Hub<IChatClient>
{
    public async Task SendMessage(string user, string message)
        => await Clients.All.ReceiveMessage(user, message);

    public async Task SendMessageToCaller(string user, string message)
        => await Clients.Caller.ReceiveMessage(user, message);

    public async Task SendMessageToGroup(string user, string message)
        => await Clients.Group("SignalR Users").ReceiveMessage(user, message);
}

Použití Hub<IChatClient> umožňuje kontrolu doby kompilace klientských metod. To brání problémům způsobeným používáním řetězců, protože Hub<T> může poskytovat přístup pouze k metodám definovaným v rozhraní. Použití silného typu Hub<T> zakáže možnost používat SendAsync.

Poznámka:

Přípona Async se neodebrala z názvů metod. Pokud není definovaná .on('MyMethodAsync')metoda klienta , nepoužívejte MyMethodAsync ji jako název.

Změna názvu metody centra

Ve výchozím nastavení je název metody centra serveru název metody .NET. Chcete-li změnit toto výchozí chování pro konkrétní metodu , použijte atribut HubMethodName . Při vyvolání metody by měl klient místo názvu metody .NET použít tento název:

[HubMethodName("SendMessageToUser")]
public async Task DirectMessage(string user, string message)
    => await Clients.User(user).SendAsync("ReceiveMessage", user, message);

Zpracování událostí pro připojení

Rozhraní SignalR API služby Hubs poskytuje OnConnectedAsync a OnDisconnectedAsync virtuální metody pro správu a sledování připojení. Přepište virtuální metodu OnConnectedAsync , aby prováděla akce, když se klient připojí k centru, jako je například jeho přidání do skupiny:

public override async Task OnConnectedAsync()
{
    await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
    await base.OnConnectedAsync();
}

Přepište virtuální metodu OnDisconnectedAsync , aby prováděla akce, když se klient odpojí. Pokud se klient záměrně odpojí, například voláním connection.stop(), exception parametr je nastaven na nullhodnotu . Pokud se však klient odpojí kvůli chybě, například kvůli selhání sítě, obsahuje parametr výjimku, exception která popisuje selhání:

public override async Task OnDisconnectedAsync(Exception? exception)
{
    await base.OnDisconnectedAsync(exception);
}

RemoveFromGroupAsync nemusí být volána , OnDisconnectedAsyncje automaticky zpracována za vás.

Zpracování chyb

Výjimky vyvolané metodami centra se odesílají klientovi, který metodu vyvolal. V javascriptovém klientovi invoke vrátí metoda JavaScript Promise. Klienti můžou ke vráceným příslibům připojit obslužnou rutinu catch nebo ji použít asyncawait try/catch/ke zpracování výjimek:

try {
  await connection.invoke("SendMessage", user, message);
} catch (err) {
  console.error(err);
}

Připojení se nezavřou, když rozbočovač vyvolá výjimku. Ve výchozím nastavení SignalR vrátí klientovi obecnou chybovou zprávu, jak je znázorněno v následujícím příkladu:

Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'SendMessage' on the server.

Neočekávané výjimky často obsahují citlivé informace, například název databázového serveru v výjimce aktivované v případě selhání připojení k databázi. SignalR nezpřístupňuje tyto podrobné chybové zprávy ve výchozím nastavení jako bezpečnostní opatření. Další informace o tom, proč jsou podrobnosti o výjimce potlačeny, najdete v tématu Aspekty zabezpečení v ASP.NET Core SignalR.

Pokud je nutné do klienta rozšířit výjimečný stav, použijte HubException třídu. HubException Pokud je vyvolán v metodě centra, SignalRodešle klientovi celou zprávu o výjimce, která nenímodifikovaná:

public Task ThrowException()
    => throw new HubException("This error will be sent to the client!");

Poznámka:

SignalR odešle Message vlastnost výjimky pouze klientovi. Trasování zásobníku a další vlastnosti výjimky nejsou klientovi k dispozici.

Další materiály

Od Rachel Appel a Kevin Griffin

Zobrazení nebo stažení ukázkového kódu (postup stažení)

Co je SignalR centrum

Rozhraní SignalR API služby Hubs umožňuje připojeným klientům volat metody na serveru, což usnadňuje komunikaci v reálném čase. Server definuje metody, které volá klient, a klient definuje metody, které jsou volány serverem. SignalR umožňuje také nepřímou komunikaci mezi klienty a klienty, vždy zprostředkovanou centrem SignalR , což umožňuje odesílání zpráv mezi jednotlivými klienty, skupinami nebo všemi připojenými klienty. SignalR postará se o všechno potřebné k tomu, aby bylo možné komunikaci mezi klientem a klientem v reálném čase.

Konfigurace SignalR center

Middleware SignalR vyžaduje některé služby, které jsou nakonfigurovány voláním AddSignalR:

services.AddSignalR();

Při přidávání SignalR funkcí do aplikace ASP.NET Core nastavte SignalR trasy voláním zpětného Startup.Configure UseEndpoints volání MapHub metody:

app.UseRouting();
app.UseEndpoints(endpoints =>
{
    endpoints.MapHub<ChatHub>("/chathub");
});

Poznámka:

ASP.NET sestavení na straně serveru se SignalR teď instalují se sadou .NET Core SDK. Další informace najdete SignalR v sestaveních ve sdíleném rozhraní .

Vytváření a používání center

Vytvořte centrum deklarováním třídy, která dědí z Hub, a přidejte do ní veřejné metody. Klienti mohou volat metody definované takto public:

public class ChatHub : Hub
{
    public Task SendMessage(string user, string message)
    {
        return Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}

Můžete zadat návratový typ a parametry, včetně komplexních typů a polí, stejně jako v jakékoli metodě jazyka C#. SignalR zpracovává serializaci a deserializaci složitých objektů a polí v parametrech a návratových hodnotách.

Poznámka:

Rozbočovače jsou přechodné:

  • Neukládejte stav ve vlastnosti třídy centra. Každé volání metody centra se provádí v nové instanci centra.
  • Vytvořte instanci centra přímo prostřednictvím injektáže závislostí. K odesílání zpráv klientovi z jiného prostředí aplikace použijte příkaz IHubContext.
  • Používá se await při volání asynchronních metod, které závisí na udržování centra. Například metoda Clients.All.SendAsync(...) může selhat, pokud je volána bez await a metoda centra se dokončí před SendAsync dokončením.

Kontextový objekt

Třída HubContext vlastnost, která obsahuje následující vlastnosti s informacemi o připojení:

Vlastnost Popis
ConnectionId Získá jedinečné ID pro připojení přiřazeno SignalR. Pro každé připojení existuje jedno ID připojení.
UserIdentifier Získá identifikátor uživatele. Ve výchozím nastavení SignalR se jako identifikátor uživatele používá ClaimTypes.NameIdentifier z ClaimsPrincipal přidruženého připojení.
User ClaimsPrincipal Získá přidružené k aktuálnímu uživateli.
Items Získá kolekci klíč/hodnota, která se dá použít ke sdílení dat v rámci tohoto připojení. Data mohou být uložena v této kolekci a budou zachována pro připojení napříč různými vyvoláním metod centra.
Features Získá kolekci funkcí dostupných v připojení. Prozatím tato kolekce není ve většině scénářů potřebná, takže zatím není podrobně zdokumentovaná.
ConnectionAborted CancellationToken Získá upozornění, když je připojení přerušeno.

Hub.Context obsahuje také následující metody:

metoda Popis
GetHttpContext HttpContext Vrátí pro připojení nebo null pokud připojení není přidružené k požadavku HTTP. Pro připojení HTTP můžete pomocí této metody získat informace, jako jsou hlavičky HTTP a řetězce dotazů.
Abort Přeruší připojení.

Objekt Klienti

Třída HubClients vlastnost, která obsahuje následující vlastnosti pro komunikaci mezi serverem a klientem:

Vlastnost Popis
All Volá metodu pro všechny připojené klienty.
Caller Volá metodu na klientovi, který vyvolal metodu centra.
Others Volá metodu pro všechny připojené klienty s výjimkou klienta, který vyvolal metodu.

Hub.Clients obsahuje také následující metody:

metoda Popis
AllExcept Volá metodu pro všechny připojené klienty s výjimkou zadaných připojení.
Client Zavolá metodu pro konkrétního připojeného klienta.
Clients Volání metody pro konkrétní připojené klienty
Group Volá metodu pro všechna připojení v zadané skupině.
GroupExcept Volá metodu pro všechna připojení v zadané skupině s výjimkou zadaných připojení.
Groups Volá metodu pro více skupin připojení.
OthersInGroup Volá metodu ve skupině připojení s výjimkou klienta, který vyvolal metodu centra.
User Volá metodu pro všechna připojení přidružená ke konkrétnímu uživateli.
Users Volá metodu pro všechna připojení přidružená k zadaným uživatelům.

Každá vlastnost nebo metoda v předchozích tabulkách vrací objekt s metodou SendAsync . Tato SendAsync metoda umožňuje zadat název a parametry klientské metody, které se mají volat.

Odesílání zpráv klientům

Pokud chcete volat konkrétní klienty, použijte vlastnosti objektu Clients . V následujícím příkladu existují tři metody centra:

  • SendMessageodešle zprávu všem připojeným klientům pomocí .Clients.All
  • SendMessageToCaller odešle zprávu zpět volajícímu pomocí funkce Clients.Caller.
  • SendMessageToGroup odešle zprávu všem klientům ve skupině SignalR Users .
public Task SendMessage(string user, string message)
{
    return Clients.All.SendAsync("ReceiveMessage", user, message);
}

public Task SendMessageToCaller(string user, string message)
{
    return Clients.Caller.SendAsync("ReceiveMessage", user, message);
}

public Task SendMessageToGroup(string user, string message)
{
    return Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);
}

Rozbočovače silného typu

Nevýhodou použití SendAsync je, že spoléhá na magický řetězec k určení klientské metody, která se má volat. Pokud je název metody chybně napsaný nebo chybí v klientovi, ponechá kód otevřený chybám za běhu.

Alternativou k použití SendAsync je silného typu s Hub Hub<T>. V následujícím příkladu ChatHub byly klientské metody extrahovány do rozhraní s názvem IChatClient.

public interface IChatClient
{
    Task ReceiveMessage(string user, string message);
}

Toto rozhraní lze použít k refaktoringu ChatHub předchozího příkladu:

    public class StronglyTypedChatHub : Hub<IChatClient>
    {
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.ReceiveMessage(user, message);
        }

        public Task SendMessageToCaller(string user, string message)
        {
            return Clients.Caller.ReceiveMessage(user, message);
        }
}

Použití Hub<IChatClient> umožňuje kontrolu doby kompilace klientských metod. To brání problémům způsobeným používáním magických řetězců, protože Hub<T> může poskytovat přístup pouze k metodám definovaným v rozhraní.

Použití silného typu Hub<T> zakáže možnost používat SendAsync. Všechny metody definované v rozhraní mohou být stále definovány jako asynchronní. Ve skutečnosti by každá z těchto metod měla vrátit Taskhodnotu . Vzhledem k tomu, že se jedná o rozhraní, nepoužívejte async klíčové slovo. Příklad:

public interface IClient
{
    Task ClientMethod();
}

Poznámka:

Přípona Async není z názvu metody odebrána. Pokud není .on('MyMethodAsync')definovaná vaše metoda klienta , neměli byste ji používat MyMethodAsync jako název.

Změna názvu metody centra

Ve výchozím nastavení je název metody centra serveru název metody .NET. Můžete však použít HubMethodName atribut změnit toto výchozí a ručně zadat název metody. Při vyvolání metody by měl klient místo názvu metody .NET použít tento název:

[HubMethodName("SendMessageToUser")]
public Task DirectMessage(string user, string message)
{
    return Clients.User(user).SendAsync("ReceiveMessage", user, message);
}

Zpracování událostí pro připojení

Rozhraní SignalR API služby Hubs poskytuje OnConnectedAsync a OnDisconnectedAsync virtuální metody pro správu a sledování připojení. Přepište virtuální metodu OnConnectedAsync , aby prováděla akce, když se klient připojí k centru, jako je například jeho přidání do skupiny:

public override async Task OnConnectedAsync()
{
    await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
    await base.OnConnectedAsync();
}

Přepište virtuální metodu OnDisconnectedAsync , aby prováděla akce, když se klient odpojí. Pokud se klient záměrně odpojí (například voláním connection.stop()), exception parametr bude null. Pokud se ale klient odpojí kvůli chybě (například selhání sítě), exception parametr bude obsahovat výjimku popisující selhání:

public override async Task OnDisconnectedAsync(Exception exception)
{
    await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", "I", "disconnect");
    await base.OnDisconnectedAsync(exception);
}

RemoveFromGroupAsync nemusí být volána , OnDisconnectedAsyncje automaticky zpracována za vás.

Upozorňující

Upozornění zabezpečení: Zveřejnění ConnectionId může vést k zosobnění se zlými úmysly, pokud SignalR je server nebo verze klienta ASP.NET Core 2.2 nebo starší.

Zpracování chyb

Výjimky vyvolané metodami centra se odesílají klientovi, který metodu vyvolal. V javascriptovém klientovi invoke vrátí metoda JavaScript Promise. Když se klientovi zobrazí chyba s obslužnou rutinou připojenou k příslibu pomocí catch, vyvolá se a předá jako javascriptový Error objekt:

connection.invoke("SendMessage", user, message).catch(err => console.error(err));

Pokud vaše centrum vyvolá výjimku, připojení se nezavřou. Ve výchozím nastavení SignalR vrátí klientovi obecnou chybovou zprávu. Příklad:

Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'MethodName' on the server.

Neočekávané výjimky často obsahují citlivé informace, například název databázového serveru v výjimce aktivované v případě selhání připojení k databázi. SignalR nezpřístupňuje tyto podrobné chybové zprávy ve výchozím nastavení jako bezpečnostní opatření. Další informace o tom, proč jsou podrobnosti o výjimce potlačeny, najdete v tématu Aspekty zabezpečení v ASP.NET Core SignalR.

Pokud máte výjimečný stav, který chcete rozšířit do klienta, můžete použít HubException třídu. Pokud vyvoláte metodu HubException centra, SignalR odešlete klientovi celou zprávu, která nenímodifikovaná:

public Task ThrowException()
{
    throw new HubException("This error will be sent to the client!");
}

Poznámka:

SignalR odešle Message vlastnost výjimky pouze klientovi. Trasování zásobníku a další vlastnosti výjimky nejsou klientovi k dispozici.

Další materiály

Od Rachel Appel a Kevin Griffin

Zobrazení nebo stažení ukázkového kódu (postup stažení)

Co je SignalR centrum

Rozhraní SignalR API služby Hubs umožňuje připojeným klientům volat metody na serveru, což usnadňuje komunikaci v reálném čase. Server definuje metody, které volá klient, a klient definuje metody, které jsou volány serverem. SignalR umožňuje také nepřímou komunikaci mezi klienty a klienty, vždy zprostředkovanou centrem SignalR , což umožňuje odesílání zpráv mezi jednotlivými klienty, skupinami nebo všemi připojenými klienty. SignalR postará se o všechno potřebné k tomu, aby bylo možné komunikaci mezi klientem a klientem v reálném čase.

Konfigurace SignalR center

Middleware SignalR vyžaduje některé služby, které jsou nakonfigurovány voláním AddSignalR:

services.AddSignalR();

Při přidávání SignalR funkcí do aplikace ASP.NET Core nastavte SignalR trasy voláním UseSignalR metody Startup.Configure :

app.UseSignalR(route =>
{
    route.MapHub<ChatHub>("/chathub");
});

Vytváření a používání center

Vytvořte centrum deklarováním třídy, která dědí z Hub, a přidejte do ní veřejné metody. Klienti mohou volat metody definované takto public:

public class ChatHub : Hub
{
    public Task SendMessage(string user, string message)
    {
        return Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}

Můžete zadat návratový typ a parametry, včetně komplexních typů a polí, stejně jako v jakékoli metodě jazyka C#. SignalR zpracovává serializaci a deserializaci složitých objektů a polí v parametrech a návratových hodnotách.

Poznámka:

Rozbočovače jsou přechodné:

  • Neukládejte stav ve vlastnosti třídy centra. Každé volání metody centra se provádí v nové instanci centra.
  • Vytvořte instanci centra přímo prostřednictvím injektáže závislostí. K odesílání zpráv klientovi z jiného prostředí aplikace použijte příkaz IHubContext.
  • Používá se await při volání asynchronních metod, které závisí na udržování centra. Například metoda Clients.All.SendAsync(...) může selhat, pokud je volána bez await a metoda centra se dokončí před SendAsync dokončením.

Kontextový objekt

Třída HubContext vlastnost, která obsahuje následující vlastnosti s informacemi o připojení:

Vlastnost Popis
ConnectionId Získá jedinečné ID pro připojení přiřazeno SignalR. Pro každé připojení existuje jedno ID připojení.
UserIdentifier Získá identifikátor uživatele. Ve výchozím nastavení SignalR se jako identifikátor uživatele používá ClaimTypes.NameIdentifier z ClaimsPrincipal přidruženého připojení.
User ClaimsPrincipal Získá přidružené k aktuálnímu uživateli.
Items Získá kolekci klíč/hodnota, která se dá použít ke sdílení dat v rámci tohoto připojení. Data mohou být uložena v této kolekci a budou zachována pro připojení napříč různými vyvoláním metod centra.
Features Získá kolekci funkcí dostupných v připojení. Prozatím tato kolekce není ve většině scénářů potřebná, takže zatím není podrobně zdokumentovaná.
ConnectionAborted CancellationToken Získá upozornění, když je připojení přerušeno.

Hub.Context obsahuje také následující metody:

metoda Popis
GetHttpContext HttpContext Vrátí pro připojení nebo null pokud připojení není přidružené k požadavku HTTP. Pro připojení HTTP můžete pomocí této metody získat informace, jako jsou hlavičky HTTP a řetězce dotazů.
Abort Přeruší připojení.

Objekt Klienti

Třída HubClients vlastnost, která obsahuje následující vlastnosti pro komunikaci mezi serverem a klientem:

Vlastnost Popis
All Volá metodu pro všechny připojené klienty.
Caller Volá metodu na klientovi, který vyvolal metodu centra.
Others Volá metodu pro všechny připojené klienty s výjimkou klienta, který vyvolal metodu.

Hub.Clients obsahuje také následující metody:

metoda Popis
AllExcept Volá metodu pro všechny připojené klienty s výjimkou zadaných připojení.
Client Zavolá metodu pro konkrétního připojeného klienta.
Clients Volání metody pro konkrétní připojené klienty
Group Volá metodu pro všechna připojení v zadané skupině.
GroupExcept Volá metodu pro všechna připojení v zadané skupině s výjimkou zadaných připojení.
Groups Volá metodu pro více skupin připojení.
OthersInGroup Volá metodu ve skupině připojení s výjimkou klienta, který vyvolal metodu centra.
User Volá metodu pro všechna připojení přidružená ke konkrétnímu uživateli.
Users Volá metodu pro všechna připojení přidružená k zadaným uživatelům.

Každá vlastnost nebo metoda v předchozích tabulkách vrací objekt s metodou SendAsync . Tato SendAsync metoda umožňuje zadat název a parametry klientské metody, které se mají volat.

Odesílání zpráv klientům

Pokud chcete volat konkrétní klienty, použijte vlastnosti objektu Clients . V následujícím příkladu existují tři metody centra:

  • SendMessageodešle zprávu všem připojeným klientům pomocí .Clients.All
  • SendMessageToCaller odešle zprávu zpět volajícímu pomocí funkce Clients.Caller.
  • SendMessageToGroup odešle zprávu všem klientům ve skupině SignalR Users .
public Task SendMessage(string user, string message)
{
    return Clients.All.SendAsync("ReceiveMessage", user, message);
}

public Task SendMessageToCaller(string user, string message)
{
    return Clients.Caller.SendAsync("ReceiveMessage", user, message);
}

public Task SendMessageToGroup(string user, string message)
{
    return Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);
}

Rozbočovače silného typu

Nevýhodou použití SendAsync je, že spoléhá na magický řetězec k určení klientské metody, která se má volat. Pokud je název metody chybně napsaný nebo chybí v klientovi, ponechá kód otevřený chybám za běhu.

Alternativou k použití SendAsync je silného typu s Hub Hub<T>. V následujícím příkladu ChatHub byly klientské metody extrahovány do rozhraní s názvem IChatClient.

public interface IChatClient
{
    Task ReceiveMessage(string user, string message);
}

Toto rozhraní lze použít k refaktoringu ChatHub předchozího příkladu:

    public class StronglyTypedChatHub : Hub<IChatClient>
    {
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.ReceiveMessage(user, message);
        }

        public Task SendMessageToCaller(string user, string message)
        {
            return Clients.Caller.ReceiveMessage(user, message);
        }
}

Použití Hub<IChatClient> umožňuje kontrolu doby kompilace klientských metod. To brání problémům způsobeným používáním magických řetězců, protože Hub<T> může poskytovat přístup pouze k metodám definovaným v rozhraní.

Použití silného typu Hub<T> zakáže možnost používat SendAsync. Všechny metody definované v rozhraní mohou být stále definovány jako asynchronní. Ve skutečnosti by každá z těchto metod měla vrátit Taskhodnotu . Vzhledem k tomu, že se jedná o rozhraní, nepoužívejte async klíčové slovo. Příklad:

public interface IClient
{
    Task ClientMethod();
}

Poznámka:

Přípona Async není z názvu metody odebrána. Pokud není .on('MyMethodAsync')definovaná vaše metoda klienta , neměli byste ji používat MyMethodAsync jako název.

Změna názvu metody centra

Ve výchozím nastavení je název metody centra serveru název metody .NET. Můžete však použít HubMethodName atribut změnit toto výchozí a ručně zadat název metody. Při vyvolání metody by měl klient místo názvu metody .NET použít tento název:

[HubMethodName("SendMessageToUser")]
public Task DirectMessage(string user, string message)
{
    return Clients.User(user).SendAsync("ReceiveMessage", user, message);
}

Zpracování událostí pro připojení

Rozhraní SignalR API služby Hubs poskytuje OnConnectedAsync a OnDisconnectedAsync virtuální metody pro správu a sledování připojení. Přepište virtuální metodu OnConnectedAsync , aby prováděla akce, když se klient připojí k centru, jako je například jeho přidání do skupiny:

public override async Task OnConnectedAsync()
{
    await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
    await base.OnConnectedAsync();
}

Přepište virtuální metodu OnDisconnectedAsync , aby prováděla akce, když se klient odpojí. Pokud se klient záměrně odpojí (například voláním connection.stop()), exception parametr bude null. Pokud se ale klient odpojí kvůli chybě (například selhání sítě), exception parametr bude obsahovat výjimku popisující selhání:

public override async Task OnDisconnectedAsync(Exception exception)
{
    await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", "I", "disconnect");
    await base.OnDisconnectedAsync(exception);
}

RemoveFromGroupAsync nemusí být volána , OnDisconnectedAsyncje automaticky zpracována za vás.

Upozorňující

Upozornění zabezpečení: Zveřejnění ConnectionId může vést k zosobnění se zlými úmysly, pokud SignalR je server nebo verze klienta ASP.NET Core 2.2 nebo starší.

Zpracování chyb

Výjimky vyvolané metodami centra se odesílají klientovi, který metodu vyvolal. V javascriptovém klientovi invoke vrátí metoda JavaScript Promise. Když se klientovi zobrazí chyba s obslužnou rutinou připojenou k příslibu pomocí catch, vyvolá se a předá jako javascriptový Error objekt:

connection.invoke("SendMessage", user, message).catch(err => console.error(err));

Pokud vaše centrum vyvolá výjimku, připojení se nezavřou. Ve výchozím nastavení SignalR vrátí klientovi obecnou chybovou zprávu. Příklad:

Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'MethodName' on the server.

Neočekávané výjimky často obsahují citlivé informace, například název databázového serveru v výjimce aktivované v případě selhání připojení k databázi. SignalR nezpřístupňuje tyto podrobné chybové zprávy ve výchozím nastavení jako bezpečnostní opatření. Další informace o tom, proč jsou podrobnosti o výjimce potlačeny, najdete v tématu Aspekty zabezpečení v ASP.NET Core SignalR.

Pokud máte výjimečný stav, který chcete rozšířit do klienta, můžete použít HubException třídu. Pokud vyvoláte metodu HubException centra, SignalR odešlete klientovi celou zprávu, která nenímodifikovaná:

public Task ThrowException()
{
    throw new HubException("This error will be sent to the client!");
}

Poznámka:

SignalR odešle Message vlastnost výjimky pouze klientovi. Trasování zásobníku a další vlastnosti výjimky nejsou klientovi k dispozici.

Další materiály