Teilen über


Starten von ASP.NET Core Blazor

Hinweis

Dies ist nicht die neueste Version dieses Artikels. Die aktuelle Version finden Sie in der .NET 10-Version dieses Artikels.

Warnung

Diese Version von ASP.NET Core wird nicht mehr unterstützt. Weitere Informationen finden Sie in der .NET- und .NET Core-Supportrichtlinie. Die aktuelle Version finden Sie in der .NET 9-Version dieses Artikels.

In diesem Artikel wird die Startkonfiguration von Blazor-Apps erläutert.

Allgemeine Leitfäden zur Konfiguration von ASP.NET Core-Apps für die serverseitige Entwicklung finden Sie unter Konfiguration in ASP.NET Core.

Startprozess und Konfiguration

Der Blazor-Startprozess erfolgt automatisch und asynchron über das Blazor-Skript (blazor.*.js), wobei der Platzhalter * folgendermaßen lautet:

  • web für eine Blazor Web App.
  • server für eine Blazor Server-App
  • webassembly für eine Blazor WebAssembly-App

Der Blazor-Startprozess erfolgt automatisch und asynchron über das Blazor-Skript (blazor.*.js), wobei der Platzhalter * folgendermaßen lautet:

  • server für eine Blazor Server-App
  • webassembly für eine Blazor WebAssembly-App

Informationen zum Speicherort des Skripts finden Sie unter Projektstruktur für ASP.NET Core Blazor.

So starten Sie Blazor manuell:

Blazor Web App:

  • Fügen Sie dem autostart="false"-Tag Blazor ein <script>-Attribut und einen Wert hinzu.
  • Platzieren Sie ein Skript, das Blazor.start() aufruft, nach dem Blazor<script>-Tag und innerhalb des schließenden </body>-Tags.
  • Fügen Sie Optionen für das statische serverseitige Rendering (statisches SSR) in die ssr-Eigenschaft ein.
  • Fügen Sie serverseitige Blazor- bzw. SignalR-Verbindungsoptionen in die circuit-Eigenschaft ein.
  • Fügen Sie clientseitige WebAssembly-Optionen in die webAssembly-Eigenschaft ein.
<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  ...
  Blazor.start({
    ssr: {
      ...
    },
    circuit: {
      ...
    },
    webAssembly: {
      ...
    }
  });
  ...
</script>

Eigenständiges Blazor WebAssembly und Blazor Server:

  • Fügen Sie dem autostart="false"-Tag Blazor ein <script>-Attribut und einen Wert hinzu.
  • Platzieren Sie ein Skript, das Blazor.start() aufruft, nach dem Blazor<script>-Tag und innerhalb des schließenden </body>-Tags.
  • Sie können zusätzliche Optionen im Parameter Blazor.start() angeben.
<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  ...
  Blazor.start({
    ...
  });
  ...
</script>

Im vorangegangenen Beispiel entspricht der {BLAZOR SCRIPT}-Platzhalter dem Pfad und Dateinamen des Blazor-Skripts. Informationen zum Speicherort des Skripts finden Sie unter Projektstruktur für ASP.NET Core Blazor.

JavaScript-Initialisierer

JavaScript-Initialisierer (JS) führen Logik vor und nach dem Laden einer Blazor-App aus. JS-Initialisierer sind in folgenden Szenarios nützlich:

  • Anpassen, wie eine Blazor-App geladen wird
  • Bibliotheken initialisieren, bevor Blazor startet.
  • Konfigurieren von Blazor-Einstellungen

JS-Initialisierer werden im Rahmen des Buildprozesses erkannt und automatisch importiert. Die Verwendung von JS-Initialisierern macht es oft überflüssig, Skriptfunktionen manuell in der App auszulösen , wenn Sie Razor-Klassenbibliotheken (RCLs) verwenden.

Fügen Sie zur Definition eines JS-Initialisierers dem Projekt ein JS-Modul mit dem Namen {NAME}.lib.module.js hinzu, wobei der Platzhalter {NAME} der Assemblyname, der Bibliotheksname oder der Paketbezeichner sein kann. Platzieren Sie die Datei im Webstammverzeichnis des Projekts, bei dem es sich in der Regel um den Ordner wwwroot handelt.

Für Blazor Web Apps:

  • beforeWebStart(options): Wird aufgerufen, bevor Blazor Web App gestartet wird. Mit beforeWebStart können Sie zum Beispiel den Ladevorgang, den Protokollierungsgrad und andere Optionen anpassen. Empfängt die Blazor-Weboptionen (options).
  • afterWebStarted(blazor): Wird aufgerufen, nachdem alle beforeWebStart-Zusagen aufgelöst wurden. Beispielsweise kann afterWebStarted verwendet werden, um Blazor-Ereignislistener und benutzerdefinierte Ereignistypen zu registrieren. Die Blazor-Instanz wird als Argument (afterWebStarted) an blazor übergeben.
  • beforeServerStart(options, extensions): Wird aufgerufen, bevor die erste Serverlaufzeit gestartet wird. Empfängt SignalR-Leitungsstartoptionen (options) und alle Erweiterungen (extensions), die während der Veröffentlichung hinzugefügt werden.
  • afterServerStarted(blazor): Wird aufgerufen, nachdem die erste Laufzeit des interaktiven Servers gestartet wurde.
  • beforeWebAssemblyStart(options, extensions): Wird aufgerufen, bevor die interaktive WebAssembly-Laufzeit gestartet wird. Empfängt die Blazor-Optionen (options) und alle Erweiterungen (extensions), die während der Veröffentlichung hinzugefügt werden. Beispielsweise können Optionen die Verwendung eines benutzerdefinierten Startressourcen-Ladeprogramms angeben.
  • afterWebAssemblyStarted(blazor): Wird aufgerufen, nachdem die interaktive WebAssembly-Laufzeit gestartet wurde.

