Dela via


vägledning för ASP.NET Core BlazorSignalR

Not

Det här är inte den senaste versionen av den här artikeln. Den aktuella versionen finns i den .NET 9-versionen av den här artikeln.

Varning

Den här versionen av ASP.NET Core stöds inte längre. Mer information finns i .NET och .NET Core Support Policy. För den aktuella versionen, se .NET 9-versionen av den här artikeln.

Viktig

Den här informationen gäller en förhandsversionsprodukt som kan ändras avsevärt innan den släpps kommersiellt. Microsoft lämnar inga garantier, uttryckliga eller underförstådda, med avseende på den information som tillhandahålls här.

Den aktuella versionen finns i .NET 9-versionen av denna artikel.

Den här artikeln beskriver hur du konfigurerar och hanterar SignalR anslutningar i Blazor appar.

Allmän vägledning om ASP.NET Core SignalR-konfiguration finns i avsnittet Översikt över ASP.NET Core SignalR i dokumentationen, särskilt ASP.NET Core SignalR konfiguration.

Appar på serversidan använder ASP.NET Core SignalR för att kommunicera med webbläsaren. SignalR:s värd- och skalningskrav gäller för appar på serversidan.

Blazor fungerar bäst när du använder WebSockets för SignalR transport på grund av tillförlitlighet, lägre svarstid och säkerhet. Long Polling används av SignalR när WebSockets inte är tillgängligt eller när appen uttryckligen har konfigurerats för att använda Long Polling.

Azure SignalR Service med tillståndskänslig återanslutning

Azure SignalR Service med SDK v1.26.1 eller senare stöder SignalR tillståndskänslig återanslutning (WithStatefulReconnect).

WebSocket-komprimering för interaktiva serverkomponenter

Som standard: Interaktiva serverkomponenter:

  • Aktivera komprimering för WebSocket-anslutningar. DisableWebSocketCompression (standard: false) styr WebSocket-komprimering.

  • Anta ett frame-ancestorsContent Security Policy (CSP)-direktiv inställt på 'self', vilket endast tillåter att appen bäddas in i en <iframe> från samma ursprung som appen levereras från, när komprimering är aktiverad eller när en konfiguration för WebSocket-kontexten tillhandahålls. ContentSecurityFrameAncestorPolicy styr frame-ancestors CSP.

Du kan ta bort frame-ancestors CSP manuellt genom att ange värdet för ContentSecurityFrameAncestorsPolicy till null, eftersom du kanske vill konfigurera CSP på ett centraliserat sätt. När frame-ancestors CSP hanteras på ett centraliserat sätt måste du vara noga med att tillämpa en princip när det första dokumentet återges. Vi rekommenderar inte att du tar bort principen helt eftersom den kan göra appen sårbar för angrepp.

Använd ConfigureWebSocketAcceptContext för att konfigurera WebSocketAcceptContext för de websocket-anslutningar som används av serverkomponenterna. Som standard tillämpas en princip som möjliggör komprimering och anger en CSP för de ramförfäder som definierats i ContentSecurityFrameAncestorsPolicy.

Användningsexempel:

Inaktivera komprimering genom att ange DisableWebSocketCompression till true, vilket minskar appens sårbarhet för angrepp men kan leda till sämre prestanda:

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

När komprimering är aktiverat konfigurerar du en striktare frame-ancestors CSP med värdet 'none' (enkla citattecken krävs), vilket tillåter WebSocket-komprimering men hindrar webbläsare från att bädda in appen i alla <iframe>:

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

När komprimering är aktiverat tar du bort frame-ancestors CSP genom att ange ContentSecurityFrameAncestorsPolicy till null. Det här scenariot rekommenderas endast för appar som ange CSP på ett centraliserat sätt:

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

Viktig

Webbläsare tillämpar CSP-direktiv från flera CSP-huvuden med det striktaste principdirektivvärdet. Därför kan en utvecklare inte lägga till en svagare frame-ancestors princip än 'self' med avsikt eller av misstag.

Enkla citattecken krävs för strängvärdet som skickas till ContentSecurityFrameAncestorsPolicy:

Värden som inte stöds:none, self

✔️ värden som stöds:'none', 'self'

Ytterligare alternativ är att ange en eller flera värdkällor och schemakällor.

För säkerhetsimplikationer, se Vägledning för hotreducering för ASP.NET Core Blazor interaktiv återgivning på serversidan. Mer information om frame-ancestors-direktivet finns i CSP: frame-ancestors (MDN-dokumentation).

Inaktivera svarskomprimering för Hot Reload

När du använder Hot Reload, ska du inaktivera Mellanprogrammet för svarskomprimering i Development-miljön. Oavsett om standardkoden från en projektmall används eller inte anropar du alltid UseResponseCompression först i pipelinen för bearbetning av begäranden.

I filen Program:

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

Förhandling på klientsidan SignalR korsande ursprung för autentisering

I det här avsnittet beskrivs hur du konfigurerar SignalRunderliggande klient för att skicka autentiseringsuppgifter, till exempel cookies eller HTTP-autentiseringshuvuden.

Använd SetBrowserRequestCredentials för att ange Include på begäranden mellan olika ursprung 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);
    }
}

När en hubbanslutning skapas tilldelar du HttpMessageHandler till alternativet HttpMessageHandlerFactory:

private HubConnectionBuilder? hubConnection;

...

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

I föregående exempel konfigureras hubbanslutnings-URL:en till den absoluta URI-adressen på /chathub. URI:n kan också anges via en sträng, till exempel https://signalr.example.comeller via konfiguration. Navigation är en injekterad NavigationManager.

Mer information finns i ASP.NET Core SignalR configuration.

Återgivning på klientsidan

Om prerendering har konfigurerats, inträffar prerendering innan klientanslutningen till servern upprättas. Mer information finns i Prerender ASP.NET Core Razor-komponenter.

Om prerendering har konfigurerats inträffar prerendering innan klientanslutningen till servern upprättas. Mer information finns i följande artiklar:

