Sdílet prostřednictvím


Pokyny pro ASP.NET Core BlazorSignalR

Poznámka:

Toto není nejnovější verze tohoto článku. Aktuální verzi najdete v tomto článku ve verzi .NET 9.

Upozorňující

Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v zásadách podpory .NET a .NET Core. Aktuální verzi najdete v tomto článku ve verzi .NET 9.

Důležité

Tyto informace se týkají předběžného vydání produktu, který může být podstatně změněn před komerčním vydáním. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.

Aktuální verzi najdete v tomto článku ve verzi .NET 9.

Tento článek vysvětluje, jak nakonfigurovat a spravovat SignalR připojení v Blazor aplikacích.

Obecné pokyny k konfiguraci ASP.NET Core SignalR najdete v tématech v části Přehled ASP.NET Základní SignalR oblasti dokumentace, zejména konfigurace ASP.NET CoreSignalR.

Aplikace na straně serveru používají ke komunikaci s prohlížečem ASP.NET Core SignalR . SignalRPodmínky hostování a škálování se vztahují na aplikace na straně serveru.

Blazor funguje nejlépe při použití protokolu WebSocket jako SignalR přenosu kvůli nižší latenci, spolehlivosti a zabezpečení. Dlouhé dotazování se používá SignalR , když webSockets není k dispozici nebo když je aplikace explicitně nakonfigurovaná tak, aby používala dlouhé dotazování.

Služba Azure SignalR s stavovým opětovným připojením

Stavové opětovné připojení (WithStatefulReconnect) bylo vydáno s .NET 8, ale v současné době se nepodporuje pro službu Azure SignalR . Další informace najdete v tématu Podpora stavových opětovného připojení? (Azure/azure-signalr č. 1878).

Komprese protokolu WebSocket pro komponenty interaktivního serveru

Ve výchozím nastavení jsou součásti interaktivního serveru:

  • Povolte kompresi připojení WebSocket. DisableWebSocketCompression (výchozí: false) řídí kompresi protokolu WebSocket.

  • Přijměte direktivu frame-ancestors CSP (Content Security Policy), která 'self'povoluje pouze vložení aplikace do <iframe> zdroje, ze kterého se aplikace obsluhuje při povolení komprese nebo při poskytnutí konfigurace kontextu WebSocket. ContentSecurityFrameAncestorPolicy řídí CSP frame-ancestors .

Poskytovatel frame-ancestors CSP je možné odebrat ručně nastavením hodnoty ContentSecurityFrameAncestorsPolicy na nullhodnotu , protože můžete chtít poskytovatele CSP nakonfigurovat centralizovaným způsobem. frame-ancestors Když je CSP spravován centralizovaným způsobem, je nutné při každém vykreslení prvního dokumentu použít zásadu. Nedoporučujeme úplně odebírat zásady, protože by mohla být aplikace zranitelná vůči útokům.

Slouží ConfigureWebSocketAcceptContext ke konfiguraci WebSocketAcceptContext připojení protokolu websocket používaných součástmi serveru. Ve výchozím nastavení se použije zásada, která umožňuje kompresi a nastaví CSP pro předky rámce definované v ContentSecurityFrameAncestorsPolicy .

Příklady použití:

Zakažte kompresi nastavením DisableWebSocketCompression , což snižuje ohrožení zabezpečení aplikace na útok, ale může vést ke truesnížení výkonu:

builder.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode(o => o.DisableWebSocketCompression = true)

Pokud je povolená komprese, nakonfigurujte přísnější frame-ancestors CSP s hodnotou 'none' (vyžaduje se jednoduché uvozovky), která umožňuje kompresi Protokolu WebSocket, ale brání prohlížečům v vložení aplikace do libovolné <iframe>:

builder.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode(o => o.ContentSecurityFrameAncestorsPolicy = "'none'")

Pokud je povolena komprese, odeberte frame-ancestors CSP nastavením ContentSecurityFrameAncestorsPolicy na null. Tento scénář se doporučuje jenom pro aplikace, které nastavují CSP centralizovaným způsobem:

builder.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode(o => o.ContentSecurityFrameAncestorsPolicy = null)

Důležité

Prohlížeče používají direktivy CSP z více hlaviček CSP pomocí nejtriknější hodnoty direktiv zásad. Vývojář proto nemůže přidat slabší frame-ancestors zásadu, než 'self' je účel nebo omylem.

Jednoduché uvozovky jsou vyžadovány pro řetězcovou hodnotu předanou ContentSecurityFrameAncestorsPolicy:

Nepodporované hodnoty: none, self

'self'

Mezi další možnosti patří zadání jednoho nebo více zdrojů hostitelů a zdrojů schématu.

Vliv na zabezpečení najdete v doprovodných materiálech ke zmírnění hrozeb pro interaktivní vykreslování na straně serveru ASP.NET CoreBlazor. Další informace o direktivě frame-ancestors najdete v tématu CSP: frame-ancestors (Dokumentace k MDN).

Zakázání komprese odpovědí pro Opětovné načítání za provozu

Při použití Opětovné načítání za provozu zakažte middleware pro kompresi odpovědí v Development prostředí. Bez ohledu na to, jestli se používá výchozí kód ze šablony projektu, vždy volejte UseResponseCompression nejprve v kanálu zpracování požadavků.

V souboru Program:

if (!app.Environment.IsDevelopment())
{
    app.UseResponseCompression();
}

Vyjednávání mezi zdroji na straně SignalR klienta pro ověřování

Tato část vysvětluje, jak nakonfigurovat SignalRzákladního klienta pro odesílání přihlašovacích údajů, jako jsou soubory cookie nebo hlavičky ověřování HTTP.

Slouží SetBrowserRequestCredentials k nastavení Include požadavků mezi zdroji fetch .

IncludeRequestCredentialsMessageHandler.cs:

using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.WebAssembly.Http;

public class IncludeRequestCredentialsMessageHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        request.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);
        return base.SendAsync(request, cancellationToken);
    }
}

Kde je vytvořené připojení rozbočovače HttpMessageHandler , přiřaďte k HttpMessageHandlerFactory této možnosti:

private HubConnectionBuilder? hubConnection;

...

hubConnection = new HubConnectionBuilder()
    .WithUrl(new Uri(Navigation.ToAbsoluteUri("/chathub")), options =>
    {
        options.HttpMessageHandlerFactory = innerHandler => 
            new IncludeRequestCredentialsMessageHandler { InnerHandler = innerHandler };
    }).Build();

Předchozí příklad nakonfiguruje adresu URL připojení centra na absolutní adresu URI na /chathubadrese . Identifikátor URI lze také nastavit pomocí řetězce, například https://signalr.example.comnebo prostřednictvím konfigurace. Navigation je injektáž NavigationManager.

Další informace najdete v tématu ASP.NET Konfigurace jádraSignalR.

Vykreslování na straně klienta

Pokud je nakonfigurované předrenderování, před navázáním připojení klienta k serveru dojde k předběžnému vytvoření. Další informace naleznete v tématu Prerender ASP.NET Základní Razor komponenty.

Pokud je nakonfigurované předrenderování, před navázáním připojení klienta k serveru dojde k předběžnému vytvoření. Další informace najdete v následujících článcích:

Předem vytyčovaná velikost stavu a SignalR omezení velikosti zprávy

Velká předsekunutá velikost stavu může překročit BlazorSignalR limit velikosti zprávy okruhu, což má za následek následující:

  • Okruh SignalR se nepodaří inicializovat s chybou v klientovi: Circuit host not initialized.
  • Uživatelské rozhraní pro opětovné připojení v klientovi se zobrazí, když okruh selže. Obnovení není možné.