Hinweis

Veraltete JS Initialisierer (beforeStart, afterStarted) werden in einer Blazor Web App standardmäßig nicht aufgerufen. Sie können die veralteten Initialisierer mit der enableClassicInitializers-Option aktivieren. Die Ausführung des Legacy-Initialisierers ist jedoch unvorhersehbar.

<script>
  Blazor.start({ enableClassicInitializers: true });
</script>

Aufgrund eines Frameworkfehlers in .NET 8 und 9 (dotnet/aspnetcore #54049) muss das Blazor Skript manuell gestartet werden, wenn beforeWebAssemblyStart(options, extensions) oder afterWebAssemblyStarted(blazor) aufgerufen wird. WENN die Server App Blazor nicht bereits manuell mit einer WebAssembly (webAssembly: {...}) Konfiguration gestartet wird, aktualisieren Sie die App Komponente im Serverprojekt wie folgt.

Components/App.razor Entfernen Sie das vorhandene Blazor<script>-Tag in Components/App.razor.

- <script src="_framework/blazor.web.js"></script>

Ersetzen Sie den <script> Tag durch das folgende Markup, das Blazor manuell mit einer WebAssembly (webAssembly: {...}) Konfiguration beginnt:

<script src="_framework/blazor.web.js" autostart="false"></script>
<script>
    Blazor.start({
        webAssembly: {}
    });
</script>

Für Blazor Server-, Blazor WebAssembly- und Blazor Hybrid-Apps:

  • beforeStart(options, extensions): Wird aufgerufen, bevor Blazor gestartet wird. Mit beforeStart können Sie zum Beispiel den Ladevorgang, den Protokollierungsgrad und andere für das Hostingmodell spezifische Optionen anpassen.
    • Client-seitig empfängt beforeStart die Blazor- Optionen (options) und alle Erweiterungen (extensions), die während der Veröffentlichung hinzugefügt werden. Beispielsweise können Optionen die Verwendung eines benutzerdefinierten Startressourcen-Ladeprogramms angeben.
    • Serverseitig empfängt beforeStartSignalR-Leitungsstartoptionen (options).
    • In BlazorWebView werden keine Optionen übergeben.
  • afterStarted(blazor): Wird aufgerufen, nachdem Blazor bereit ist, Aufrufe von JS zu empfangen. So wird afterStarted beispielsweise verwendet, um Bibliotheken zu initialisieren, indem JS-Interop-Aufrufe durchgeführt und benutzerdefinierte Elemente registriert werden. Die Blazor-Instanz wird als Argument (afterStarted) an blazor übergeben.

Zusätzliche .NET WebAssembly-Runtime-Rückrufe:

  • onRuntimeConfigLoaded(config): Wird aufgerufen, wenn die Startkonfiguration heruntergeladen wird. Ermöglicht der App, Parameter (Konfiguration) vor dem Start der Laufzeit zu ändern (der Parameter lautet MonoConfig von dotnet.d.ts):

    export function onRuntimeConfigLoaded(config) {
      // Sample: Enable startup diagnostic logging when the URL contains 
      // parameter debug=1
      const params = new URLSearchParams(location.search);
      if (params.get("debug") == "1") {
        config.diagnosticTracing = true;
      }
    }
    
  • onRuntimeReady({ getAssemblyExports, getConfig }): Wird aufgerufen, nachdem die .NET WebAssembly-Runtime gestartet wurde (der Parameter ist RuntimeAPI aus dotnet.d.ts):

    export function onRuntimeReady({ getAssemblyExports, getConfig }) {
      // Sample: After the runtime starts, but before Main method is called, 
      // call [JSExport]ed method.
      const config = getConfig();
      const exports = await getAssemblyExports(config.mainAssemblyName);
      exports.Sample.Greet();
    }
    

Beide Rückrufe können ein Promise zurückgeben, und die Zusage wird erwartet, bevor der Start fortgesetzt wird.

Für den Dateinamen gilt Folgendes:

  • Wenn die JS-Initialisierer als statisches Objekt im Projekt genutzt werden, verwenden Sie das Format {ASSEMBLY NAME}.lib.module.js. Hierbei steht der Platzhalter {ASSEMBLY NAME} für den Assemblynamen der App. Benennen Sie beispielsweise die Datei BlazorSample.lib.module.js für ein Projekt mit dem Assemblynamen BlazorSample. Platzieren Sie die Datei im Ordner wwwroot der App.
  • Wenn die JS Initialisierer von einer RCL verwendet werden, verwenden Sie das Format {LIBRARY NAME/PACKAGE ID}.lib.module.js, wobei der {LIBRARY NAME/PACKAGE ID} Platzhalter der Bibliotheksname oder paketbezeichner des Projekts ist (<PackageId> Wert in der Projektdatei der Bibliothek). Benennen Sie beispielsweise die Datei RazorClassLibrary1.lib.module.js für eine RCL mit dem Paketbezeichner RazorClassLibrary1. Platzieren Sie die Datei im Ordner wwwroot der Bibliothek.

Für Blazor Web Apps:

Das folgende Beispiel zeigt JS-Initialisierer, die vor und nach dem Start von Blazor Web App benutzerdefinierte Skripts laden, indem sie diese in <head> und beforeWebStart an afterWebStarted anfügen:

export function beforeWebStart() {
  var customScript = document.createElement('script');
  customScript.setAttribute('src', 'beforeStartScripts.js');
  document.head.appendChild(customScript);
}

export function afterWebStarted() {
  var customScript = document.createElement('script');
  customScript.setAttribute('src', 'afterStartedScripts.js');
  document.head.appendChild(customScript);
}

Das vorherige beforeWebStart-Beispiel stellt nur sicher, dass das benutzerdefinierte Skript geladen wird, bevor Blazor gestartet wird. Es garantiert nicht, dass erwartete Zusagen im Skript vollständig ausgeführt werden, bevor Blazor gestartet wird.

Für Blazor Server-, Blazor WebAssembly- und Blazor Hybrid-Apps:

Das folgende Beispiel zeigt JS-Initialisierer, die vor und nach dem Start von Blazor benutzerdefinierte Skripts laden, indem sie diese in <head> und beforeStart an afterStarted anfügen:

export function beforeStart(options, extensions) {
  var customScript = document.createElement('script');
  customScript.setAttribute('src', 'beforeStartScripts.js');
  document.head.appendChild(customScript);
}

export function afterStarted(blazor) {
  var customScript = document.createElement('script');
  customScript.setAttribute('src', 'afterStartedScripts.js');
  document.head.appendChild(customScript);
}

Das vorherige beforeStart-Beispiel stellt nur sicher, dass das benutzerdefinierte Skript geladen wird, bevor Blazor gestartet wird. Es garantiert nicht, dass erwartete Zusagen im Skript vollständig ausgeführt werden, bevor Blazor gestartet wird.

Hinweis

MVC- und Razor Pages-Apps laden JS-Initialisierer nicht automatisch. Jedoch kann der Entwicklercode ein Skript enthalten, das das Manifest der App abruft und das Laden der JS-Initialisierer auslöst.

Beispiele für JS-Initialisierer finden Sie in den folgenden Ressourcen:

Hinweis

Dokumentationslinks zur .NET-Referenzquelle laden in der Regel den Standardbranch des Repositorys, der die aktuelle Entwicklung für das nächste Release von .NET darstellt. Um ein Tag für ein bestimmtes Release auszuwählen, wählen Sie diesen mit der Dropdownliste Switch branches or tags (Branches oder Tags wechseln) aus. Weitere Informationen finden Sie unter How to select a version tag of ASP.NET Core source code (dotnet/AspNetCore.Docs #26205) (Auswählen eines Versionstags von ASP.NET Core-Quellcode (dotnet/AspNetCore.Docs #26205)).

Sicherstellen, dass Bibliotheken in einer bestimmten Reihenfolge geladen werden

Hängen Sie benutzerdefinierte Skripte an <head> in beforeStart und afterStarted in der Reihenfolge an, in der sie geladen werden sollen.

Das folgende Beispiel lädt script1.js vor script2.js und script3.js vor script4.js:

export function beforeStart(options, extensions) {
    var customScript1 = document.createElement('script');
    customScript1.setAttribute('src', 'script1.js');
    document.head.appendChild(customScript1);

    var customScript2 = document.createElement('script');
    customScript2.setAttribute('src', 'script2.js');
    document.head.appendChild(customScript2);
}

export function afterStarted(blazor) {
    var customScript1 = document.createElement('script');
    customScript1.setAttribute('src', 'script3.js');
    document.head.appendChild(customScript1);

    var customScript2 = document.createElement('script');
    customScript2.setAttribute('src', 'script4.js');
    document.head.appendChild(customScript2);
}

Importieren zusätzlicher Module

Verwenden Sie import-Anweisungen auf oberster Ebene in der Datei des JS-Initialisierers, um zusätzliche Module zu importieren.

additionalModule.js:

export function logMessage() {
  console.log('logMessage is logging');
}

In der JS-Initialisiererdatei (.lib.module.js):

import { logMessage } from "/additionalModule.js";

export function beforeStart(options, extensions) {
  ...

  logMessage();
}

Importzuordnungen

Importzuordnungen werden von ASP.NET Core und Blazor unterstützt.

Initialisieren von Blazor, wenn das Dokument bereit ist

Das folgende Beispiel startet Blazor, wenn das Dokument bereit ist:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  document.addEventListener("DOMContentLoaded", function() {
    Blazor.start();
  });
</script>

Im vorangegangenen Beispiel entspricht der {BLAZOR SCRIPT}-Platzhalter dem Pfad und Dateinamen des Blazor-Skripts. Informationen zum Speicherort des Skripts finden Sie unter Projektstruktur für ASP.NET Core Blazor.

Verketten mit dem Promise, der sich aus einem manuellen Start ergibt

Wenn Sie weitere Aufgaben wie etwa eine JS-Interop-Initialisierung ausführen möchten, verwenden Sie then für die Verkettung mit dem Promise, das sich aus dem manuellen Start der Blazor-App ergibt:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start().then(function () {
    ...
  });
</script>

Im vorangegangenen Beispiel entspricht der {BLAZOR SCRIPT}-Platzhalter dem Pfad und Dateinamen des Blazor-Skripts. Informationen zum Speicherort des Skripts finden Sie unter Projektstruktur für ASP.NET Core Blazor.

Hinweis

Damit eine Bibliothek nach dem Start von Blazor automatisch weitere Aufgaben ausführt, verwenden Sie einen JavaScript-Initialisierer. Bei Verwendung eines JS-Initialisierers ist es für den Nutzer der Bibliothek nicht erforderlich, JS-Aufrufe mit dem manuellen Start von Blazor zu verkoppeln.

Laden clientseitiger Startressourcen

Wenn eine App im Browser geladen wird, lädt sie Startressourcen vom Server herunter:

  • JavaScript-Code zum Bootstrap der App
  • .NET-Runtime und Assemblies
  • Gebietsschemaspezifische Daten

Passen Sie an, wie diese Startressourcen mithilfe der loadBootResource-API geladen werden. Die loadBootResource-Funktion überschreibt den integrierten Lademechanismus für Startressourcen. Verwenden Sie loadBootResource für die folgenden Szenarien:

  • Laden Sie statische Ressourcen wie Zeitzonendaten oder dotnet.wasm aus einem CDN.
  • Komprimierte Assemblys über eine HTTP-Anforderung laden und auf dem Client für Hosts dekomprimieren, die das Abrufen komprimierter Inhalte vom Server nicht unterstützen.
  • Ressourcen per Alias an einen anderen Namen umleiten, indem jede fetch-Anforderung an einen neuen Namen umgeleitet wird.

Hinweis

Externe Quellen müssen die erforderlichen CORS-Header (Cross-Origin Resource Sharing) für Browser zurückgeben, um das ursprungsübergreifende Laden von Ressourcen zu ermöglichen. CDNs stellen in der Regel die erforderlichen Header bereit.

loadBootResource-Parameter sind in der folgenden Tabelle aufgeführt.

Parameter Beschreibung
type Der Typ der Ressource. Mögliche Typen sind: assembly, pdb, dotnetjs, dotnetwasm und timezonedata. Sie müssen nur für benutzerdefinierte Verhaltensmuster Typen angeben. Nicht mit loadBootResource angegebene Typen werden vom Framework entsprechend ihres Standardladeverhaltens geladen. Die dotnetjs-Startressource (dotnet.*.js) muss entweder null für das Standardladeverhalten oder einen URI für die Quelle der dotnetjs-Startressource zurückgeben.
name Der Name der Ressource.
defaultUri Der relative oder absolute URI der Ressource.
integrity Die Integritätszeichenfolge, die den erwarteten Inhalt in der Antwort darstellt.

Die loadBootResource-Funktion kann eine URI-Zeichenfolge zurückgeben, um den Ladevorgang zu überschreiben. Im Beispiel unten werden die folgenden Dateien aus bin/Release/{TARGET FRAMEWORK}/wwwroot/_framework von einem CDN unter https://cdn.example.com/blazorwebassembly/{VERSION}/ bereitgestellt:

  • dotnet.*.js
  • dotnet.wasm
  • Zeitzonendaten

Der Platzhalter {TARGET FRAMEWORK} ist der Zielframeworkmoniker (z. B. net7.0). Der Platzhalter {VERSION} ist die freigegebene Frameworkversion (z. B. 7.0.0).

Blazor Web App:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    webAssembly: {
      loadBootResource: function (type, name, defaultUri, integrity) {
        console.log(`Loading: '${type}', '${name}', '${defaultUri}', '${integrity}'`);
        switch (type) {
          case 'dotnetjs':
          case 'dotnetwasm':
          case 'timezonedata':
            return `https://cdn.example.com/blazorwebassembly/{VERSION}/${name}`;
        }
      }
    }
  });