Förrenderad tillståndsstorlek och SignalR storleksgräns för meddelanden

En stor för-renderad tillståndsstorlek kan överskrida Blazor:s SignalR krets meddelande-storleksgräns, vilket resulterar i följande:

  • Det går inte att initiera SignalR-kretsen med ett fel på klienten: Circuit host not initialized.
  • Återanslutningsgränssnittet på klienten visas när kretsen misslyckas. Det går inte att återställa.

Lös problemet genom att använda antingen av följande metoder:

  • Minska mängden data som du lägger i det förinstallerade tillståndet.
  • Öka storleksgränsen för SignalR meddelande. WARNING: Om du ökar gränsen kan risken för DoS-attacker (Denial of Service) ökas.

Ytterligare resurser på klientsidan

Använd sessionstillhörighet (klibbiga sessioner) för webbfarmdrift på serversidan

När fler än en bakomliggande server används måste appen implementera sessionstillhörighet, som även kallas klistriga sessioner. Sessionstillhörighet säkerställer att en klients krets återansluter till samma server om anslutningen avbryts, vilket är viktigt eftersom klienttillståndet endast lagras i minnet på den server som först upprättade klientens krets.

Följande fel utlöses av en app som inte har aktiverat sessionstillhörighet i en webbfarm:

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

För mer information om sessionstillhörighet med Azure App Service-värdtjänster, se Värd och distribuera ASP.NET Core server-side-appar Blazor.

Azure SignalR Service

Den valfria Azure SignalR Service- fungerar tillsammans med appens SignalR hubb för att skala upp en app på serversidan till ett stort antal samtidiga anslutningar. Dessutom bidrar tjänstens globala räckvidd och högpresterande datacenter avsevärt till att minska svarstiden på grund av geografi.

Tjänsten krävs inte för Blazor appar som finns i Azure App Service eller Azure Container Apps, men kan vara till hjälp i andra värdmiljöer:

  • För att underlätta utskalning av anslutningar.
  • Hantera global distributionen.

För mer information, se Att vara värd och distribuera serverside ASP.NET Core-applikationer Blazor.

Alternativ för kretshanterare på serversidan

Konfigurera kretsen med CircuitOptions. Visa standardvärden i referenskällan .

Anteckning