Pokud chcete tento problém vyřešit, použijte některý z následujících přístupů:

  • Snižte množství dat, která vkládáte do předkažovaného stavu.
  • SignalR Zvětšete limit velikosti zprávy. UPOZORNĚNÍ: Zvýšení limitu může zvýšit riziko útoků DoS (DoS).

Další prostředky na straně klienta

Použití spřažení relací (rychlé relace) pro hostování webfarm na straně serveru

Pokud se používá více než jeden back-endový server, musí aplikace implementovat spřažení relací, označované také jako rychlé relace. Spřažení relace zajišťuje, že se okruh klienta znovu připojí ke stejnému serveru, pokud dojde k vyřazení připojení, což je důležité, protože stav klienta se uchovává pouze v paměti serveru, který poprvé navazoval okruh klienta.

Následující chyba je vyvolán aplikací, která ve webfarmu nepovolila spřažení relací:

Uncaught (in promise) Error: Invocation canceled due to the underlying connection being closed.

Další informace o spřažení relací s hostování služby Aplikace Azure Najdete v tématu Hostování a nasazování aplikací na straně Blazor serveru ASP.NET Core.

Služba Azure SignalR

Volitelná služba Azure SignalR funguje ve spojení s centrem aplikace SignalR pro vertikální navýšení kapacity aplikace na straně serveru na velký počet souběžných připojení. Globální dosah služby a vysoce výkonná datová centra navíc výrazně pomáhají snížit latenci kvůli zeměpisné poloze.

Služba se nevyžaduje pro Blazor aplikace hostované ve službě Aplikace Azure Service nebo Azure Container Apps, ale může být užitečná v jiných hostitelských prostředích:

  • Pro usnadnění horizontálního navýšení kapacity připojení.
  • Zpracování globální distribuce

Další informace najdete v tématu Hostování a nasazování aplikací na straně Blazorserveru ASP.NET Core.

Možnosti obslužné rutiny okruhu na straně serveru

Nakonfigurujte okruh pomocí CircuitOptions. Umožňuje zobrazit výchozí hodnoty ve zdroji odkazu.

Poznámka:

Odkazy na dokumentaci k referenčnímu zdroji .NET obvykle načítají výchozí větev úložiště, která představuje aktuální vývoj pro příští verzi .NET. Pokud chcete vybrat značku pro konkrétní verzi, použijte rozevírací seznam pro přepnutí větví nebo značek. Další informace najdete v tématu Jak vybrat značku verze zdrojového kódu ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Přečtěte si nebo nastavte možnosti v Program souboru s delegátem možností na AddInteractiveServerComponents. Zástupný {OPTION} symbol představuje možnost a {VALUE} zástupný symbol je hodnota.

V souboru Program:

builder.Services.AddRazorComponents().AddInteractiveServerComponents(options =>
{
    options.{OPTION} = {VALUE};
});

Přečtěte si nebo nastavte možnosti v Program souboru s delegátem možností na AddServerSideBlazor. Zástupný {OPTION} symbol představuje možnost a {VALUE} zástupný symbol je hodnota.

V souboru Program:

builder.Services.AddServerSideBlazor(options =>
{
    options.{OPTION} = {VALUE};
});

Přečtěte si nebo nastavte možnosti Startup.ConfigureServices pomocí delegáta možností na AddServerSideBlazor. Zástupný {OPTION} symbol představuje možnost a {VALUE} zástupný symbol je hodnota.

In Startup.ConfigureServices of Startup.cs:

services.AddServerSideBlazor(options =>
{
    options.{OPTION} = {VALUE};
});

Chcete-li konfigurovat HubConnectionContext, použijte s HubConnectionContextOptions AddHubOptions. Zobrazení výchozích hodnot pro možnosti kontextu připojení centra v referenčním zdroji Popisy možností v dokumentaci najdete v SignalR tématu konfigurace ASP.NET CoreSignalR. Zástupný {OPTION} symbol představuje možnost a {VALUE} zástupný symbol je hodnota.

Poznámka:

Odkazy na dokumentaci k referenčnímu zdroji .NET obvykle načítají výchozí větev úložiště, která představuje aktuální vývoj pro příští verzi .NET. Pokud chcete vybrat značku pro konkrétní verzi, použijte rozevírací seznam pro přepnutí větví nebo značek. Další informace najdete v tématu Jak vybrat značku verze zdrojového kódu ASP.NET Core (dotnet/AspNetCore.Docs #26205).

V souboru Program:

builder.Services.AddRazorComponents().AddInteractiveServerComponents().AddHubOptions(options =>
{
    options.{OPTION} = {VALUE};
});

V souboru Program:

builder.Services.AddServerSideBlazor().AddHubOptions(options =>
{
    options.{OPTION} = {VALUE};
});

In Startup.ConfigureServices of Startup.cs:

services.AddServerSideBlazor().AddHubOptions(options =>
{
    options.{OPTION} = {VALUE};
});

Upozorňující

Výchozí hodnota MaximumReceiveMessageSize je 32 kB. Zvýšení hodnoty může zvýšit riziko útoků DoS (Denial of Service).

Blazor spoléhá na MaximumParallelInvocationsPerClient hodnotu 1, což je výchozí hodnota. Další informace naleznete v tématu MaximumParallelInvocationsPerClient > 1 break file upload in Blazor Server mode (dotnet/aspnetcore #53951).

Informace o správě paměti najdete v tématu Hostování a nasazování aplikací na straně Blazor serveru ASP.NET Core.

Blazor Možnosti rozbočovače

Nakonfigurujte MapBlazorHub možnosti pro řízení HttpConnectionDispatcherOptions Blazor centra. Zobrazení výchozích hodnot pro možnosti dispečeru připojení rozbočovače ve zdroji odkazů Zástupný {OPTION} symbol představuje možnost a {VALUE} zástupný symbol je hodnota.

Poznámka:

Odkazy na dokumentaci k referenčnímu zdroji .NET obvykle načítají výchozí větev úložiště, která představuje aktuální vývoj pro příští verzi .NET. Pokud chcete vybrat značku pro konkrétní verzi, použijte rozevírací seznam pro přepnutí větví nebo značek. Další informace najdete v tématu Jak vybrat značku verze zdrojového kódu ASP.NET Core (dotnet/AspNetCore.Docs #26205).

app.MapBlazorHub Volání umístěte za voláním app.MapRazorComponents do souboru aplikaceProgram:

app.MapBlazorHub(options =>
{
    options.{OPTION} = {VALUE};
});

Konfigurace centra používaného AddInteractiveServerRenderMode s MapBlazorHub chybou s chybou AmbiguousMatchException:

Microsoft.AspNetCore.Routing.Matching.AmbiguousMatchException: The request matched multiple endpoints.

Pokud chcete tento problém vyřešit u aplikací, které cílí na .NET 8, dejte vlastní nakonfigurované Blazor rozbočovači vyšší prioritu WithOrder pomocí metody:

app.MapBlazorHub(options =>
{
    options.CloseOnAuthenticationExpiration = true;
}).WithOrder(-1);

Další informace naleznete v následujících zdrojích:

Do souboru aplikace Program zadejte možnostiapp.MapBlazorHub:

app.MapBlazorHub(options =>
{
    options.{OPTION} = {VALUE};
});

Zadejte možnosti app.MapBlazorHub konfigurace směrování koncového bodu:

app.UseEndpoints(endpoints =>
{
    endpoints.MapBlazorHub(options =>
    {
        options.{OPTION} = {VALUE};
    });
    ...
});

Maximální velikost příjmu zprávy

Tato část se vztahuje pouze na projekty, které implementují SignalR.

Maximální povolená velikost příchozí SignalR zprávy pro metody rozbočovače je omezená HubOptions.MaximumReceiveMessageSize (výchozí hodnota: 32 kB). SignalR zprávy větší než MaximumReceiveMessageSize vyvolá chybu. Architektura neukládá omezení velikosti SignalR zprávy z centra na klienta.

Pokud SignalR není protokolování nastavené na Ladění nebo Trasování, zobrazí se chyba velikosti zprávy jenom v konzole vývojářských nástrojů prohlížeče:

Chyba: Připojení bylo odpojeno s chybou Chyba: Server vrátil chybu při zavření: Připojení se ukončilo s chybou.

Pokud SignalR je protokolování na straně serveru nastaveno na ladění nebo trasování, protokolování na straně serveru zobrazí InvalidDataException chybu velikosti zprávy.

appsettings.Development.json:

{
  "DetailedErrors": true,
  "Logging": {
    "LogLevel": {
      ...
      "Microsoft.AspNetCore.SignalR": "Debug"
    }
  }
}

Chyba:

System.IO.InvalidDataException: Byla překročena maximální velikost zprávy 32768B. Velikost zprávy se dá nakonfigurovat v AddHubOptions.

Jedním z přístupů je zvýšení limitu nastavením MaximumReceiveMessageSize v Program souboru. Následující příklad nastaví maximální velikost příjmu zprávy na 64 kB:

builder.Services.AddRazorComponents().AddInteractiveServerComponents()
    .AddHubOptions(options => options.MaximumReceiveMessageSize = 64 * 1024);

Zvýšení limitu SignalR velikosti příchozích zpráv je nákladné vyžadovat více prostředků serveru a zvyšuje riziko útoků DoS (DoS). Navíc čtení velkého množství obsahu do paměti jako řetězců nebo bajtových polí může také vést k přidělení, která pracují špatně s uvolňováním paměti, což vede k dalším sankcím za výkon.

Lepší možností pro čtení velkých datových částí je odeslat obsah v menších blocích a zpracovat datovou část jako .Stream To se dá použít při čtení velkých datových částí JSON zprostředkovatele komunikace JavaScriptuJS nebo při JS dostupnosti dat zprostředkovatele komunikace jako nezpracovaných bajtů. Příklad, který ukazuje odesílání velkých binárních datových částí v serverových aplikacích, které používají techniky podobné InputFile komponentě, najdete v ukázkové aplikaci Binary Submit a BlazorInputLargeTextArea v ukázce komponenty.

Poznámka:

Odkazy na dokumentaci k referenčnímu zdroji .NET obvykle načítají výchozí větev úložiště, která představuje aktuální vývoj pro příští verzi .NET. Pokud chcete vybrat značku pro konkrétní verzi, použijte rozevírací seznam pro přepnutí větví nebo značek. Další informace najdete v tématu Jak vybrat značku verze zdrojového kódu ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Formuláře, které zpracovávají velké datové části, SignalR můžou také přímo používat komunikaci streamování JS . Další informace naleznete v tématu Volání metod .NET z funkcí JavaScriptu v ASP.NET Core Blazor. Příklad formulářů, který streamuje <textarea> data na server, najdete v tématu Řešení potíží s formuláři ASP.NET CoreBlazor.

Jedním z přístupů je zvýšení limitu nastavením MaximumReceiveMessageSize v Program souboru. Následující příklad nastaví maximální velikost příjmu zprávy na 64 kB:

builder.Services.AddServerSideBlazor()
    .AddHubOptions(options => options.MaximumReceiveMessageSize = 64 * 1024);

Zvýšení limitu SignalR velikosti příchozích zpráv je nákladné vyžadovat více prostředků serveru a zvyšuje riziko útoků DoS (DoS). Navíc čtení velkého množství obsahu do paměti jako řetězců nebo bajtových polí může také vést k přidělení, která pracují špatně s uvolňováním paměti, což vede k dalším sankcím za výkon.

Lepší možností pro čtení velkých datových částí je odeslat obsah v menších blocích a zpracovat datovou část jako .Stream To se dá použít při čtení velkých datových částí JSON zprostředkovatele komunikace JavaScriptuJS nebo při JS dostupnosti dat zprostředkovatele komunikace jako nezpracovaných bajtů. Příklad, který ukazuje odesílání velkých binárních datových částí, které Blazor Server používají techniky podobné InputFile komponentě, najdete v ukázkové aplikaci Binary Submit aInputLargeTextArea Blazorv ukázce komponenty.

Poznámka:

Odkazy na dokumentaci k referenčnímu zdroji .NET obvykle načítají výchozí větev úložiště, která představuje aktuální vývoj pro příští verzi .NET. Pokud chcete vybrat značku pro konkrétní verzi, použijte rozevírací seznam pro přepnutí větví nebo značek. Další informace najdete v tématu Jak vybrat značku verze zdrojového kódu ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Formuláře, které zpracovávají velké datové části, SignalR můžou také přímo používat komunikaci streamování JS . Další informace naleznete v tématu Volání metod .NET z funkcí JavaScriptu v ASP.NET Core Blazor. Příklad formulářů, který streamuje <textarea> data v aplikaci, najdete v Blazor Server tématu Řešení potíží s formuláři ASP.NET CoreBlazor.

Zvýšení limitu nastavením MaximumReceiveMessageSize v Startup.ConfigureServices:

services.AddServerSideBlazor()
    .AddHubOptions(options => options.MaximumReceiveMessageSize = 64 * 1024);

Zvýšení limitu SignalR velikosti příchozích zpráv je nákladné vyžadovat více prostředků serveru a zvyšuje riziko útoků DoS (DoS). Navíc čtení velkého množství obsahu do paměti jako řetězců nebo bajtových polí může také vést k přidělení, která pracují špatně s uvolňováním paměti, což vede k dalším sankcím za výkon.

Při vývoji kódu, který přenáší velké množství dat, zvažte následující pokyny:

  • Využijte nativní podporu spolupráce streamování JS k přenosu dat větších než SignalR limitu velikosti příchozích zpráv:
  • Obecné tipy:
    • Nepřidělujte velké objekty v JS kódu jazyka C#.
    • Volné spotřebované paměti po dokončení nebo zrušení procesu
    • Vynucujte následující další požadavky pro účely zabezpečení:
      • Deklarujte maximální velikost souboru nebo dat, které lze předat.
      • Deklarujte minimální rychlost nahrávání z klienta na server.
    • Po přijetí dat serverem mohou být tato data následující:
      • Dočasně uložené v vyrovnávací paměti, dokud se neshromáždí všechny segmenty.
      • Spotřebováno okamžitě. Data se například dají okamžitě uložit do databáze nebo zapisovat na disk při přijetí jednotlivých segmentů.
  • Rozdělte data na menší části a posílejte datové segmenty postupně, dokud server neobdrží všechna data.
  • Nepřidělujte velké objekty v JS kódu jazyka C#.
  • Při odesílání nebo přijímání dat neblokujte hlavní vlákno uživatelského rozhraní po dlouhou dobu.
  • Volné spotřebované paměti po dokončení nebo zrušení procesu
  • Vynucujte následující další požadavky pro účely zabezpečení:
    • Deklarujte maximální velikost souboru nebo dat, které lze předat.
    • Deklarujte minimální rychlost nahrávání z klienta na server.
  • Po přijetí dat serverem mohou být tato data následující:
    • Dočasně uložené v vyrovnávací paměti, dokud se neshromáždí všechny segmenty.
    • Spotřebováno okamžitě. Data se například dají okamžitě uložit do databáze nebo zapisovat na disk při přijetí jednotlivých segmentů.

Blazor Konfigurace směrování koncového bodu centra na straně serveru

Program Voláním v souboru MapBlazorHub namapujte BlazorHub výchozí cestu aplikace. Skript Blazor (blazor.*.js) automaticky odkazuje na koncový bod vytvořený MapBlazorHub.

Reflektujte stav připojení na straně serveru v uživatelském rozhraní.

Pokud klient zjistí ztracené připojení k serveru, zobrazí se uživateli výchozí uživatelské rozhraní, zatímco se klient pokusí znovu připojit:

Výchozí uživatelské rozhraní pro opětovné připojení.

Výchozí uživatelské rozhraní pro opětovné připojení.

Pokud se opětovné připojení nezdaří, uživateli se zobrazí pokyn, aby se znovu zkusil nebo znovu načte stránku:

Výchozí uživatelské rozhraní opakování.

Výchozí uživatelské rozhraní opakování.

Pokud opětovné připojení proběhne úspěšně, stav uživatele se často ztratí. Vlastní kód lze přidat do libovolné komponenty, aby se při selhání připojení uložil a znovu načítá stav uživatele. Další informace najdete v tématu ASP.NET Blazor základní správa stavu.

Pokud chcete uživatelské rozhraní přizpůsobit, definujte jeden prvek s obsahem id components-reconnect-modal elementu <body> . Následující příklad umístí prvek do App komponenty.

App.razor:

Pokud chcete uživatelské rozhraní přizpůsobit, definujte jeden prvek s obsahem id components-reconnect-modal elementu <body> . Následující příklad umístí prvek na stránku hostitele.

Pages/_Host.cshtml:

Pokud chcete uživatelské rozhraní přizpůsobit, definujte jeden prvek s obsahem id components-reconnect-modal elementu <body> . Následující příklad umístí prvek na stránku rozložení.

Pages/_Layout.cshtml:

Pokud chcete uživatelské rozhraní přizpůsobit, definujte jeden prvek s obsahem id components-reconnect-modal elementu <body> . Následující příklad umístí prvek na stránku hostitele.

Pages/_Host.cshtml:

<div id="components-reconnect-modal">
    Connection lost.<br>Attempting to reconnect...
</div>

Poznámka:

Pokud aplikace vykresluje více než jeden prvek, id components-reconnect-modal obdrží pouze první vykreslený prvek změny třídy CSS k zobrazení nebo skrytí elementu.

Do šablony stylů webu přidejte následující styly CSS.

wwwroot/app.css:

wwwroot/css/site.css:

#components-reconnect-modal {
    display: none;
}

#components-reconnect-modal.components-reconnect-show, 
#components-reconnect-modal.components-reconnect-failed, 
#components-reconnect-modal.components-reconnect-rejected {
    display: block;
    background-color: white;
    padding: 2rem;
    border-radius: 0.5rem;
    text-align: center;
    box-shadow: 0 3px 6px 2px rgba(0, 0, 0, 0.3);
    margin: 50px 50px;
    position: fixed;
    top: 0;
    z-index: 10001;
}

Následující tabulka popisuje třídy CSS použité u components-reconnect-modal elementu rozhraním Blazor .

CSS – třída Označuje...
components-reconnect-show Ztracené připojení. Klient se pokouší znovu připojit. Zobrazit modální.
components-reconnect-hide Na serveru se znovu naváže aktivní připojení. Skryjte modální.
components-reconnect-failed Opětovné připojení se nezdařilo, pravděpodobně kvůli selhání sítě. Pokud se chcete pokusit znovu připojit, zavolejte window.Blazor.reconnect() v JavaScriptu.
components-reconnect-rejected Opětovné připojení bylo odmítnuto. Server byl dosažen, ale odmítl připojení a stav uživatele na serveru se ztratil. Pokud chcete aplikaci znovu načíst, zavolejte location.reload() v JavaScriptu. Tento stav připojení může mít za následek následující:
  • V okruhu na straně serveru dojde k chybovému ukončení.
  • Klient se odpojí dostatečně dlouho, aby server zahodil stav uživatele. Instance komponent uživatele jsou uvolněny.
  • Server se restartuje nebo se pracovní proces aplikace recykluje.

Přizpůsobte zpoždění před zobrazením uživatelského rozhraní pro opětovné připojení nastavením transition-delay vlastnosti v šabloně stylů CSS webu pro modální prvek. Následující příklad nastaví zpoždění přechodu z 500 ms (výchozí) na 1 000 ms (1 sekunda).

wwwroot/app.css:

wwwroot/css/site.css:

#components-reconnect-modal {
    transition: visibility 0s linear 1000ms;
}