</script>

Blazor WebAssembly eigenständig:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    loadBootResource: function (type, name, defaultUri, integrity) {
      console.log(`Loading: '${type}', '${name}', '${defaultUri}', '${integrity}'`);
      switch (type) {
        case 'dotnetjs':
        case 'dotnetwasm':
        case 'timezonedata':
          return `https://cdn.example.com/blazorwebassembly/{VERSION}/${name}`;
      }
    }
  });
</script>

Im vorangegangenen Beispiel entspricht der {BLAZOR SCRIPT}-Platzhalter dem Pfad und Dateinamen des Blazor-Skripts. Informationen zum Speicherort des Skripts finden Sie unter Projektstruktur für ASP.NET Core Blazor.

Um mehr als nur die URLs für Startressourcen anzupassen, kann die loadBootResource-Funktion fetch direkt aufrufen und das Ergebnis zurückgeben. Im folgenden Beispiel wird ein benutzerdefinierter HTTP-Header den ausgehenden Anforderungen hinzugefügt. Um das Standardverhalten bei der Integritätsprüfung beizubehalten, übergeben Sie den Parameter integrity.

Blazor Web App:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    webAssembly: {
      loadBootResource: function (type, name, defaultUri, integrity) {
        if (type == 'dotnetjs') {
          return null;
        } else {
          return fetch(defaultUri, {
            cache: 'no-cache',
            integrity: integrity,
            headers: { 'Custom-Header': 'Custom Value' }
          });
        }
      }
    }
  });