Dokumentationslänkar till .NET-referenskällan läser vanligtvis in lagringsplatsens standardgren, vilket representerar den aktuella utvecklingen för nästa version av .NET. Om du vill välja en tagg för en specifik version, använd rullgardinsmenyn Växla grenar eller taggar. Mer information finns i Så här väljer du en versionstagg för ASP.NET Core-källkod (dotnet/AspNetCore.Docs #26205).

Läs eller ange alternativet i filen Program med ett delegat för alternativ för AddInteractiveServerComponents. Platshållaren {OPTION} representerar alternativet och platshållaren {VALUE} är värdet.

I filen Program:

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

Läs eller ange alternativen i filen Program med hjälp av en alternativhanterare till AddServerSideBlazor. Platshållaren {OPTION} representerar alternativet och platshållaren {VALUE} är värdet.

I filen Program:

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

Läs eller ange alternativen i Startup.ConfigureServices med ett alternativdelegat till AddServerSideBlazor. Platshållaren {OPTION} representerar alternativet och platshållaren {VALUE} är värdet.

I Startup.ConfigureServices av Startup.cs:

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

Om du vill konfigurera HubConnectionContextanvänder du HubConnectionContextOptions med AddHubOptions. Visa standardinställningarna för kontextalternativen för hubbanslutning i referenskälla. Alternativbeskrivningar i SignalR-dokumentationen finns i ASP.NET Core SignalR configuration. Platshållaren {OPTION} representerar alternativet och platshållaren {VALUE} är värdet.

Anteckning

Dokumentationslänkar till .NET-referenskällan läser vanligtvis in lagringsplatsens standardgren, vilket representerar den aktuella utvecklingen för nästa version av .NET. För att välja en tagg för en specifik utgåva använder du rullgardinsmenyn Växla grenar eller taggar. Mer information finns i Så här väljer du en versionstagg för ASP.NET Core-källkod (dotnet/AspNetCore.Docs #26205).

I filen Program:

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

I filen Program:

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

I Startup.ConfigureServices av Startup.cs:

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

Varning

Standardvärdet för MaximumReceiveMessageSize är 32 KB. Att öka värdet kan öka risken för DoS-attacker (Denial of Service).

Blazor förlitar sig på att MaximumParallelInvocationsPerClient är angivet till 1, vilket är standardvärdet. För mer information, se MaximumParallelInvocationsPerClient > 1 bryter filuppladdning i Blazor Server-läge (dotnet/aspnetcore #53951).

För information om minneshantering, se Hosta och distribuera ASP.NET Core-appar på serversidan Blazor.

Blazor hubalternativ

Konfigurera alternativ för MapBlazorHub för att styra HttpConnectionDispatcherOptions hos Blazor-hubben. Visa standardinställningarna för alternativen för hubbanslutningsavsändare i referenskälla. Platshållaren {OPTION} representerar alternativet och platshållaren {VALUE} är värdet.

Not

Dokumentationslänkar till .NET-referenskällan läser vanligtvis in lagringsplatsens standardgren, vilket representerar den aktuella utvecklingen för nästa version av .NET. Om du vill välja en tagg för en specifik version använder du listrutan Växla grenar eller taggar. Mer information finns i Så här väljer du en versionstagg för ASP.NET Core-källkod (dotnet/AspNetCore.Docs #26205).

Placera anropet till app.MapBlazorHub efter anropet till app.MapRazorComponents i appens Program-fil:

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

Det går inte att konfigurera den hubb som används av AddInteractiveServerRenderMode med MapBlazorHub på grund av en AmbiguousMatchException.

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

Om du vill lösa problemet för appar som är inriktade på .NET 8 ger du den anpassade konfigurerade Blazor hubben högre prioritet med hjälp av metoden WithOrder:

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

Mer information finns i följande resurser:

Ange alternativen till app.MapBlazorHub i appens Program-fil.

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

Ange alternativen till app.MapBlazorHub i konfigurationen för slutpunktsroutning:

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

Maximal meddelandestorlek för mottagning

Det här avsnittet gäller endast för projekt som implementerar SignalR.

Den maximala inkommande SignalR meddelandestorlek som tillåts för hubbmetoder begränsas av HubOptions.MaximumReceiveMessageSize (standard: 32 KB). SignalR meddelanden som är större än MaximumReceiveMessageSize generera ett fel. Ramverket har ingen gräns för storleken på ett SignalR meddelande från hubben till en klient.

När SignalR loggning inte har angetts till Felsöka eller Tracevisas endast ett meddelandestorleksfel i webbläsarens konsol för utvecklarverktyg:

Fel: Anslutningen kopplades från på grund av ett fel: Servern returnerade ett fel vid stängning: Anslutningen stängdes på grund av ett fel.

När SignalR loggning på serversidan har angetts till Felsöka eller Spårning, visar loggning på serversidan en InvalidDataException för ett meddelandestorleksfel.

appsettings.Development.json:

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

Fel:

System.IO.InvalidDataException: Den maximala meddelandestorleken på 32768 byte överskreds. Meddelandestorleken kan konfigureras i AddHubOptions.

En metod innebär att öka gränsen genom att ange MaximumReceiveMessageSize i filen Program. I följande exempel anges den maximala meddelandestorleken för mottagna meddelanden till 64 KB:

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

Om du ökar storleksgränsen SignalR för inkommande meddelanden medför det behovet av fler serverresurser och ökar risken för DoS-attacker (Denial of Service). Dessutom kan läsning av en stor mängd innehåll i minnet som strängar eller bytematriser också resultera i allokeringar som fungerar dåligt med skräpinsamlaren, vilket resulterar i ytterligare prestandapåföljder.

Ett bättre alternativ för att läsa stora nyttolaster är att skicka innehållet i mindre segment och bearbeta nyttolasten som en Stream. Detta kan användas när du läser stora JavaScript-interoperabilitets-JJSON-payloads (JS) eller om JS-interoperabilitetsdata är tillgängliga som rådata. Ett exempel som visar hur du skickar stora binära nyttolaster i appar på serversidan som använder tekniker som liknar InputFile komponentenfinns i exempelappen Binary Submit och BlazorInputLargeTextArea Component Sample.

Notis

Dokumentationslänkar till .NET-referenskällan läser vanligtvis in lagringsplatsens standardgren, vilket representerar den aktuella utvecklingen för nästa version av .NET. Om du vill välja en tagg för en specifik version använder du listrutan Växla grenar eller taggar. Mer information finns i Så här väljer du en versionstagg för ASP.NET Core-källkod (dotnet/AspNetCore.Docs #26205).

Formulär som bearbetar stora nyttolaster över SignalR kan också använda direktuppspelning JS interop direkt. Mer information finns i Anropa .NET-metoder från JavaScript-funktioner i ASP.NET Core Blazor. Ett formulärexempel som strömmar <textarea> data till servern finns i Felsöka ASP.NET Core Blazor-formulär.

En metod innebär att öka gränsen genom att ange MaximumReceiveMessageSize i filen Program. I följande exempel anges den maximala meddelandestorleken för mottagna meddelanden till 64 KB:

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

Om du ökar SignalR storleksgränsen för inkommande meddelanden sker kostnaden för att kräva fler serverresurser, och det ökar risken för DoS-attacker (Denial of Service). Dessutom kan läsning av en stor mängd innehåll i minnet som strängar eller bytematriser också resultera i allokeringar som fungerar dåligt med skräpinsamlaren, vilket resulterar i ytterligare prestandapåföljder.

Ett bättre alternativ för att läsa stora nyttolaster är att skicka innehållet i mindre segment och bearbeta nyttolasten som en Stream. Detta kan användas när du läser stora JavaScript- (JS) interop JSON-nyttolaster eller om JS interop-data är tillgängliga som rådata. Ett exempel som visar hur du skickar stora binära nyttolaster i Blazor Server som använder tekniker som liknar InputFile komponentenfinns i exempelappen Binary Submit och BlazorInputLargeTextArea Component Sample.

Anteckning

Dokumentationslänkar till .NET-referenskällan läser vanligtvis in lagringsplatsens standardgren, vilket representerar den aktuella utvecklingen för nästa version av .NET. Om du vill välja en tagg för en specifik version använder du listrutan Växla grenar eller taggar. Mer information finns i Så här väljer du en versionstagg för ASP.NET Core-källkod (dotnet/AspNetCore.Docs #26205).

Formulär som bearbetar stora nyttolaster över SignalR kan också använda direktuppspelning JS interop direkt. Mer information finns i Anropa .NET-metoder från JavaScript-funktioner i ASP.NET Core Blazor. Ett exempel på formulär som strömmar data från <textarea> i en Blazor Server app finns i Felsöka ASP.NET Core Blazor formulär.

Öka gränsen genom att ange MaximumReceiveMessageSize i Startup.ConfigureServices:

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

Om du ökar SignalR storleksgränsen för inkommande meddelanden sker kostnaden för att kräva fler serverresurser, och det ökar risken för DoS-attacker (Denial of Service). Dessutom kan läsning av en stor mängd innehåll i minnet som strängar eller byte-arrayer också resultera i allokeringar som hanteras dåligt av skräpinsamlaren, vilket resulterar i ytterligare prestandaförluster.

Tänk på följande när du utvecklar kod som överför en stor mängd data:

  • Använd stöd för intern direktuppspelning JS interop för att överföra data som är större än storleksgränsen för inkommande meddelanden SignalR:
  • Allmänna tips:
    • Allokera inte stora objekt i JS- och C#-kod.
    • Ledigt förbrukat minne när processen har slutförts eller avbrutits.
    • Tillämpa följande ytterligare krav för säkerhetsändamål:
      • Deklarera den maximala fil- eller datastorlek som kan skickas.
      • Deklarera den lägsta uppladdningshastigheten från klienten till servern.
    • När data har tagits emot av servern kan data vara:
      • Lagras tillfälligt i en minnesbuffert tills alla segment samlas in.
      • Förbrukas omedelbart. Data kan till exempel lagras omedelbart i en databas eller skrivas till disk när varje segment tas emot.
  • Dela upp data i mindre delar och skicka datasegmenten sekventiellt tills alla data tas emot av servern.
  • Allokera inte stora objekt i JS- och C#-kod.
  • Blockera inte huvudgränssnittstråden under långa perioder när du skickar eller tar emot data.
  • Ledigt förbrukat minne när processen har slutförts eller avbrutits.
  • Tillämpa följande ytterligare krav för säkerhetsändamål:
    • Deklarera den maximala fil- eller datastorlek som kan skickas.
    • Deklarera den lägsta uppladdningshastigheten från klienten till servern.
  • När data har tagits emot av servern kan data vara:
    • Lagras tillfälligt i en minnesbuffert tills alla segment samlas in.
    • Förbrukas omedelbart. Data kan till exempel lagras omedelbart i en databas eller skrivas till disk när varje segment tas emot.

Blazor hubbslutpunktsvägskonfiguration på serversidan

I filen Program anropar du MapBlazorHub för att mappa BlazorHub till appens standardsökväg. Skriptet Blazor (blazor.*.js) pekar automatiskt på slutpunkten som skapats av MapBlazorHub.

Återspegla anslutningstillståndet på serversidan i användargränssnittet

Om klienten identifierar en förlorad anslutning till servern visas ett standardgränssnitt för användaren när klienten försöker återansluta:

Standardgränssnittet för återanslutning.

Standardgränssnittet för återanslutning.

Om återanslutningen misslyckas instrueras användaren att försöka igen eller läsa in sidan igen:

Standardgränssnittet för återförsök.

Standardgränssnittet för återförsök.

Om återanslutningen lyckas går användartillståndet ofta förlorat. Anpassad kod kan läggas till i valfri komponent för att spara och läsa in användartillståndet på nytt över anslutningsfel. Mer information finns i ASP.NET Core Blazor state management.

Om du vill anpassa användargränssnittet definierar du ett enda element med en id av components-reconnect-modal i <body>-elementinnehållet. I följande exempel placeras elementet i komponenten App.

App.razor:

Om du vill anpassa användargränssnittet definierar du ett enda element med en id av components-reconnect-modal i <body>-elementinnehållet. I följande exempel placeras elementet på värdsidan.

Pages/_Host.cshtml:

Om du vill anpassa användargränssnittet definierar du ett enda element med en id av components-reconnect-modal i innehållet för <body>-elementet. I följande exempel placeras elementet på layoutsidan.

Pages/_Layout.cshtml:

Om du vill anpassa användargränssnittet definierar du ett enda element med en id av components-reconnect-modal i <body>-elementinnehållet. I följande exempel placeras elementet på värdsidan.

Pages/_Host.cshtml:

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

Not

Om mer än ett element med en id av components-reconnect-modal återges av appen, tar endast det första renderade elementet emot CSS-klassändringar för att visa eller dölja elementet.

Lägg till följande CSS-formatmallar i webbplatsens formatmall.

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;
}

I följande tabell beskrivs css-klasserna som tillämpas på components-reconnect-modal-elementet av Blazor-ramverket.

CSS-klass Indikerar...
components-reconnect-show En förlorad anslutning. Klienten försöker återansluta. Visa dialogrutan.
components-reconnect-hide En aktiv anslutning upprättas på nytt till servern. Dölj modalen.
components-reconnect-failed Återanslutningen misslyckades, förmodligen på grund av ett nätverksfel. Om du vill försöka återansluta anropar du window.Blazor.reconnect() i JavaScript.
components-reconnect-rejected Återanslutningen avvisades. Servern nåddes men nekade anslutningen och användarens tillstånd på servern går förlorat. Om du vill ladda om appen igen anropar du location.reload() i JavaScript. Det här anslutningstillståndet kan uppstå när:
  • En krasch i kretsen på serversidan inträffar.
  • Klienten är frånkopplad tillräckligt länge för att servern ska kunna släppa användarens tillstånd. Instanser av användarens komponenter tas bort.
  • Servern startas om eller så återanvänds appens arbetsprocess.

Anpassa fördröjningen innan återanslutningsgränssnittet visas genom att ange egenskapen transition-delay i platsens CSS för modal-elementet. I följande exempel anges övergångsfördröjningen från 500 ms (standard) till 1 000 ms (1 sekund).

wwwroot/app.css:

wwwroot/css/site.css:

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

Om du vill visa det aktuella återanslutningsförsöket definierar du ett element med en id av components-reconnect-current-attempt. Om du vill visa det maximala antalet återanslutningsförsök definierar du ett element med en id av components-reconnect-max-retries. I följande exempel placeras dessa element i ett modal-element för återanslutningsförsök efter föregående exempel.

<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>

När den anpassade återanslutningsmodalen visas återges följande innehåll med en återanslutningsförsöksräknare:

Det uppstod ett problem med anslutningen! (Aktuellt återanslutningsförsök: 1/8)

Återgivning på serversidan

Som standard förinstalleras komponenterna på servern innan klientanslutningen till servern upprättas. Mer information finns i Prerender ASP.NET Core Razor-komponenter.

Som standard förinstalleras komponenterna på servern innan klientanslutningen till servern upprättas. Mer information finns i Komponenttagghjälp i ASP.NET Core.

Övervaka kretsaktivitet på serversidan

Övervaka inkommande kretsaktivitet med hjälp av metoden CreateInboundActivityHandlerCircuitHandler. Inkommande kretsaktivitet är en aktivitet som skickas från webbläsaren till servern, till exempel användargränssnittshändelser eller JavaScript-to-.NET interop-anrop.

Du kan till exempel använda en kretsaktivitetshanterare för att identifiera om klienten är inaktiv och logga dess krets-ID (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;
    }
}

Registrera tjänsten i filen Program. I följande exempel konfigureras standardtimeouten för inaktivitet på fem minuter till fem sekunder för att testa föregående IdleCircuitHandler implementering:

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

Kretsaktivitetshanterare tillhandahåller också en metod för att komma åt områdesspecifika Blazor-tjänster från andra ej-Blazor beroendeinjektionsomfång. Mer information och exempel finns i:

Blazor startupföretag

Konfigurera den manuella starten av Blazor:s SignalR-krets i App.razor-filen i en Blazor Web App:

Konfigurera den manuella starten av BlazorSignalR krets i Pages/_Host.cshtml -filen (Blazor Server):

Konfigurera den manuella starten av Blazor:s krets SignalR i Pages/_Layout.cshtml-filen (Blazor Server):

Konfigurera den manuella starten av BlazorSignalR krets i Pages/_Host.cshtml -filen (Blazor Server):

  • Lägg till ett autostart="false"-attribut i taggen <script> för blazor.*.js-skriptet.
  • Placera ett skript som anropar Blazor.start() när Blazor-skriptet har lästs in och inuti den avslutande </body> taggen.

När autostart är inaktiverad fungerar alla aspekter av appen som inte är beroende av kretsen normalt. Till exempel fungerar routning på klientsidan. Alla aspekter som är beroende av kretsen fungerar dock inte förrän Blazor.start() anropas. Appbeteendet är oförutsägbart utan en etablerad krets. Komponentmetoder kan till exempel inte köras medan kretsen är frånkopplad.

Mer information, inklusive hur du initierar Blazor när dokumentet är klart och hur du kedjar till en JS Promisefinns i ASP.NET Core Blazor start.

Konfigurera SignalR timeouter och Keep-Alive på klienten

Konfigurera följande värden för klienten:

  • withServerTimeout: Konfigurerar tidsgränsen för servern i millisekunder. Om den här tidsgränsen förflutit utan att ta emot några meddelanden från servern avslutas anslutningen med ett fel. Standardvärdet för timeout är 30 sekunder. Tidsgränsen för servern bör vara minst dubbelt så stor som värdet som tilldelats till Keep-Alive intervall (withKeepAliveInterval).
  • withKeepAliveInterval: Konfigurerar Keep-Alive intervall i millisekunder (standardintervall för pingning av servern). Med den här inställningen kan servern identifiera hårda frånkopplingar, till exempel när en klient kopplar från datorn från nätverket. Pingen sker högst så ofta som servern pingar. Om servern pingar var femte sekund och du tilldelar ett värde som är lägre än 5000 (5 sekunder), kommer den att fortsätta pinga var femte sekund. Standardvärdet är 15 sekunder. Keep-Alive intervallet ska vara mindre än eller lika med halva värdet som tilldelats serverns timeout (withServerTimeout).

I följande exempel för filen App.razor (Blazor Web App) visas tilldelningen av standardvärden.

Blazor Web App:

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

Följande exempel för filen Pages/_Host.cshtml (Blazor Server, alla versioner utom ASP.NET Core i .NET 6) eller Pages/_Layout.cshtml fil (Blazor Server, ASP.NET Core i .NET 6).

Blazor Server:

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

I föregående exempel är platshållaren {BLAZOR SCRIPT}Blazor skriptsökväg och filnamn. För platsen för skriptet och sökvägen som ska användas, se ASP.NET Core Blazor projektstruktur.

När du skapar en hubbanslutning i en komponent anger du ServerTimeout (standard: 30 sekunder) och KeepAliveInterval (standard: 15 sekunder) på HubConnectionBuilder. Ange HandshakeTimeout (standard: 15 sekunder) på den inbyggda HubConnection. I följande exempel visas tilldelningen av standardvärden:

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();
}

Konfigurera följande värden för klienten:

  • serverTimeoutInMilliseconds: Tidsgränsen för servern i millisekunder. Om den här tidsgränsen förflutit utan att ta emot några meddelanden från servern avslutas anslutningen med ett fel. Standardvärdet för timeout är 30 sekunder. Tidsgränsen för servern bör vara minst dubbelt så stor som värdet som tilldelats till Keep-Alive intervall (keepAliveIntervalInMilliseconds).
  • keepAliveIntervalInMilliseconds: Standardintervall där servern ska pingas. Med den här inställningen kan servern identifiera hårda frånkopplingar, till exempel när en klient kopplar från datorn från nätverket. Pingen sker högst lika ofta som servern pingar. Om servern pingar var femte sekund innebär det att ett värde lägre än 5000 (5 sekunder) orsakar pingningar var femte sekund. Standardvärdet är 15 sekunder. Det Keep-Alive intervallet ska vara mindre än eller lika med halva det tilldelade värdet för serverns timeout (serverTimeoutInMilliseconds).

Följande exempel för filen Pages/_Host.cshtml (Blazor Server, alla versioner utom ASP.NET Core i .NET 6) eller Pages/_Layout.cshtml -filen (Blazor Server, ASP.NET Core i .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>

I det föregående exemplet är platshållaren {BLAZOR SCRIPT} skriptsökvägen och filnamnet Blazor. För platsen för skriptet och sökvägen som ska användas, se ASP.NET Core Blazor projektstruktur.

När du skapar en hubbanslutning i en komponent anger du ServerTimeout (standard: 30 sekunder), HandshakeTimeout (standard: 15 sekunder) och KeepAliveInterval (standard: 15 sekunder) på den inbyggda HubConnection. I följande exempel visas tilldelningen av standardvärden:

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();
}

När du ändrar värdena för serverns timeout (ServerTimeout) eller Keep-Alive intervall (KeepAliveInterval):

  • Tidsgränsen för servern bör vara minst dubbelt så stor som värdet som tilldelats till Keep-Alive intervall.
  • Det Keep-Alive intervallet ska vara mindre än eller lika med hälften av det värde som tilldelats serverns tidsgräns.

Mer information finns i avsnittet Globala distributions- och anslutningsfel i följande artiklar:

Ändra återanslutningshanteraren på serversidan

Återanslutningshanterarens kretsanslutningshändelser kan ändras för anpassade beteenden, till exempel:

  • Meddela användaren om anslutningen bryts.
  • Så här utför du loggning (från klienten) när en krets är ansluten.

Om du vill ändra anslutningshändelserna registrerar du återanrop för följande anslutningsändringar:

  • Avbrutna anslutningar använder onConnectionDown.
  • Upprättade/återupprättade anslutningar använder onConnectionUp.

Både onConnectionDown och onConnectionUp måste anges.

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>

Platshållaren {BLAZOR SCRIPT} i det föregående exemplet är Blazor skriptsökväg och filnamn. För platsen för skriptet och sökvägen som ska användas, se ASP.NET Core Blazor projektstruktur.

Uppdatera sidan automatiskt när återanslutningen på serversidan misslyckas

Standardbeteendet för återanslutning kräver att användaren vidtar manuella åtgärder för att uppdatera sidan när återanslutningen misslyckas. En anpassad återanslutningshanterare kan dock användas för att automatiskt uppdatera sidan:

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>

I föregående exempel är platshållaren {BLAZOR SCRIPT} scriptets sökväg och filnamn Blazor. För platsen för skriptet och sökvägen som ska användas, se ASP.NET Core Blazor projektstruktur.

Skapa följande wwwroot/boot.js fil.

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;
      }
    }
  });
})();