Chcete-li zobrazit aktuální pokus o opětovné připojení, definujte prvek s hodnotou .id components-reconnect-current-attempt Chcete-li zobrazit maximální počet opakovaných pokusů o opětovné připojení, definujte prvek s znakem id components-reconnect-max-retries. Následující příklad umístí tyto prvky do modálního prvku pokusu o opětovné připojení za předchozím příkladem.

<div id="components-reconnect-modal">
    There was a problem with the connection!
    (Current reconnect attempt: 
    <span id="components-reconnect-current-attempt"></span> /
    <span id="components-reconnect-max-retries"></span>)
</div>

Když se zobrazí modální modál vlastního opětovného připojení, vykreslí následující obsah s čítačem pokusu o opětovné připojení:

Došlo k problému s připojením! (Aktuální pokus o opětovné připojení: 1 / 8)

Vykreslování na straně serveru

Ve výchozím nastavení jsou komponenty předváděné na serveru před navázáním připojení klienta k serveru. Další informace naleznete v tématu Prerender ASP.NET Základní Razor komponenty.

Ve výchozím nastavení jsou komponenty předváděné na serveru před navázáním připojení klienta k serveru. Další informace naleznete v nápovědě značky komponenty v ASP.NET Core.

Monitorování aktivity okruhu na straně serveru

Monitorování příchozí aktivity okruhu CreateInboundActivityHandler pomocí metody on CircuitHandler. Příchozí aktivita okruhu je jakákoli aktivita odesílaná z prohlížeče na server, například události uživatelského rozhraní nebo JavaScript-to-.NET volání zprostředkovatele komunikace.

Pomocí obslužné rutiny aktivity okruhu můžete například zjistit, jestli je klient nečinný, a protokolovat ID jeho okruhu (Circuit.Id):

using Microsoft.AspNetCore.Components.Server.Circuits;
using Microsoft.Extensions.Options;
using Timer = System.Timers.Timer;

public sealed class IdleCircuitHandler : CircuitHandler, IDisposable
{
    private Circuit? currentCircuit;
    private readonly ILogger logger;
    private readonly Timer timer;

    public IdleCircuitHandler(ILogger<IdleCircuitHandler> logger, 
        IOptions<IdleCircuitOptions> options)
    {
        timer = new Timer
        {
            Interval = options.Value.IdleTimeout.TotalMilliseconds,
            AutoReset = false
        };

        timer.Elapsed += CircuitIdle;
        this.logger = logger;
    }

    private void CircuitIdle(object? sender, System.Timers.ElapsedEventArgs e)
    {
        logger.LogInformation("{CircuitId} is idle", currentCircuit?.Id);
    }

    public override Task OnCircuitOpenedAsync(Circuit circuit, 
        CancellationToken cancellationToken)
    {
        currentCircuit = circuit;

        return Task.CompletedTask;
    }

    public override Func<CircuitInboundActivityContext, Task> CreateInboundActivityHandler(
        Func<CircuitInboundActivityContext, Task> next)
    {
        return context =>
        {
            timer.Stop();
            timer.Start();

            return next(context);
        };
    }

    public void Dispose() => timer.Dispose();
}

public class IdleCircuitOptions
{
    public TimeSpan IdleTimeout { get; set; } = TimeSpan.FromMinutes(5);
}

public static class IdleCircuitHandlerServiceCollectionExtensions
{
    public static IServiceCollection AddIdleCircuitHandler(
        this IServiceCollection services, 
        Action<IdleCircuitOptions> configureOptions)
    {
        services.Configure(configureOptions);
        services.AddIdleCircuitHandler();

        return services;
    }