</script>

Blazor WebAssembly eigenständig:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    loadBootResource: function (type, name, defaultUri, integrity) {
      if (type == 'dotnetjs') {
        return null;
      } else {
        return fetch(defaultUri, {
          cache: 'no-cache',
          integrity: integrity,
          headers: { 'Custom-Header': 'Custom Value' }
        });
      }
    }
  });
</script>

Im vorangegangenen Beispiel entspricht der {BLAZOR SCRIPT}-Platzhalter dem Pfad und Dateinamen des Blazor-Skripts. Informationen zum Speicherort des Skripts finden Sie unter Projektstruktur für ASP.NET Core Blazor.

Wenn die loadBootResource-Funktion null zurückgibt, verwendet Blazor das Standardladeverhalten für die Ressource. Der vorherige Code gibt beispielsweise null für die dotnetjs-Startressource (dotnet.*.js) zurück, da die dotnetjs-Startressource entweder null für das Standardladeverhalten oder einen URI für die Quelle der dotnetjs-Startressource zurückgeben muss.

Die loadBootResource-Funktion kann auch ein Response-Versprechen zurückgeben. Ein Beispiel finden Sie unter Hosten und Bereitstellen von ASP.NET CoreBlazor WebAssembly.

Weitere Informationen finden Sie unter ASP.NET Core Blazor WebAssembly Caching und Fehler bei Integritätsprüfungen.