Mer information om Blazor startup finns i ASP.NET Core Blazor startup.

Justera antalet återförsök och intervall för återanslutning på serversidan

Om du vill justera antalet återanslutningsförsök och intervall anger du antalet återförsök (maxRetries) och perioden i millisekunder som tillåts för varje återförsök (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>

I föregående exempel representerar platshållaren {BLAZOR SCRIPT} skriptsökvägen och platshållaren Blazor filnamnet. För platsen för skriptet och sökvägen som ska användas, se ASP.NET Core Blazor projektstruktur.

När användaren navigerar tillbaka till en app med en frånkopplad krets görs återanslutningsförsök omedelbart i stället för att vänta under nästa återanslutningsintervall. Det här beteendet syftar till att återuppta anslutningen så snabbt som möjligt för användaren.

Standardinställningen för återanslutning använder en beräknad väntestrategi. De första flera återanslutningsförsöken sker i snabb följd innan beräknade fördröjningar introduceras mellan försöken. Standardlogik för att beräkna återförsöksintervallet är en implementeringsinformation som kan ändras utan föregående meddelande, men du kan hitta standardlogik som Blazor-ramverket använder i computeDefaultRetryInterval-funktionen (referenskälla).

Anteckning

Dokumentationslänkar till .NET-referenskällan läser vanligtvis in lagringsplatsens standardgren, vilket representerar den aktuella utvecklingen för nästa version av .NET. Om du vill välja en tagg för en specifik version använder du listrutan Växla grenar eller taggar. Mer information finns i Så här väljer du en versionstagg för ASP.NET Core-källkod (dotnet/AspNetCore.Docs #26205).

Anpassa beteendet för återförsöksintervall genom att ange en funktion för att beräkna återförsöksintervallet. I följande exponentiella backoff-exempel multipliceras antalet tidigare återanslutningsförsök med 1 000 ms för att beräkna återförsöksintervallet. När antalet tidigare försök att återansluta (previousAttempts) är större än den maximala återförsöksgränsen (maxRetries), tilldelas null till återförsöksintervallet (retryIntervalMilliseconds) för att avbryta ytterligare återanslutningsförsök:

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

Ett alternativ är att ange den exakta sekvensen med återförsöksintervall. Efter det senaste angivna återförsöksintervallet stoppas återförsöken eftersom funktionen retryIntervalMilliseconds returnerar undefined:

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

För mer information om Blazor-start, se ASP.NET Core Blazor-start.

Kontrollera när återanslutningsgränssnittet visas

Att styra när återanslutningsgränssnittet visas kan vara användbart i följande situationer:

  • En utplacerad app visar ofta återanslutningsgränssnittet på grund av ping-timeouter som orsakas av fördröjning i det interna nätverket eller på Internet, och du vill öka väntetiden.
  • En app bör rapportera tidigare till användarna att anslutningen har brutits, och man vill förkorta fördröjningen.

Tidpunkten för återanslutningsgränssnittets utseende påverkas av att justera Keep-Alive intervall och tidsgränser på klienten. Användargränssnittet för återanslutning visas när tidsgränsen för servern nås på klienten (withServerTimeout, avsnittet Klientkonfiguration). Att ändra värdet för withServerTimeout kräver dock ändringar i andra inställningar för Keep-Alive, timeout och handskakning som beskrivs i följande vägledning.

Som allmänna rekommendationer för vägledningen som följer:

  • Det Keep-Alive intervallet ska matcha mellan klient- och serverkonfigurationer.
  • Tidsgränser bör vara minst dubbelt så stora som värdet som tilldelats till Keep-Alive-intervallet.

Serverkonfiguration

Ange följande:

  • ClientTimeoutInterval (standard: 30 sekunder): Tidsfönstret klienter måste skicka ett meddelande innan servern stänger anslutningen.
  • HandshakeTimeout (standard: 15 sekunder): Intervallet som används av servern för att timeoutera inkommande handskakningsbegäranden från klienter.
  • KeepAliveInterval (standard: 15 sekunder): Intervallet som används av servern för att skicka keep alive-ping till anslutna klienter. Observera att det också finns en Keep-Alive intervallinställning på klienten, som ska matcha serverns värde.

ClientTimeoutInterval och HandshakeTimeout kan ökas och KeepAliveInterval kan förbli desamma. Det viktiga är att om du ändrar värdena kontrollerar du att tidsgränserna är minst dubbelt så stora som värdet för Keep-Alive intervall och att Keep-Alive intervall matchar mellan server och klient. För mer information, se avsnittet Configure SignalR timeouts och Keep-Alive på klienten.

I följande exempel:

  • ClientTimeoutInterval ökas till 60 sekunder (standardvärde: 30 sekunder).
  • HandshakeTimeout ökas till 30 sekunder (standardvärde: 15 sekunder).
  • KeepAliveInterval anges inte i utvecklarkoden och använder standardvärdet 15 sekunder. Om du minskar värdet för Keep-Alive-intervallet ökar frekvensen för kommunikations ping, vilket ökar belastningen på appen, servern och nätverket. Var noga med att undvika dålig prestanda vid sänkning av Keep-Alive intervall.

Blazor Web App (.NET 8 eller senare) i serverprojektets Program-fil:

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

Blazor Server i filen Program:

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

Mer information finns i avsnittet alternativ för kretshanterare på serversidan.

Klientkonfiguration

Ange följande:

  • withServerTimeout (standard: 30 sekunder): Konfigurerar tidsgränsen för servern, som anges i millisekunder, för kretsens hubbanslutning.
  • withKeepAliveInterval (standard: 15 sekunder): Intervallet, som anges i millisekunder, där anslutningen skickar Keep-Alive meddelanden.

Tidsgränsen för servern kan ökas och Keep-Alive-intervallet kan förbli detsamma. Det viktiga är att om du ändrar värdena kontrollerar du att tidsgränsen för servern är minst dubbelt så stor som värdet för Keep-Alive intervall och att Keep-Alive intervallvärden matchar mellan server och klient. Mer information finns i avsnittet Konfigurera SignalR timeout och Keep-Alive på klienten.

I följande startkonfiguration exempel (plats för Blazor skriptet) används ett anpassat värde på 60 sekunder för serverns timeout. Det Keep-Alive intervallet (withKeepAliveInterval) är inte inställt och använder standardvärdet 15 sekunder.

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>

När du skapar en hubbanslutning i en komponent anger du tidsgränsen för servern (WithServerTimeout, standard: 30 sekunder) på HubConnectionBuilder. Ange HandshakeTimeout (standard: 15 sekunder) på den inbyggda HubConnection. Kontrollera att tidsgränserna är minst dubbelt så många som Keep-Alive intervall (WithKeepAliveInterval/KeepAliveInterval) och att Keep-Alive-värdet matchar mellan server och klient.

Följande exempel baseras på komponenten Index i SignalR med Blazor självstudie. Tidsgränsen för servern ökas till 60 sekunder och tidsgränsen för handskakning ökas till 30 sekunder. Det Keep-Alive intervallet anges inte och använder standardvärdet 15 sekunder.

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();
}

Ange följande:

  • serverTimeoutInMilliseconds (standard: 30 sekunder): Konfigurerar tidsgränsen för servern, som anges i millisekunder, för kretsens hubbanslutning.
  • keepAliveIntervalInMilliseconds (standard: 15 sekunder): Intervallet, som anges i millisekunder, där anslutningen skickar Keep-Alive meddelanden.

Tidsgränsen för servern kan ökas, och Keep-Alive-intervallet kan förbli detsamma. Det viktiga är att om du ändrar värdena kontrollerar du att tidsgränsen för servern är minst dubbelt så stor som värdet för Keep-Alive intervall och att Keep-Alive intervallvärden matchar mellan server och klient. För mer information, se avsnittet Konfigurera SignalR tidsgränser och Keep-Alive på klienten.

I följande startkonfiguration exempel (plats för Blazor skriptet) används ett anpassat värde på 60 sekunder för serverns timeout. Det Keep-Alive intervallet (keepAliveIntervalInMilliseconds) är inte inställt och använder standardvärdet 15 sekunder.

I 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>

När du skapar en hubbanslutning i en komponent anger du ServerTimeout (standard: 30 sekunder) och HandshakeTimeout (standard: 15 sekunder) på den inbyggda HubConnection. Bekräfta att tidsgränserna är minst dubbelt så stora som Keep-Alive-intervallen. Bekräfta att Keep-Alive intervall matchar mellan server och klient.

Följande exempel baseras på komponenten Index i handledningen iSignalR med Blazor. ServerTimeout ökas till 60 sekunder och HandshakeTimeout ökas till 30 sekunder. Det Keep-Alive intervallet (KeepAliveInterval) är inte inställt och använder standardvärdet 15 sekunder.

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();
}