    public static IServiceCollection AddIdleCircuitHandler(
        this IServiceCollection services)
    {
        services.AddScoped<CircuitHandler, IdleCircuitHandler>();

        return services;
    }
}

Zaregistrujte službu v Program souboru. Následující příklad nakonfiguruje výchozí časový limit nečinnosti pět minut až pět sekund, aby bylo možné otestovat předchozí IdleCircuitHandler implementaci:

builder.Services.AddIdleCircuitHandler(options => 
    options.IdleTimeout = TimeSpan.FromSeconds(5));

Obslužné rutiny aktivit okruhu také poskytují přístup k vymezeným Blazor službám z jinýchBlazor oborů injektáže závislostí (DI). Další informace a příklady najdete tady:

Blazor spuštění

Nakonfigurujte ruční spuštění okruhu BlazorSignalR v App.razor souboru Blazor Web App:

Nakonfigurujte ruční spuštění okruhu BlazorSignalR Pages/_Host.cshtml v souboru ():Blazor Server

Nakonfigurujte ruční spuštění okruhu BlazorSignalR Pages/_Layout.cshtml v souboru ():Blazor Server

Nakonfigurujte ruční spuštění okruhu BlazorSignalR Pages/_Host.cshtml v souboru ():Blazor Server

  • autostart="false" Přidejte do značky blazor.*.js atribut <script> pro skript.
  • Umístěte skript, který volá Blazor.start() po Blazor načtení skriptu a uvnitř koncové </body> značky.

Pokud autostart je zakázána, funguje každý aspekt aplikace, který není závislý na okruhu normálně. Například směrování na straně klienta je funkční. Jakýkoli aspekt, který závisí na okruhu, ale není funkční, dokud Blazor.start() se nevolá. Chování aplikace je nepředvídatelné bez zavedeného okruhu. Například metody komponent se nespustí při odpojení okruhu.

Další informace, včetně toho, jak inicializovatBlazor, když je dokument připravený a jak se zřetězit s JS Promise, najdete v tématu ASP.NET Spuštění CoreBlazor.

Konfigurace SignalR časových limitů a udržování aktivního na klientovi

Nakonfigurujte pro klienta následující hodnoty:

  • withServerTimeout: Nakonfiguruje časový limit serveru v milisekundách. Pokud tento časový limit uplynou bez příjmu zpráv ze serveru, připojení se ukončí s chybou. Výchozí hodnota časového limitu je 30 sekund. Časový limit serveru by měl být alespoň dvojnásobný, než je hodnota přiřazená intervalu keep-Alive (withKeepAliveInterval).
  • withKeepAliveInterval: Nakonfiguruje interval Keep-Alive v milisekundách (výchozí interval, ve kterém se má server otestovat příkazem ping). Toto nastavení umožňuje serveru rozpoznat pevné odpojení, například když klient odpojí počítač od sítě. Příkaz ping se vyskytuje nejčastěji jako příkaz ping na serveru. Pokud server odešle příkaz ping každých pět sekund, přiřazování hodnoty nižší než 5000 (5 sekund) odešle příkaz ping každých pět sekund. Výchozí hodnota je 15 sekund. Interval Keep-Alive by měl být menší nebo roven polovině hodnoty přiřazené k vypršení časového limitu serveru (withServerTimeout).

Následující příklad souboru App.razor (Blazor Web App) ukazuje přiřazení výchozích hodnot.

Blazor Web App:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    circuit: {
      configureSignalR: function (builder) {
        builder.withServerTimeout(30000).withKeepAliveInterval(15000);
      }
    }
  });
</script>

Následující příklad souboru Pages/_Host.cshtml (Blazor Servervšechny verze kromě ASP.NET Core v .NET 6) nebo Pages/_Layout.cshtml soubor (Blazor ServerASP.NET Core v .NET 6).

Blazor Server:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    configureSignalR: function (builder) {
      builder.withServerTimeout(30000).withKeepAliveInterval(15000);
    }
  });
</script>

V předchozím příkladu {BLAZOR SCRIPT} je Blazor zástupný symbol cesta ke skriptu a název souboru. Umístění skriptu a cesty, které se má použít, najdete v tématu ASP.NET Struktura projektu CoreBlazor.

Při vytváření připojení rozbočovače v komponentě nastavte ServerTimeout (výchozí: 30 sekund) a KeepAliveInterval (výchozí: 15 sekund) na kartě HubConnectionBuilder. HandshakeTimeout Nastavte (výchozí: 15 sekund) na sestavené HubConnection. Následující příklad ukazuje přiřazení výchozích hodnot:

protected override async Task OnInitializedAsync()
{
    hubConnection = new HubConnectionBuilder()
        .WithUrl(Navigation.ToAbsoluteUri("/chathub"))
        .WithServerTimeout(TimeSpan.FromSeconds(30))
        .WithKeepAliveInterval(TimeSpan.FromSeconds(15))
        .Build();

    hubConnection.HandshakeTimeout = TimeSpan.FromSeconds(15);

    hubConnection.On<string, string>("ReceiveMessage", (user, message) => ...

    await hubConnection.StartAsync();
}

Nakonfigurujte pro klienta následující hodnoty:

  • serverTimeoutInMilliseconds: Časový limit serveru v milisekundách. Pokud tento časový limit uplynou bez příjmu zpráv ze serveru, připojení se ukončí s chybou. Výchozí hodnota časového limitu je 30 sekund. Časový limit serveru by měl být alespoň dvojnásobný, než je hodnota přiřazená intervalu keep-Alive (keepAliveIntervalInMilliseconds).
  • keepAliveIntervalInMilliseconds: Výchozí interval, ve kterém se má server otestovat příkazem ping. Toto nastavení umožňuje serveru rozpoznat pevné odpojení, například když klient odpojí počítač od sítě. Příkaz ping se vyskytuje nejčastěji jako příkaz ping na serveru. Pokud server odešle příkaz ping každých pět sekund, přiřazování hodnoty nižší než 5000 (5 sekund) odešle příkaz ping každých pět sekund. Výchozí hodnota je 15 sekund. Interval Keep-Alive by měl být menší nebo roven polovině hodnoty přiřazené k vypršení časového limitu serveru (serverTimeoutInMilliseconds).

Následující příklad souboru Pages/_Host.cshtml (Blazor Servervšechny verze kromě ASP.NET Core v .NET 6) nebo Pages/_Layout.cshtml soubor (Blazor ServerASP.NET Core v .NET 6):

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    configureSignalR: function (builder) {
      let c = builder.build();
      c.serverTimeoutInMilliseconds = 30000;
      c.keepAliveIntervalInMilliseconds = 15000;
      builder.build = () => {
        return c;
      };
    }
  });
</script>

V předchozím příkladu {BLAZOR SCRIPT} je Blazor zástupný symbol cesta ke skriptu a název souboru. Umístění skriptu a cesty, které se má použít, najdete v tématu ASP.NET Struktura projektu CoreBlazor.

Při vytváření připojení rozbočovače v komponentě nastavte ServerTimeout (výchozí: 30 sekund), HandshakeTimeout (výchozí: 15 sekund) a KeepAliveInterval (výchozí: 15 sekund) na sestavené HubConnection. Následující příklad ukazuje přiřazení výchozích hodnot:

protected override async Task OnInitializedAsync()
{
    hubConnection = new HubConnectionBuilder()
        .WithUrl(Navigation.ToAbsoluteUri("/chathub"))
        .Build();

    hubConnection.ServerTimeout = TimeSpan.FromSeconds(30);
    hubConnection.HandshakeTimeout = TimeSpan.FromSeconds(15);
    hubConnection.KeepAliveInterval = TimeSpan.FromSeconds(15);

    hubConnection.On<string, string>("ReceiveMessage", (user, message) => ...

    await hubConnection.StartAsync();
}

Při změně hodnot časového limitu serveru (ServerTimeout) nebo intervalu Keep-Alive (KeepAliveInterval):

  • Časový limit serveru by měl být alespoň dvojnásobný, než je hodnota přiřazená intervalu Keep-Alive.
  • Interval Keep-Alive by měl být menší nebo roven polovině hodnoty přiřazené k vypršení časového limitu serveru.

Další informace najdete v částech globálního nasazení a selhání připojení v následujících článcích:

Úprava obslužné rutiny opětovného připojení na straně serveru

Události připojení okruhu obslužné rutiny opětovného připojení je možné upravit pro vlastní chování, například:

  • Chcete-li upozornit uživatele, pokud je připojení ukončeno.
  • Pokud chcete provést protokolování (z klienta), když je okruh připojený.

Pokud chcete upravit události připojení, zaregistrujte zpětná volání pro následující změny připojení:

  • Vyřazená připojení se používají onConnectionDown.
  • Navázaná/navázaná připojení se používají onConnectionUp.

Musí být zadáno obojí onConnectionDown a onConnectionUp musí být zadáno.

Blazor Web App:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    circuit: {
      reconnectionHandler: {
        onConnectionDown: (options, error) => console.error(error),
        onConnectionUp: () => console.log("Up, up, and away!")
      }
    }
  });
</script>

Blazor Server:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    reconnectionHandler: {
      onConnectionDown: (options, error) => console.error(error),
      onConnectionUp: () => console.log("Up, up, and away!")
    }
  });
</script>

V předchozím příkladu {BLAZOR SCRIPT} je Blazor zástupný symbol cesta ke skriptu a název souboru. Umístění skriptu a cesty, které se má použít, najdete v tématu ASP.NET Struktura projektu CoreBlazor.

Automatická aktualizace stránky při selhání opětovného připojení na straně serveru

Výchozí chování opětovného připojení vyžaduje, aby uživatel po selhání opětovného připojení ručně aktualizoval stránku. K automatické aktualizaci stránky se ale dá použít vlastní obslužná rutina opětovného připojení:

App.razor:

Pages/_Host.cshtml:

<div id="reconnect-modal" style="display: none;"></div>
<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script src="boot.js"></script>

V předchozím příkladu {BLAZOR SCRIPT} je Blazor zástupný symbol cesta ke skriptu a název souboru. Umístění skriptu a cesty, které se má použít, najdete v tématu ASP.NET Struktura projektu CoreBlazor.

Vytvořte následující wwwroot/boot.js soubor.

Blazor Web App:

(() => {
  const maximumRetryCount = 3;
  const retryIntervalMilliseconds = 5000;
  const reconnectModal = document.getElementById('reconnect-modal');

  const startReconnectionProcess = () => {
    reconnectModal.style.display = 'block';

    let isCanceled = false;

    (async () => {
      for (let i = 0; i < maximumRetryCount; i++) {
        reconnectModal.innerText = `Attempting to reconnect: ${i + 1} of ${maximumRetryCount}`;

        await new Promise(resolve => setTimeout(resolve, retryIntervalMilliseconds));

        if (isCanceled) {
          return;
        }

        try {
          const result = await Blazor.reconnect();
          if (!result) {
            // The server was reached, but the connection was rejected; reload the page.
            location.reload();
            return;
          }

          // Successfully reconnected to the server.
          return;
        } catch {
          // Didn't reach the server; try again.
        }
      }

      // Retried too many times; reload the page.
      location.reload();
    })();

    return {
      cancel: () => {
        isCanceled = true;
        reconnectModal.style.display = 'none';
      },
    };
  };

  let currentReconnectionProcess = null;

  Blazor.start({
    circuit: {
      reconnectionHandler: {
        onConnectionDown: () => currentReconnectionProcess ??= startReconnectionProcess(),
        onConnectionUp: () => {
          currentReconnectionProcess?.cancel();
          currentReconnectionProcess = null;
        }
      }
    }
  });
})();

Blazor Server:

(() => {
  const maximumRetryCount = 3;
  const retryIntervalMilliseconds = 5000;
  const reconnectModal = document.getElementById('reconnect-modal');

  const startReconnectionProcess = () => {
    reconnectModal.style.display = 'block';

    let isCanceled = false;

    (async () => {
      for (let i = 0; i < maximumRetryCount; i++) {
        reconnectModal.innerText = `Attempting to reconnect: ${i + 1} of ${maximumRetryCount}`;

        await new Promise(resolve => setTimeout(resolve, retryIntervalMilliseconds));

        if (isCanceled) {
          return;
        }

        try {
          const result = await Blazor.reconnect();
          if (!result) {
            // The server was reached, but the connection was rejected; reload the page.
            location.reload();
            return;
          }

          // Successfully reconnected to the server.
          return;
        } catch {
          // Didn't reach the server; try again.
        }
      }

      // Retried too many times; reload the page.
      location.reload();
    })();

    return {
      cancel: () => {
        isCanceled = true;
        reconnectModal.style.display = 'none';
      },
    };
  };

  let currentReconnectionProcess = null;

  Blazor.start({
    reconnectionHandler: {
      onConnectionDown: () => currentReconnectionProcess ??= startReconnectionProcess(),
      onConnectionUp: () => {
        currentReconnectionProcess?.cancel();
        currentReconnectionProcess = null;
      }
    }
  });
})();

Další informace o spuštění architektury Blazor najdete v tématu Spuštění ASP.NET Core Blazor.

Úprava počtu opakování opakování a intervalu opětovného připojení na straně serveru

Pokud chcete upravit počet opakování a interval opětovného připojení, nastavte počet opakování (maxRetries) a období v milisekundách povolených pro každý pokus o opakování (retryIntervalMilliseconds).

Blazor Web App:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    circuit: {
      reconnectionOptions: {
        maxRetries: 3,
        retryIntervalMilliseconds: 2000
      }
    }
  });
</script>

Blazor Server:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    reconnectionOptions: {
      maxRetries: 3,
      retryIntervalMilliseconds: 2000
    }
  });
</script>

V předchozím příkladu {BLAZOR SCRIPT} je Blazor zástupný symbol cesta ke skriptu a název souboru. Umístění skriptu a cesty, které se má použít, najdete v tématu ASP.NET Struktura projektu CoreBlazor.

Když se uživatel vrátí do aplikace s odpojeným okruhem, pokusí se o opětovné připojení okamžitě, a nečeká na dobu trvání dalšího intervalu opětovného připojení. Toto chování se snaží obnovit připojení co nejrychleji pro uživatele.

Výchozí časování opětovného připojení používá vypočítanou strategii zpětného odpojení. K prvnímu několika opakovaným pokusům o opětovné připojení dochází v rychlém sledu před uvedením vypočítaných zpoždění mezi pokusy. Výchozí logika pro výpočet intervalu opakování je podrobnosti implementace, která se může bez předchozího upozornění změnit, ale můžete najít výchozí logiku, kterou Blazor architektura používá ve computeDefaultRetryInterval funkci (referenční zdroj).

Poznámka:

Odkazy na dokumentaci k referenčnímu zdroji .NET obvykle načítají výchozí větev úložiště, která představuje aktuální vývoj pro příští verzi .NET. Pokud chcete vybrat značku pro konkrétní verzi, použijte rozevírací seznam pro přepnutí větví nebo značek. Další informace najdete v tématu Jak vybrat značku verze zdrojového kódu ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Přizpůsobte chování intervalu opakování zadáním funkce pro výpočet intervalu opakování. V následujícím exponenciálním příkladu opakování se počet předchozích pokusů o opětovné připojení vynásobí číslem 1 000 ms pro výpočet intervalu opakování. Pokud je počet předchozích pokusů o opětovné připojení (previousAttempts) větší než maximální limit opakování (maxRetries), null je přiřazen k intervalu opakování (retryIntervalMilliseconds), aby se zastavily další pokusy o opětovné připojení:

Blazor.start({
  circuit: {
    reconnectionOptions: {
      retryIntervalMilliseconds: (previousAttempts, maxRetries) => 
        previousAttempts >= maxRetries ? null : previousAttempts * 1000
    },
  },
});

Alternativou je určit přesnou sekvenci intervalů opakování. Po posledním zadaném intervalu opakování se opakování zastaví, protože retryIntervalMilliseconds funkce vrátí undefined:

Blazor.start({
  circuit: {
    reconnectionOptions: {
      retryIntervalMilliseconds: 
        Array.prototype.at.bind([0, 1000, 2000, 5000, 10000, 15000, 30000]),
    },
  },
});

Další informace o spuštění architektury Blazor najdete v tématu Spuštění ASP.NET Core Blazor.

Ovládací prvek, když se zobrazí uživatelské rozhraní pro opětovné připojení

Řízení, kdy se zobrazí uživatelské rozhraní pro opětovné připojení, může být užitečné v následujících situacích:

  • Nasazená aplikace často zobrazuje uživatelské rozhraní pro opětovné připojení kvůli vypršení časového limitu příkazu ping způsobeným latencí interní sítě nebo internetu a chcete zpoždění zvýšit.
  • Aplikace by měla nahlásit uživatelům, že připojení se dříve ukončilo, a chcete zkrátit zpoždění.

Načasování vzhledu uživatelského rozhraní pro opětovné připojení je ovlivněno úpravou intervalu zachování a časových limitů v klientovi. Uživatelské rozhraní pro opětovné připojení se zobrazí po dosažení časového limitu serveru v klientovi (withServerTimeoutoddíl Konfigurace klienta). Změna hodnoty vyžaduje změny jiných nastavení funkce Keep-Alive, timeout a handshake popsaných withServerTimeout v následujících doprovodných materiálech.

Obecné doporučení pro následující pokyny:

  • Interval uchování by se měl shodovat mezi konfigurací klienta a serveru.
  • Časové limity by měly být alespoň dvojnásobné, než je hodnota přiřazená intervalu Keep-Alive.

Konfigurace serveru

Nastavte následující:

  • ClientTimeoutInterval (výchozí hodnota: 30 sekund): Klienti časového intervalu musí odeslat zprávu předtím, než server připojení zavře.
  • HandshakeTimeout (výchozí hodnota: 15 sekund): Interval používaný serverem k vypršení časového limitu příchozích požadavků handshake klienty.
  • KeepAliveInterval (výchozí hodnota: 15 sekund): Interval používaný serverem k odesílání aktivních příkazů ping připojeným klientům. Všimněte si, že v klientovi je také nastavení intervalu Keep-Alive, které by mělo odpovídat hodnotě serveru.

HandshakeTimeout A ClientTimeoutInterval může být zvýšen a KeepAliveInterval může zůstat stejný. Důležité je, že pokud změníte hodnoty, ujistěte se, že časové limity jsou alespoň dvojnásobné hodnoty intervalu Keep-Alive a že interval Keep-Alive odpovídá mezi serverem a klientem. Další informace najdete v části Konfigurace SignalR časových limitů a udržování naživu v části klienta .

V následujícím příkladu:

  • Hodnota ClientTimeoutInterval se zvýší na 60 sekund (výchozí hodnota: 30 sekund).
  • Hodnota HandshakeTimeout se zvýší na 30 sekund (výchozí hodnota: 15 sekund).
  • Není KeepAliveInterval nastaven v kódu vývojáře a používá výchozí hodnotu 15 sekund. Snížení hodnoty intervalu Keep-Alive zvyšuje frekvenci příkazů ping pro komunikaci, což zvyšuje zatížení aplikace, serveru a sítě. Je třeba dbát na to, abyste se vyhnuli nízkému výkonu při snížení intervalu Udržování naživu.

Blazor Web App (.NET 8 nebo novější) v souboru projektu Program serveru:

builder.Services.AddRazorComponents().AddInteractiveServerComponents()
    .AddHubOptions(options =>
{
    options.ClientTimeoutInterval = TimeSpan.FromSeconds(60);
    options.HandshakeTimeout = TimeSpan.FromSeconds(30);
});

Blazor ServerProgram v souboru:

builder.Services.AddServerSideBlazor()
    .AddHubOptions(options =>
    {
        options.ClientTimeoutInterval = TimeSpan.FromSeconds(60);
        options.HandshakeTimeout = TimeSpan.FromSeconds(30);
    });

Další informace najdete v části Možnosti obslužné rutiny okruhu na straně serveru.

Konfigurace klienta

Nastavte následující:

  • withServerTimeout (výchozí hodnota: 30 sekund): Nakonfiguruje časový limit serveru zadaný v milisekundách pro připojení rozbočovače okruhu.
  • withKeepAliveInterval (výchozí hodnota: 15 sekund): Interval zadaný v milisekundách, ve kterém připojení odesílá zprávy Keep-Alive.

Časový limit serveru je možné zvýšit a interval Keep-Alive může zůstat stejný. Důležité je, že pokud změníte hodnoty, ujistěte se, že časový limit serveru je alespoň dvojnásobná hodnota intervalu Keep-Alive a že hodnoty intervalu Keep-Alive odpovídají mezi serverem a klientem. Další informace najdete v části Konfigurace SignalR časových limitů a udržování naživu v části klienta .

V následujícím příkladu konfigurace spuštění (umístění Blazor skriptu) se pro vypršení časového limitu serveru použije vlastní hodnota 60 sekund. Interval Keep-Alive (withKeepAliveInterval) není nastavený a používá výchozí hodnotu 15 sekund.

Blazor Web App:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    circuit: {
      configureSignalR: function (builder) {
        builder.withServerTimeout(60000);
      }
    }
  });
</script>

Blazor Server:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    configureSignalR: function (builder) {
      builder.withServerTimeout(60000);
    }
  });
</script>

Při vytváření připojení rozbočovače v komponentě nastavte časový limit serveru (WithServerTimeoutvýchozí hodnota: 30 sekund) na kartě HubConnectionBuilder. HandshakeTimeout Nastavte (výchozí: 15 sekund) na sestavené HubConnection. Ověřte, že časové limity jsou alespoň dvakrát interval keep-alive (WithKeepAliveInterval/KeepAliveInterval) a že hodnota Keep-Alive odpovídá mezi serverem a klientem.

Následující příklad je založen na Index komponentěSignalR v kurzu.Blazor Časový limit serveru se zvýší na 60 sekund a časový limit handshake se zvýší na 30 sekund. Interval Keep-Alive není nastavený a používá výchozí hodnotu 15 sekund.