Steuerelementheader in C#-Code

Steuern Sie Header beim Programmstart in C#-Code mit den folgenden Ansätzen.

In den folgenden Beispielen wird eine Inhaltssicherheitsrichtlinie (Content Security Policy, CSP) über einen CSP-Header auf die App angewendet. Der Platzhalter {POLICY STRING} entspricht der CSP-Richtlinienzeichenfolge. Weitere Informationen zu CSPs finden Sie unter Durchsetzung einer Inhaltssicherheitsrichtlinie für ASP.NET CoreBlazor.

Hinweis

Kopfzeilen können nach dem Start der Antwort nicht festgelegt werden. Die Ansätze in diesem Abschnitt legen nur Kopfzeilen fest, bevor die Antwort beginnt, sodass die hier beschriebenen Ansätze sicher sind. Weitere Informationen finden Sie unter IHttpContextAccessor/HttpContext in ASP.NET Core Blazor Apps.

Serverseitige und vorab gerenderte clientseitige Szenarien

Verwenden SieASP.NET Core-Middleware, um die Sammlung „headers“ zu steuern.

Gehen Sie in der Program-Datei folgendermaßen vor:

In Startup.Configure von Startup.cs:

app.Use(async (context, next) =>
{
    context.Response.Headers.Append("Content-Security-Policy", "{POLICY STRING}");
    await next();
});

Im vorstehenden Beispiel wird Inline-Middleware verwendet. Sie können jedoch auch eine benutzerdefinierte Middlewareklasse erstellen und die Middleware mit einer Erweiterungsmethode in der Program-Datei aufrufen. Weitere Informationen finden Sie unter Schreiben von benutzerdefinierter ASP.NET Core Middleware.

Clientseitige Entwicklung ohne Vorrendern

Übergeben Sie StaticFileOptions an MapFallbackToFile, um Antwortheader in der OnPrepareResponse-Stage anzugeben.

Gehen Sie in der serverseitigen Program-Datei folgendermaßen vor:

In Startup.Configure von Startup.cs:

var staticFileOptions = new StaticFileOptions
{
    OnPrepareResponse = context =>
    {
        context.Context.Response.Headers.Append("Content-Security-Policy", 
            "{POLICY STRING}");
    }
};

...

app.MapFallbackToFile("index.html", staticFileOptions);

Client-seitige Indikatoren für das Laden

Ein Ladeindikator zeigt, dass die App normal geladen wird und dass der Benutzer warten sollte, bis der Ladevorgang abgeschlossen ist.

Blazor Web App Ladeindikator

Die in Blazor WebAssembly Apps verwendete Ladeanzeige ist in einer app, die aus der Blazor Web App Projektvorlage erstellt wurde, nicht vorhanden. Normalerweise ist ein Indikator für interaktive WebAssembly-Komponenten nicht wünschenswert, da Blazor Web Apps clientseitige Komponenten auf dem Server initialisieren, um schnelle Ladezeiten zu erreichen. Bei Situationen im gemischten Rendermodus muss das Framework oder der Entwicklercode auch darauf achten, die folgenden Probleme zu vermeiden:

  • Anzeigen mehrerer Indikatoren für den Ladevorgang auf derselben gerenderten Seite
  • Versehentliches Verwerfen der vorab gerenderten Inhalte beim Laden der .NET WebAssembly-Runtime.