Koppla bort Blazor:s krets SignalR från klienten

Blazor SignalR-kretsen kopplas från när sidhändelsen unload utlöses. Om du vill koppla från kretsen för andra scenarier på klienten anropar du Blazor.disconnect i lämplig händelsehanterare. I följande exempel kopplas kretsen från när sidan är dold (pagehide händelse):

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

Mer information om Blazor uppstart finns i ASP.NET Core Blazor uppstart.

Kretshanterare på serversidan

Du kan definiera en kretshanterare, som tillåter körning av kod vid ändringar i tillståndet för en användares krets. En kretshanterare implementeras genom att härleda från CircuitHandler och registrera klassen i appens tjänstcontainer. I följande exempel på en kretsavkännare spåras öppna SignalR anslutningar.

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;
}

Kretshanterare registreras med DI. Begränsade instanser skapas per instans av en krets. Med hjälp av TrackingCircuitHandler i föregående exempel skapas en singleton-tjänst eftersom tillståndet för alla kretsar måste spåras.

I filen Program:

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

I Startup.ConfigureServices av Startup.cs:

services.AddSingleton<CircuitHandler, TrackingCircuitHandler>();

Om en anpassad kretshanterares metoder utlöser ett ohanterat undantag är undantaget allvarligt för kretsen. Om du vill tolerera undantag i en hanterares kod eller åberopade metoder, kan du omsluta koden med en eller flera try-catch-instruktioner med felhantering och loggar.