protected override async Task OnInitializedAsync()
{
    hubConnection = new HubConnectionBuilder()
        .WithUrl(Navigation.ToAbsoluteUri("/chathub"))
        .WithServerTimeout(TimeSpan.FromSeconds(60))
        .Build();

    hubConnection.HandshakeTimeout = TimeSpan.FromSeconds(30);

    hubConnection.On<string, string>("ReceiveMessage", (user, message) => ...

    await hubConnection.StartAsync();
}

Nastavte následující:

  • serverTimeoutInMilliseconds (výchozí hodnota: 30 sekund): Nakonfiguruje časový limit serveru zadaný v milisekundách pro připojení rozbočovače okruhu.
  • keepAliveIntervalInMilliseconds (výchozí hodnota: 15 sekund): Interval zadaný v milisekundách, ve kterém připojení odesílá zprávy Keep-Alive.

Časový limit serveru je možné zvýšit a interval Keep-Alive může zůstat stejný. Důležité je, že pokud změníte hodnoty, ujistěte se, že časový limit serveru je alespoň dvojnásobná hodnota intervalu Keep-Alive a že hodnoty intervalu Keep-Alive odpovídají mezi serverem a klientem. Další informace najdete v části Konfigurace SignalR časových limitů a udržování naživu v části klienta .

V následujícím příkladu konfigurace spuštění (umístění Blazor skriptu) se pro vypršení časového limitu serveru použije vlastní hodnota 60 sekund. Interval Keep-Alive (keepAliveIntervalInMilliseconds) není nastavený a používá výchozí hodnotu 15 sekund.

V Pages/_Host.cshtml:

<script src="_framework/blazor.server.js" autostart="false"></script>
<script>
  Blazor.start({
    configureSignalR: function (builder) {
      let c = builder.build();
      c.serverTimeoutInMilliseconds = 60000;
      builder.build = () => {
        return c;
      };
    }
  });
</script>

Při vytváření připojení rozbočovače v komponentě nastavte ServerTimeout (výchozí: 30 sekund) a HandshakeTimeout (výchozí: 15 sekund) na sestavené HubConnection. Ověřte, že časové limity jsou alespoň dvojité intervalu Keep-Alive. Ověřte, že interval udržování naživu odpovídá mezi serverem a klientem.

Následující příklad je založen na Index komponentěSignalR v kurzu.Blazor Zvýší se ServerTimeout na 60 sekund a HandshakeTimeout zvýší se na 30 sekund. Interval Keep-Alive (KeepAliveInterval) není nastavený a používá výchozí hodnotu 15 sekund.

protected override async Task OnInitializedAsync()
{
    hubConnection = new HubConnectionBuilder()
        .WithUrl(Navigation.ToAbsoluteUri("/chathub"))
        .Build();

    hubConnection.ServerTimeout = TimeSpan.FromSeconds(60);
    hubConnection.HandshakeTimeout = TimeSpan.FromSeconds(30);

    hubConnection.On<string, string>("ReceiveMessage", (user, message) => ...

    await hubConnection.StartAsync();
}

Odpojení Blazorokruhu SignalR od klienta

BlazorSignalR Okruh se odpojí při unload aktivaci události stránky. Pokud chcete odpojit okruh pro jiné scénáře v klientovi, vyvolejte Blazor.disconnect ho v příslušné obslužné rutině události. V následujícím příkladu se okruh odpojí, když je stránka skrytá (pagehide událost):

window.addEventListener('pagehide', () => {
  Blazor.disconnect();
});

Další informace o spuštění architektury Blazor najdete v tématu Spuštění ASP.NET Core Blazor.

Obslužná rutina okruhu na straně serveru

Můžete definovat obslužnou rutinu okruhu, která umožňuje spouštění kódu na změnách stavu okruhu uživatele. Obslužná rutina okruhu je implementována odvozením CircuitHandler a registrací třídy v kontejneru služby aplikace. Následující příklad obslužné rutiny okruhu sleduje otevřená SignalR připojení.

TrackingCircuitHandler.cs:

using Microsoft.AspNetCore.Components.Server.Circuits;

public class TrackingCircuitHandler : CircuitHandler
{
    private HashSet<Circuit> circuits = new();

    public override Task OnConnectionUpAsync(Circuit circuit, 
        CancellationToken cancellationToken)
    {
        circuits.Add(circuit);

        return Task.CompletedTask;
    }

    public override Task OnConnectionDownAsync(Circuit circuit, 
        CancellationToken cancellationToken)
    {
        circuits.Remove(circuit);

        return Task.CompletedTask;
    }

    public int ConnectedCircuits => circuits.Count;
}

Obslužné rutiny okruhu se registrují pomocí DI. Instance s vymezeným oborem se vytvářejí pro každou instanci okruhu. TrackingCircuitHandler V předchozím příkladu se vytvoří jednoúčelová služba, protože musí být sledován stav všech okruhů.

V souboru Program:

builder.Services.AddSingleton<CircuitHandler, TrackingCircuitHandler>();

In Startup.ConfigureServices of Startup.cs:

services.AddSingleton<CircuitHandler, TrackingCircuitHandler>();

Pokud metody obslužné rutiny vlastního okruhu vyvolá neošetřenou výjimku, je výjimka pro okruh závažná. Chcete-li tolerovat výjimky v kódu obslužné rutiny nebo volaných metodách, zabalte kód do jednoho nebo více try-catch příkazů pomocí zpracování chyb a protokolování.

Když okruh skončí, protože se uživatel odpojil a architektura vyčistit stav okruhu, architektura vyhodí rozsah DI okruhu. Disposing the scope disposes any circuit-scoped DI services that implement .System.IDisposable Pokud některá služba DI během vyřazení vyvolá neošetřenou výjimku, architektura ji zaznamená do protokolu. Další informace najdete v tématu ASP.NET injektáž závislostí jádraBlazor.

Obslužná rutina okruhu na straně serveru pro zachycení uživatelů pro vlastní služby

CircuitHandler Použijte k zachycení uživatele ze AuthenticationStateProvider služby a jeho nastavení ve službě. Další informace a ukázkový kód najdete v tématu ASP.NET na straně serveru a Blazor Web App dalších scénářích zabezpečení.

Uzavření okruhů, pokud neexistují žádné zbývající součásti interaktivního serveru

Komponenty interaktivního serveru zpracovávají události webového uživatelského rozhraní pomocí připojení v reálném čase s prohlížečem označovaným jako okruh. Okruh a jeho přidružený stav se vytvoří, když se vykreslí kořenová součást Interactive Serveru. Okruh se zavře, pokud na stránce nejsou žádné zbývající součásti interaktivního serveru, které uvolní prostředky serveru.

IHttpContextAccessor/HttpContext v Razor součástech

IHttpContextAccessor musí se vyhnout interaktivnímu vykreslování, protože není k dispozici platný HttpContext .

IHttpContextAccessor lze použít pro součásti, které jsou staticky vykresleny na serveru. Pokud je to ale možné, doporučujeme ho vyhnout.

HttpContext lze použít jako kaskádový parametr pouze v staticky vykreslovaných kořenových komponentách pro obecné úlohy, jako je kontrola a úprava hlaviček nebo jiných vlastností v komponentě App (Components/App.razor). Hodnota je vždy null určená pro interaktivní vykreslování.

[CascadingParameter]
public HttpContext? HttpContext { get; set; }

Pro scénáře, ve HttpContext kterých se vyžaduje v interaktivních komponentách, doporučujeme tok dat přes trvalý stav komponenty ze serveru. Další informace najdete v tématu ASP.NET základní serverové a Blazor Web App další scénáře zabezpečení.

Nepoužívejte IHttpContextAccessor/HttpContext přímo ani nepřímo v Razor komponentách serverových Blazor aplikací. Blazor aplikace běží mimo kontext kanálu ASP.NET Core. Není HttpContext zaručeno, že bude k dispozici v rámci aplikace IHttpContextAccessora HttpContext není zaručeno, že bude obsahovat kontext, který aplikaci spustil Blazor .

Doporučený postup pro předávání stavu požadavku do Blazor aplikace je prostřednictvím parametrů kořenové komponenty během počátečního vykreslování aplikace. Případně může aplikace zkopírovat data do vymezené služby v události životního cyklu inicializace kořenové komponenty pro použití v celé aplikaci. Další informace najdete v tématu ASP.NET základní serverové a Blazor Web App další scénáře zabezpečení.

Důležitým aspektem zabezpečení na straně Blazor serveru je, že se uživatel připojený k danému okruhu může v určitém okamžiku Blazor po navázání okruhu aktualizovat, ale IHttpContextAccessor neaktualizuje se. Další informace o řešení této situace s vlastními službami najdete v tématu ASP.NET jádra na straně serveru a Blazor Web App dalších scénářích zabezpečení.

Další prostředky na straně serveru