Eine zukünftige Version von .NET kann einen frameworkbasierten Ladeindikator bereitstellen. Währenddessen können Sie einen benutzerdefinierten Ladeindikator zu einem Blazor Web App hinzufügen.

Komponentenbasiertes interaktives WebAssembly-Rendering mit Prerendering

Dieses Szenario gilt für interaktives WebAssembly-Rendering pro Komponente (@rendermode InteractiveWebAssembly angewendet auf einzelne Komponenten).

Erstellen Sie eine ContentLoading-Komponente im Ordner Layout der App .Client, die OperatingSystem.IsBrowser aufruft.

  • Wenn false, zeigen Sie einen Indikator für das Laden an.
  • Bei true wird der Inhalt der angeforderten Komponente gerendert.

Um CSS-Formatvorlagen für den Indikator zu laden, fügen Sie die Formatvorlagen dem <head> Inhalt mit der HeadContent-Komponente hinzu. Weitere Informationen finden Sie unter Steuerung des head-Inhalts in ASP.NET Core-AppsBlazor.

Layout/ContentLoading.razor:

@if (!RendererInfo.IsInteractive)
{
    <!-- OPTIONAL ...
    <HeadContent>
        <style>
            ...
        </style>
    </HeadContent>
    -->
    <progress id="loadingIndicator" aria-label="Content loading…"></progress>
}
else
{
    @ChildContent
}

@code {
    [Parameter]
    public RenderFragment? ChildContent { get; set; }
}
@if (!OperatingSystem.IsBrowser())
{
    <!-- OPTIONAL ...
    <HeadContent>
        <style>
            ...
        </style>
    </HeadContent>
    -->
    <progress id="loadingIndicator" aria-label="Content loading…"></progress>
}
else
{
    @ChildContent
}

@code {
    [Parameter]
    public RenderFragment? ChildContent { get; set; }
}

Wenn Sie noch nicht über einen Layout Ordner im .Client Projekt verfügen, fügen Sie den Namespace für den Layout Ordner der _Imports.razor Datei hinzu. Im folgenden Beispiel lautet BlazorSample.Clientder Namespace des Projekts:

@using BlazorSample.Client.Layout

Umschließen Sie in einer Komponente, die interaktives WebAssembly-Rendering verwendet, das Razor-Markup der Komponente mit der ContentLoading-Komponente. Das folgende Beispiel veranschaulicht den Ansatz mit der Counter-Komponente einer App, die aus der Blazor Web App-Projektvorlage erstellt wurde.

Pages/Counter.razor:

@page "/counter"
@rendermode InteractiveWebAssembly

<PageTitle>Counter</PageTitle>

<ContentLoading>
    <h1>Counter</h1>

    <p role="status">Current count: @currentCount</p>

    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
</ContentLoading>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}

Globales interaktives WebAssembly-Rendering mit Prerendering

Dieses Szenario gilt für das globale interaktive WebAssembly-Rendering mit Prerendering (@rendermode="InteractiveWebAssembly" für HeadOutlet- und Routes-Komponenten in der App-Komponente).

Erstellen Sie eine ContentLoading-Komponente im Ordner Layout der App .Client, die RendererInfo.IsInteractive aufruft.

  • Wenn false, zeigen Sie einen Indikator für das Laden an.
  • Bei true wird der Inhalt der angeforderten Komponente gerendert.

Um CSS-Formatvorlagen für den Indikator zu laden, fügen Sie die Formatvorlagen dem <head> Inhalt mit der HeadContent-Komponente hinzu. Weitere Informationen finden Sie unter Steuerung des head-Inhalts in ASP.NET Core-AppsBlazor.

Layout/ContentLoading.razor:

@if (!RendererInfo.IsInteractive)
{
    <!-- OPTIONAL ...
    <HeadContent>
        <style>
            ...
        </style>
    </HeadContent>
    -->
    <progress id="loadingIndicator" aria-label="Content loading…"></progress>
}
else
{
    @ChildContent
}

@code {
    [Parameter]
    public RenderFragment? ChildContent { get; set; }
}
@if (!OperatingSystem.IsBrowser())
{
    <!-- OPTIONAL ...
    <HeadContent>
        <style>
            ...
        </style>
    </HeadContent>
    -->
    <progress id="loadingIndicator" aria-label="Content loading…"></progress>
}
else
{
    @ChildContent
}

@code {
    [Parameter]
    public RenderFragment? ChildContent { get; set; }
}

Wenn Sie noch nicht über einen Layout Ordner im .Client Projekt verfügen, fügen Sie den Namespace für den Layout Ordner der _Imports.razor Datei hinzu. Im folgenden Beispiel lautet BlazorSample.Clientder Namespace des Projekts:

@using BlazorSample.Client.Layout

Umschließen Sie in der MainLayout-Komponente (Layout/MainLayout.razor) des .Client-Projekts die Body-Eigenschaft (@Body) mit der ContentLoading-Komponente:

In Layout/MainLayout.razor:

+ <ContentLoading>
    @Body
+ </ContentLoading>

Globales interaktives WebAssembly-Rendering ohne Prerendering

Dieses Szenario gilt für das globale interaktive WebAssembly-Rendering ohne Prerendering (@rendermode="new InteractiveWebAssemblyRenderMode(prerender: false)" in den HeadOutlet und Routes Komponenten innerhalb der App Komponente).