När en krets slutar på grund av att en användare har kopplats från och ramverket rensar kretstillståndet, tar ramverket bort kretsens DI-omfång. Att ta bort omfånget tar bort alla DI-tjänster med kretsomfattning som implementerar System.IDisposable. Om någon DI-tjänst genererar ett ohanterat undantag under borttagningen loggar ramverket undantaget. Mer information finns i ASP.NET Core Blazor beroendeinjektion.

Kretshanterare på serversidan för att samla in användare för anpassade tjänster

Använd en CircuitHandler för att samla in en användare från AuthenticationStateProvider och ange användaren i en tjänst. Mer information och exempelkod finns i ASP.NET Core-serversidan och Blazor Web App ytterligare säkerhetsscenarier.

Stängning av kretsar när det inte finns några återstående interaktiva serverkomponenter

Interaktiva serverkomponenter hanterar webbgränssnittshändelser med hjälp av en realtidsanslutning med webbläsaren som kallas en krets. En krets och dess associerade tillstånd skapas när en interaktiv rotserverkomponent återges. Kretsen stängs när det inte finns några återstående interaktiva serverkomponenter på sidan, vilket frigör serverresurser.

Starta SignalR-kretsen med en annan URL

Förhindra att appen startas automatiskt genom att lägga till autostart="false" i taggen Blazor<script> (plats för Blazor startskriptet). Upprätta krets-URL:en manuellt med hjälp av Blazor.start. I följande exempel används sökvägen /signalr.