Fügen Sie der App einen JavaScript-Initialisierer hinzu. Im folgenden JavaScript-Moduldateinamen ist der {ASSEMBLY NAME} Platzhalter der Assemblyname des Serverprojekts (z. B BlazorSample. ). Der wwwroot Ordner, in dem das Modul platziert wird, ist der wwwroot Ordner im serverseitigen Projekt, nicht im .Client Projekt.

Im folgenden Beispiel wird ein progress Indikator verwendet, der nicht den tatsächlichen Fortschritt der Bereitstellung clientseitiger Startressourcen an den Client angibt. Es dient jedoch als allgemeiner Ansatz für die Weiterentwicklung, wenn die Statusanzeige den tatsächlichen Fortschritt des Ladens der Startressourcen der App anzeigt.

wwwroot/{ASSEMBLY NAME}.lib.module.js:

export function beforeWebStart(options) {
  var progress = document.createElement("progress");
  progress.id = 'loadingIndicator';
  progress.ariaLabel = 'Blazor loading…';
  progress.style = 'position:absolute;top:50%;left:50%;margin-right:-50%;' +
    'transform:translate(-50%,-50%);';
  document.body.appendChild(progress);
}

export function afterWebAssemblyStarted(blazor) {
  var progress = document.getElementById('loadingIndicator');
  progress.remove();
}

Aufgrund eines Frameworkfehlers in .NET 8 und 9 (dotnet/aspnetcore #54049) muss das Blazor Skript manuell gestartet werden. WENN die Server App Blazor nicht bereits manuell mit einer WebAssembly (webAssembly: {...}) Konfiguration gestartet wird, aktualisieren Sie die App Komponente im Serverprojekt wie folgt.

Components/App.razor Entfernen Sie das vorhandene Blazor<script>-Tag in Components/App.razor.

- <script src="_framework/blazor.web.js"></script>

Ersetzen Sie den <script> Tag durch das folgende Markup, das Blazor manuell mit einer WebAssembly (webAssembly: {...}) Konfiguration beginnt:

<script src="_framework/blazor.web.js" autostart="false"></script>
<script>
    Blazor.start({
        webAssembly: {}
    });
</script>

Wenn Sie eine kurze Verzögerung zwischen dem Entfernen des Ladeindikators und dem Rendern der ersten Seite feststellen, können Sie das Entfernen des Indikators garantieren, indem Sie in der OnAfterRenderAsync Lebenszyklusmethode entweder der MainLayout- oder Routes-Komponenten die Entfernung des Indikators aufrufen. Weitere Informationen und ein Codebeispiel finden Sie unter Dokumentieren eines Ansatzes für einen Ladeindikator, der mit globalen interaktiven WebAssembly ohne Vorrendern (dotnet/AspNetCore.Docs #35111) funktioniert.

Ladestatus der Blazor WebAssembly-App

Die Projektvorlage enthält skalierbare Vektorgrafiken (Scalable Vector Graphics, SVG) und Textindikatoren, die den Ladefortschritt der App anzeigen.

Die Statusindikatoren werden mit HTML und CSS mithilfe von zwei benutzerdefinierten CSS-Eigenschaften (Variablen) implementiert, die von Blazor bereitgestellt werden:

  • --blazor-load-percentage: Der Prozentsatz der geladenen App-Dateien.
  • --blazor-load-percentage-text: Der Prozentsatz der geladenen App-Dateien auf die nächste ganze Zahl gerundet.

Mithilfe der vorherigen CSS-Variablen können Sie benutzerdefinierte Statusindikatoren erstellen, die dem Stil Ihrer App entsprechen.

Im folgenden Beispiel:

  • resourcesLoaded ist eine sofortige Angabe der Anzahl der Ressourcen, die beim Starten der App geladen wurden.
  • totalResources ist die Gesamtanzahl der zu ladenden Ressourcen.
const percentage = resourcesLoaded / totalResources * 100;
document.documentElement.style.setProperty(
  '--blazor-load-percentage', `${percentage}%`);
document.documentElement.style.setProperty(
  '--blazor-load-percentage-text', `"${Math.floor(percentage)}%"`);

Der standardmäßige runde Fortschrittsindikator wird in HTML in der Datei wwwroot/index.html implementiert:

<div id="app">
    <svg class="loading-progress">
        <circle r="40%" cx="50%" cy="50%" />
        <circle r="40%" cx="50%" cy="50%" />
    </svg>
    <div class="loading-progress-text"></div>
</div>

Weitere Informationen zum -Projektvorlagenmarkup und zum Stil der Standardstatusindikatoren finden Sie in der ASP.NET Core-Referenz:

Hinweis

Dokumentationslinks zur .NET-Referenzquelle laden in der Regel den Standardbranch des Repositorys, der die aktuelle Entwicklung für das nächste Release von .NET darstellt. Um ein Tag für ein bestimmtes Release auszuwählen, wählen Sie diesen mit der Dropdownliste Switch branches or tags (Branches oder Tags wechseln) aus. Weitere Informationen finden Sie unter How to select a version tag of ASP.NET Core source code (dotnet/AspNetCore.Docs #26205) (Auswählen eines Versionstags von ASP.NET Core-Quellcode (dotnet/AspNetCore.Docs #26205)).

Anstatt den standardmäßigen runden Fortschrittsindikator zu verwenden, zeigt das folgende Beispiel, wie ein linearer Fortschrittsindikator implementiert wird.

Fügen Sie die folgenden Formatvorlagen in wwwroot/css/app.css hinzu:

.linear-progress {
    background: silver;
    width: 50vw;
    margin: 20% auto;
    height: 1rem;
    border-radius: 10rem;
    overflow: hidden;
    position: relative;
}

.linear-progress:after {
    content: '';
    position: absolute;
    inset: 0;
    background: blue;
    scale: var(--blazor-load-percentage, 0%) 100%;
    transform-origin: left top;
    transition: scale ease-out 0.5s;
}

Eine CSS-Variable (var(...)) wird dazu verwendet, den Wert von --blazor-load-percentage an die scale-Eigenschaft eines blauen Pseudoelements zu übergeben, das den Ladefortschritt der Dateien der App angibt. Wenn die App geladen wird, wird --blazor-load-percentage automatisch aktualisiert, wodurch sich die visuelle Darstellung des Statusindikators dynamisch ändert.

Entfernen Sie in wwwroot/index.html den runden SVG-Standardindikator in <div id="app">...</div>, und ersetzen Sie ihn durch das folgende Markup:

<div class="linear-progress"></div>

Konfigurieren der .NET-WebAssembly-Runtime

In erweiterten Programmierszenarios wird die configureRuntime-Funktion mit dem dotnet-Runtimehost-Generator verwendet, um die .NET WebAssembly-Runtime zu konfigurieren. Beispielsweise legt dotnet.withEnvironmentVariable eine Umgebungsvariable fest, die:

  • Konfigurieren Sie die .NET WebAssembly-Runtime.
  • Ändert das Verhalten einer C-Bibliothek.

Hinweis

Im GitHub-Repository dotnet/runtime ist eine Dokumentationsanfrage für weitere Informationen zu Umgebungsvariablen ausstehend, die die .NET WebAssembly-Laufzeit konfigurieren oder das Verhalten von C-Bibliotheken beeinflussen. Obwohl die Dokumentationsanfrage noch nicht abgeschlossen ist, finden Sie weitere Informationen und Querverweise auf zusätzliche Ressourcen in der Anfrage Frage/Anfrage nach Dokumentation zu .NET WASM Runtime env vars (dotnet/runtime #98225).

Die configureRuntime-Funktion kann auch verwendet werden, um die Integration mit einem Browserprofiler zu ermöglichen.

In den folgenden Beispielen, die eine Umgebungsvariable festlegen, gilt Folgendes für die Platzhalter:

  • Der Platzhalter {BLAZOR SCRIPT} entspricht dem Blazor-Skriptpfad und -Dateinamen. Informationen zum Speicherort des Skripts finden Sie unter Projektstruktur für ASP.NET Core Blazor.
  • Der Platzhalter {NAME} ist der Name der Umgebungsvariable.
  • Der Platzhalter {VALUE} ist der Wert der Umgebungsvariable.

Blazor Web App:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    webAssembly: {
      configureRuntime: dotnet => {
        dotnet.withEnvironmentVariable("{NAME}", "{VALUE}");
      }
    }
  });
</script>

Blazor WebAssembly eigenständig:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    configureRuntime: dotnet => {
      dotnet.withEnvironmentVariable("{NAME}", "{VALUE}");
    }
  });