Blazor Web Apps:

- <script src="_framework/blazor.web.js"></script>
+ <script src="_framework/blazor.web.js" autostart="false"></script>
+ <script>
+   Blazor.start({
+     circuit: {
+       configureSignalR: builder => builder.withUrl("/signalr")
+     },
+   });
+ </script>

Blazor Server:

- <script src="_framework/blazor.server.js"></script>
+ <script src="_framework/blazor.server.js" autostart="false"></script>
+ <script>
+   Blazor.start({
+     configureSignalR: builder => builder.withUrl("/signalr")
+   });
+ </script>

Lägg till följande MapBlazorHub-anrop med hubbsökvägen till pipelinen för bearbetning av mellanprogram i serverappens Program-fil.

Blazor Web Apps:

app.MapBlazorHub("/signalr");

Blazor Server:

Lämna det befintliga anropet MapBlazorHub i filen och lägg till ett nytt anrop till MapBlazorHub med sökvägen:

app.MapBlazorHub();
+ app.MapBlazorHub("/signalr");

IHttpContextAccessor/HttpContext

IHttpContextAccessor bör vanligtvis undvikas med interaktiv återgivning eftersom en giltig HttpContext inte alltid är tillgänglig.

IHttpContextAccessor kan användas för komponenter som återges statiskt på servern. Vi rekommenderar dock att du undviker det om det är möjligt.