</script>

Hinweis

Auf die .NET-Runtimeinstanz kann mithilfe der .NET WebAssembly-Runtime-API (Blazor.runtime) zugegriffen werden. Die Buildkonfiguration der App kann z. B. mit Blazor.runtime.runtimeBuildInfo.buildConfiguration abgerufen werden.

Weitere Informationen zur .NET WebAssembly-Runtimekonfiguration finden Sie in der TypeScript-Definitionsdatei (dotnet.d.ts) der Runtime im dotnet/runtime-GitHub-Repository.

Hinweis

Dokumentationslinks zur .NET-Referenzquelle laden in der Regel den Standardbranch des Repositorys, der die aktuelle Entwicklung für das nächste Release von .NET darstellt. Um ein Tag für ein bestimmtes Release auszuwählen, wählen Sie diesen mit der Dropdownliste Switch branches or tags (Branches oder Tags wechseln) aus. Weitere Informationen finden Sie unter How to select a version tag of ASP.NET Core source code (dotnet/AspNetCore.Docs #26205) (Auswählen eines Versionstags von ASP.NET Core-Quellcode (dotnet/AspNetCore.Docs #26205)).

Deaktivieren der erweiterten Navigation und Formularverarbeitung

Dieser Abschnitt gilt für Blazor Web Apps.

Um die erweiterte Navigation und Formularverarbeitung zu deaktivieren, legen Sie disableDomPreservation auf true für Blazor.start fest:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    ssr: { disableDomPreservation: true }
  });
</script>

Im vorangegangenen Beispiel entspricht der {BLAZOR SCRIPT}-Platzhalter dem Pfad und Dateinamen des Blazor-Skripts. Informationen zum Speicherort des Skripts finden Sie unter Projektstruktur für ASP.NET Core Blazor.

Zusätzliche Ressourcen