HttpContext kan användas som en kaskadparameter endast i statiskt renderade rotkomponenter för allmänna uppgifter, till exempel att inspektera och ändra rubriker eller andra egenskaper i komponenten App (Components/App.razor). Värdet är alltid null för interaktiv återgivning.

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

För scenarier där HttpContext krävs i interaktiva komponenter rekommenderar vi att data skickas via bestående komponenttillstånd från servern. Mer information finns i ASP.NET Core-serversidan och Blazor Web App ytterligare säkerhetsscenarier.

Använd inte IHttpContextAccessor/HttpContext direkt eller indirekt i de Razor komponenterna i Blazor appar på serversidan. Blazor appar körs utanför ASP.NET Core-pipelinekontexten. Den HttpContext är inte garanterad att vara tillgänglig inom IHttpContextAccessoroch HttpContext är inte garanterat att ha kontexten som startade Blazor-appen.

Den rekommenderade metoden för att skicka begärandetillstånd till Blazor-appen är genom rotkomponentparametrar vid appens första återgivning. Alternativt kan appen kopiera data till en begränsad tjänst i rotkomponentens initieringslivscykelhändelse för användning i hela appen. Mer information finns i ASP.NET Core-serversidan och Blazor Web App ytterligare säkerhetsscenarier.

En viktig aspekt av serversidans Blazor-säkerhet är att användaren som är ansluten till en given krets kan bli uppdaterad vid något tillfälle efter att Blazor-kretsen har upprättats men IHttpContextAccessorinte uppdateras. Mer information om hur du hanterar den här situationen med anpassade tjänster finns i ASP.NET Core-serversidan och Blazor Web App ytterligare säkerhetsscenarier.

Personifiering för Windows-autentisering

Autentiserade hubbanslutningar (HubConnection) skapas med UseDefaultCredentials för att ange användning av standardautentiseringsuppgifter för HTTP-begäranden. Mer information finns i -autentisering och auktorisering i ASP.NET Core SignalR.

När appen körs i IIS Express som den inloggade användaren under Windows-autentisering, vilket sannolikt är användarens personliga konto eller arbetskonto, är standardautentiseringsuppgifterna för den inloggade användaren.

När appen publiceras till IIS körs appen under programpoolen Identity. HubConnection ansluter som IIS-användarkontot som är värd för appen, inte användaren som kommer åt sidan.

Implementera personifiering med HubConnection för att använda webbanvändarens identitet.

I följande exempel:

protected override async Task OnInitializedAsync()
{
    var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();

    if (authState?.User.Identity is not null)
    {
        var user = authState.User.Identity as WindowsIdentity;

        if (user is not null)
        {
            await WindowsIdentity.RunImpersonatedAsync(user.AccessToken, 
                async () =>
                {
                    hubConnection = new HubConnectionBuilder()
                        .WithUrl(NavManager.ToAbsoluteUri("/hub"), config =>
                        {
                            config.UseDefaultCredentials = true;
                        })
                        .WithAutomaticReconnect()
                        .Build();

                        hubConnection.On<string>("name", userName =>
                        {
                            name = userName;
                            InvokeAsync(StateHasChanged);
                        });

                        await hubConnection.StartAsync();
                });
        }
    }
}

I föregående kod är NavManager en NavigationManageroch AuthenticationStateProvider är en AuthenticationStateProvider tjänsteinstans (AuthenticationStateProvider dokumentation).

Ytterligare resurser på serversidan