Neuerungen in ASP.NET Core 8.0

In diesem Artikel werden die wichtigsten Änderungen in ASP.NET Core 8.0 aufgezeigt und Links zur relevanten Dokumentation bereitgestellt.

Blazor

Vollständige Stapel-Webbenutzeroberfläche

Mit der Veröffentlichung von .NET 8 ist Blazor ein Framework mit vollständiger Stapel-Webbenutzeroberfläche für die Entwicklung von Apps, die Inhalte entweder auf Komponenten- oder Seitenebene folgendermaßen rendern:

  • Statisches Serverrendering (auch als statisches serverseitiges Rendering, statisches SSR, bezeichnet) zum Generieren von statischem HTML-Code auf dem Server.
  • Interaktives Serverrendering (auch als interaktives serverseitiges Rendering, interaktives SSR bezeichnet) zum Generieren interaktiver Komponenten mit Prerendering auf dem Server.
  • Interaktives WebAssembly-Rendering (auch als clientseitiges Rendering bezeichnet, CSR, das immer als interaktiv angenommen wird) zum Generieren interaktiver Komponenten auf dem Client mit Prerendering auf dem Server.
  • Interaktives automatisches Rendering, um zunächst die serverseitige ASP.NET Core-Laufzeit für das Rendern von Inhalten und Interaktivität zu verwenden. Die .NET WebAssembly-Laufzeit auf dem Client wird für nachfolgendes Rendern und Interaktivität verwendet, nachdem das Blazor-Paket heruntergeladen wurde und die WebAssembly-Laufzeit aktiviert wird. Das interaktive automatische Rendering sorgt in der Regel für den schnellsten Start von Apps.

Interaktive Rendermodi rendern standardmäßig auch Inhalte vorab.

Weitere Informationen finden Sie in den folgenden Artikeln:

Die Beispiele in der gesamten Blazor-Dokumentation wurden für die Verwendung in Blazor-Web-Apps aktualisiert. Blazor Server-Beispiele bleiben in Inhalten, die für .NET 7 oder früher versioniert sind.

Neuer Artikel zu Klassenbibliotheken mit statischem serverseitigem Rendering (statisches SSR)

Wir haben einen neuen Artikel hinzugefügt, in dem die Erstellung von Komponentenbibliotheken in Razor-Klassenbibliotheken (RCLs) mit statischem serverseitigem Rendering (statisches SSR) erläutert wird.

Weitere Informationen finden Sie unter ASP.NET Core-Razor-Klassenbibliotheken (RCLs) mit statischem serverseitigem Rendering (statisches SSR).

Neuer Artikel zu HTTP-Zwischenspeicherungsproblemen

Wir haben einen neuen Artikel hinzugefügt, in dem einige der häufig auftretenden Probleme beim Zwischenspeichern von HTTP erläutert werden, die beim Upgrade von Blazor-Apps auf Hauptversionen auftreten können und wie HTTP-Zwischenspeicherungsprobleme behoben werden.

Weitere Informationen finden Sie unter Vermeiden von HTTP-Zwischenspeicherungsproblemen beim Upgrade von ASP.NET Core-Blazor-Apps.

Neue Blazor-Web-App-Vorlage

Wir haben eine neue Blazor-Projektvorlage eingeführt: die Blazor-Web App-Vorlage. Die neue Vorlage bietet einen einzigen Ausgangspunkt für die Verwendung von Blazor-Komponenten zum Erstellen einer Webbenutzeroberfläche im gewünschten Stil. Die Vorlage kombiniert die Stärken der vorhandenen Blazor Server- und Blazor WebAssembly-Hostingmodelle mit den neuen Blazor-Funktionen, die in .NET 8 hinzugefügt wurden: statisches serverseitiges Rendering (statisches SSR), Streamingrendering, erweiterte Navigations- und Formularverarbeitung sowie die Möglichkeit, Interaktivität mithilfe von Blazor Server oder Blazor WebAssembly auf Basis von Komponenten hinzuzufügen.

Im Rahmen der Vereinheitlichung der verschiedenen Blazor-Hostingmodelle in einem einzigen Modell in .NET 8 haben wir auch die Anzahl der Blazor-Projektvorlagen konsolidiert. Wir haben die Blazor Server-Vorlage entfernt. Außerdem wurde die Option „ASP.NET Core Hosted“ aus der Blazor WebAssembly-Vorlage entfernt. Beide Szenarien werden durch Optionen abgebildet, in denen die Blazor-Web App-Vorlage verwendet wird.

Hinweis

Vorhandene Blazor Server- und Blazor WebAssembly-Apps werden in .NET 8 weiterhin unterstützt. Optional können diese Apps aktualisiert werden, um die neuen Blazor-Features für vollständiger Stapel-Webbenutzeroberflächen zu verwenden.

Weitere Informationen zur neuen Blazor-Web-App-Vorlage finden Sie in den folgenden Artikeln:

Neue JS-Initialisierer für Blazor-Web-Apps

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

  • beforeStart wird für Aufgaben wie das Anpassen des Ladevorgangs, die Protokollierungsebene und andere Optionen verwendet.
  • afterStarted wird für Aufgaben wie das Registrieren von Blazor-Ereignislistenern und benutzerdefinierten Ereignistypen verwendet.

Die vorherigen Legacy-JS-Initialisierer werden in einer Blazor Web-App nicht standardmäßig aufgerufen. Für Blazor-Web-Apps werden neue JS-Initialisierer verwendet: beforeWebStart, afterWebStarted, beforeServerStart, afterServerStarted, beforeWebAssemblyStart und afterWebAssemblyStarted.

Weitere Informationen finden Sie unter Starten von ASP.NET CoreBlazor.

Aufteilen von Anleitungen zum Prerendering und zur Integration

Bei früheren Versionen von .NET wurden Prerendering- und Integrationsfunktionen in einem einzigen Artikel behandelt. Um unsere Abdeckung zu vereinfachen und zu konzentrieren, haben wir die Themen in die folgenden neuen Artikel unterteilt, die für .NET 8 aktualisiert wurden:

Beibehalten des Komponentenstatus in einer Blazor-Web App

Sie können den Komponentenstatus in einer Blazor-Web App mit dem vorhandenen Dienst PersistentComponentState beibehalten und lesen. Dies ist nützlich für das Beibehalten des Komponentenstatus während des Prerenderings.

Blazor-Web-Apps behalten automatisch alle registrierten Status auf App-Ebene bei, die während des Prerenderings erstellt wurden, wodurch die Notwendigkeit für den Persist Component State Tag-Helper beseitigt wird.

Formularverarbeitung und Modellbindung

Blazor-Komponenten können jetzt übermittelte Formularanforderungen verarbeiten, einschließlich Modellbindung und Validierung der Anforderungsdaten. Komponenten können Formulare mit separater Formularbehandlung mithilfe des standardmäßigen HTML-Tags <form> oder der vorhandenen EditForm-Komponente implementieren.

Die Modellbindung des Formulars in Blazor berücksichtigt die Datenvertragsattribute (z. B. [DataMember] und [IgnoreDataMember]) zum Anpassen der Bindung der Formulardaten an das Modell.

In .NET 8 ist eine neue Unterstützung zum Schutz vor Fälschungen enthalten. Eine neue AntiforgeryToken-Komponente rendert ein Token für den Fälschungsschutz als verborgenes Feld, und das neue [RequireAntiforgeryToken]-Attribut aktiviert den Schutz. Wenn eine Überprüfung zum Fälschungsschutz fehlschlägt, wird eine Antwort mit Fehlercode 400 (Ungültige Anforderung) ohne Formularverarbeitung zurückgegeben. Die neuen Features zum Schutz vor Fälschungen sind standardmäßig für Formulare aktiviert, die auf Editform basieren, und können manuell auf Standard-HTML-Formulare angewendet werden.

Weitere Informationen finden Sie unter Übersicht über ASP.NET Core Blazor Formulare.

Erweiterte Navigations- und Formularverarbeitung

Statisches serverseitiges Rendering (statisches SSR) führt in der Regel eine vollständige Seitenaktualisierung durch, wenn der Benutzer zu einer neuen Seite navigiert oder ein Formular sendet. In .NET 8 kann Blazor die Seitennavigation und Formularverarbeitung verbessern, indem es die Anforderung abfängt und stattdessen eine Abrufanforderung ausführt. Blazor verarbeitet dann den gerenderten Antwortinhalt, indem es in das Browser-DOM gepatcht wird. Die verbesserte Navigations- und Formularverarbeitung vermeidet die Notwendigkeit einer vollständigen Seitenaktualisierung und behält den Seitenzustand in größerem Umfang bei, sodass Seiten schneller und reibungsloser geladen werden. Die erweiterte Navigation ist standardmäßig aktiviert, wenn das Skript Blazor (blazor.web.js) geladen wird. Die erweiterte Formularbehandlung kann optional für bestimmte Formulare aktiviert werden.

Mit der neuen erweiterten Navigations-API können Sie die aktuelle Seite aktualisieren, indem Sie NavigationManager.Refresh(bool forceLoad = false) aufrufen.

Weitere Informationen finden Sie in den folgenden Abschnitten des Artikels BlazorRouting:

Neuer Artikel zum statischen Rendering mit erweiterter Navigation für JS-Interoperabilität

Einige Anwendungen sind auf JS-Interoperabilität angewiesen, um Initialisierungsaufgaben durchzuführen, die für jede Seite spezifisch sind. Wenn Sie die erweiterte Navigationsfunktion von Blazor mit statisch gerenderten Seiten verwenden, die Interopinitialisierungsaufgaben für JS-Interoperabilität durchführen, werden seitenbezogene JS möglicherweise nicht jedes Mal wie erwartet erneut ausgeführt, wenn eine erweiterte Seitennavigation erfolgt. In einem neuen Artikel wird erläutert, wie Sie dieses Szenario in Blazor-Web-Apps handhaben:

ASP.NET Core Blazor JavaScript mit statischem serverseitigen Rendering (statisches SSR)

Streamingrendering

Sie können jetzt Inhaltsaktualisierungen im Antwortdatenstrom streamen, wenn Sie statisches serverseitiges Rendering (statisches SSR) mit Blazorverwenden. Streamingrendering kann die Benutzererfahrung für Seiten verbessern, die zeitintensive asynchrone Aufgaben ausführen. Dies geschieht durch vollständiges Rendern des Renderinginhalts, sobald dieser verfügbar ist.

Um beispielsweise eine Seite zu rendern, müssen Sie möglicherweise eine zeitintensive Datenbankabfrage oder einen API-Aufruf durchführen. Normalerweise müssen asynchrone Aufgaben, die im Rahmen des Renderns einer Seite ausgeführt werden, abgeschlossen werden, bevor die gerenderte Antwort gesendet wird, wodurch sich das Laden der Seite verzögern kann. Streamingrendering rendert zunächst die gesamte Seite mit Platzhalterinhalten, während asynchrone Vorgänge ausgeführt werden. Nach Abschluss der asynchronen Vorgänge wird der aktualisierte Inhalt über dieselbe Antwortverbindung an den Client gesendet und in das DOM gepatcht. Der Vorteil dieses Ansatzes besteht darin, dass das Hauptlayout der App so schnell wie möglich gerendert wird. Danach wird die Seite aktualisiert, sobald die Inhalte verfügbar sind.

Weitere Informationen finden Sie unter Rendering von Razor-Komponenten in ASP.NET Core.

Einfügen von schlüsselbasierten Diensten in Komponenten

Blazor unterstützt jetzt das Einfügen schlüsselbasierter Dienste mithilfe des [Inject]-Attributs. Schlüssel ermöglichen es, Bereiche für die Registrierung und für den Verbrauch von Diensten bei Verwendung der Abhängigkeitsinjektion festzulegen. Verwenden Sie die neue InjectAttribute.Key-Eigenschaft, um den Schlüssel für den zu injizierenden Dienst anzugeben:

[Inject(Key = "my-service")]
public IMyService MyService { get; set; }

Die @injectRazor-Direktive unterstützt keine wichtigen Dienste für diese Version, aber die Arbeit wird von Update @inject nachverfolgt, um wichtige Dienste (dotnet/razor #9286) für eine zukünftige .NET-Version zu unterstützen.

Weitere Informationen finden Sie unter Abhängigkeitsinjektion in ASP.NET Core Blazor.

Zugreifen auf HttpContext als kaskadierenden Parameter

Sie können jetzt über eine statische Serverkomponente auf den aktuellen HttpContext-Parameter als kaskadierenden Parameter zugreifen:

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

Der Zugrif auf HttpContext von einer statischen Serverkomponente aus kann nützlich sein, um Header oder andere Eigenschaften zu prüfen und zu ändern.

Ein Beispiel für die Übergabe von HttpContext Status-, Zugriffs- und Aktualisierungs-Tokens an Komponenten finden Sie unter Serverseitige ASP.NET CoreBlazor zusätzliche Sicherheitsszenarien.

Rendern von Razor-Komponenten außerhalb von ASP.NET Core

Sie können jetzt Razor-Komponenten außerhalb des Kontexts einer HTTP-Anforderung rendern. Sie können Razor-Komponenten als HTML direkt in eine Zeichenfolge oder einen Stream rendern – unabhängig von der ASP.NET Core-Hostingumgebung. Dies ist praktisch in Szenarien, in denen Sie HTML-Fragmente generieren möchten, beispielsweise zum Generieren von E-Mail- oder statischen Website-Inhalten.

Weitere Informationen finden Sie unter Rendern von Razor-Komponenten außerhalb von ASP.NET Core.

Unterstützung von Abschnitten

Die neuen Komponenten SectionOutlet und SectionContent in Blazor fügen eine Unterstützung zum Angeben von Outlets für Inhalte hinzu, die dann später eingefügt werden können. Abschnitte werden häufig verwendet, um Platzhalter in Layouts zu definieren, die später von bestimmten Seiten ausgefüllt werden. Auf Abschnitte wird entweder durch einen eindeutigen Namen oder mithilfe einer eindeutigen Objekt-ID verwiesen.

Weitere Informationen finden Sie unter Blazor-Abschnitte in ASP.NET Core.

Unterstützung von Fehlerseiten

BlazorWeb-Apps können eine benutzerdefinierte Fehlerseite für die Verwendung mit der ASP.NET Core-Middleware zur Ausnahmebehandlung definieren. Die Blazor-Web App-Projektvorlage enthält eine Standardfehlerseite (Components/Pages/Error.razor) mit ähnlichen Inhalten wie die MVC- und Razor-Seiten-Apps. Wenn die Fehlerseite als Reaktion auf eine Anforderung von der Middleware zur Ausnahmebehandlung gerendert wird, wird die Fehlerseite immer als statische Serverkomponente gerendert, auch wenn ansonsten Interaktivität aktiviert ist.

Error.razor in 8.0 Verweisquelle

QuickGrid

Die Blazor-QuickGrid-Komponente ist jetzt nicht mehr experimentell und damit Bestandteil des Blazor-Frameworks in .NET 8.

QuickGrid ist eine leistungsstarke Rasterkomponente zum Anzeigen von Daten in tabellarischer Form. QuickGrid ist eine einfache und bequeme Möglichkeit zum Anzeigen Ihrer Daten und bietet weiterhin leistungsstarke Features wie Sortieren, Filtern, Paging und Virtualisierung.

Weitere Informationen finden Sie unter ASP.NET Core Blazor QuickGrid-Komponente.

Routen zu benannten Elementen

Blazor unterstützt jetzt die Verwendung von clientseitigem Routing, um auf einer Seite mithilfe von Standard-URL-Fragmenten zu einem bestimmten HTML-Element zu navigieren. Wenn Sie einen Bezeichner für ein HTML-Element mithilfe des id-Standardattributs angeben, wird Blazor ordnungsgemäß zu diesem Element scrollen, wenn das URL-Fragment mit dem Elementbezeichner übereinstimmt.

Weitere Informationen finden Sie unter ASP.NET Core: Routing und Navigation in Blazor.

Kaskadierende Werte auf Stammebene

Kaskadierende Werte auf Stammebene können für die gesamte Komponentenhierarchie registriert werden. Benannte kaskadierende Werte und Abonnements für Updatebenachrichtigungen werden unterstützt.

Weitere Informationen finden Sie unter Kaskadierende Werte und Parameter in Blazor in ASP.NET Core.

Virtualisieren leerer Inhalte

Verwenden Sie den neuen Parameter EmptyContent für die Komponente Virtualize, um Inhalte bereitzustellen, wenn die Komponente geladen wurde und Items entweder leer oder ItemsProviderResult<T>.TotalItemCount null ist.

Weitere Informationen finden Sie unter Razor-Komponentenvirtualisierung in ASP.NET Core.

Schließen von Leitungen, wenn keine verbleibenden interaktiven Serverkomponenten vorhanden sind

Interaktive Serverkomponenten verarbeiten Ereignisse auf der Webbenutzeroberfläche mithilfe einer Echtzeitverbindung mit dem Browser. Sie wird als Leitung bezeichnet. Ein Schaltkreis und sein zugehöriger Status werden eingerichtet, wenn eine interaktive Root-Serverkomponente gerendert wird. Die Verbindung wird geschlossen, wenn keine interaktiven Serverkomponenten auf der Seite vorhanden sind, wodurch Serverressourcen freigegeben werden.

Überwachen der SignalR-Leitungsaktivität

Sie können die Aktivität der eingehenden Leitungsaktivität jetzt in serverseitigen Apps überwachen, indem Sie die neue CreateInboundActivityHandler-Methode für CircuitHandler verwenden. Eingehende Leitungsaktivität ist jede Aktivität, die vom Browser an den Server gesendet wird, z. B. Benutzeroberflächenereignisse oder Interop-Aufrufe von JavaScript an .NET.

Weitere Informationen finden Sie in den Anleitungen zu ASP.NET Core BlazorSignalR.

Schnellere Laufzeitleistung mit Jiterpreter

Jiterpreter ist ein neues Laufzeitfeature in .NET 8, das eine partielle Just-in-Time-Kompilierungsunterstützung (JIT) ermöglicht, wenn es in WebAssembly ausgeführt wird, um eine verbesserte Laufzeitleistung zu erzielen.

Weitere Informationen finden Sie unter Hosten und Bereitstellen von Blazor WebAssembly in ASP.NET Core.

AOT(Ahead-of-Time) SIMD und Ausnahmebehandlung

Blazor WebAssembly-AOT-Kompilierung (Ahead-of-Time) verwendet jetzt standardmäßig WebAssembly Fixed-Width SIMD und WebAssembly-Ausnahmebehandlung, um die Laufzeitleistung zu verbessern.

Weitere Informationen finden Sie in den folgenden Artikeln:

Webfreundliche Webcil-Pakete

Webcil ist ein webfreundliches Tool zum Verpacken von .NET-Assemblys, das Inhalte, die für die systemeigene Windows-Ausführung spezifisch sind, entfernt, um Probleme beim Bereitstellen in Umgebungen zu vermeiden, die den Download oder die Verwendung von .dll-Dateien blockieren. Webcil ist für Blazor WebAssembly-Apps standardmäßig aktiviert.

Weitere Informationen finden Sie unter Hosten und Bereitstellen von Blazor WebAssembly in ASP.NET Core.

Hinweis

Vor der Veröffentlichung von .NET 8 wurden in der Anleitung zum Deployment-Layout für ASP.NET Core gehostete Blazor WebAssembly-Apps Umgebungen angesprochen, die Clients am Herunterladen und Ausführen von DLLs mit einem mehrteiligen Bündelungsansatz hindern. In .NET 8 oder höher verwendet Blazor das Webcil-Dateiformat, um dieses Problem zu beheben. Multipart-Bündelung mithilfe des experimentellen NuGet-Pakets, das im Artikel WebAssembly-Bereitstellungslayout beschrieben wird, wird für Blazor-Apps in .NET 8 oder höher nicht unterstützt. Weitere Informationen finden Sie unter Verbessern des Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle-Pakets, um ein benutzerdefiniertes Paketformat (dotnet/aspnetcore #36978) zu definieren. Wenn Sie das mehrteilige Paket in .NET 8 oder höheren Apps weiterhin verwenden möchten, können Sie die Anleitungen im Artikel verwenden, um Ihr eigenes mehrteiliges NuGet-Bündelungspaket zu erstellen, das aber von Microsoft nicht unterstützt wird.

Blazor WebAssembly: Verbesserungen beim Debuggen

Beim Debuggen von .NET in WebAssembly lädt der Debugger jetzt Symboldaten von Symbolspeicherorten herunter, die in den Visual Studio-Einstellungen konfiguriert sind. Dies verbessert das Debuggen für Apps, die NuGet-Pakete verwenden.

Sie können Blazor WebAssembly-Apps jetzt mithilfe von Firefox debuggen. Zum Debuggen von Blazor WebAssembly-Apps muss der Browser für das Remotedebuggen konfiguriert und dann eine Verbindung mit dem Browser mithilfe der Browserentwicklertools über den .NET-WebAssembly-Debugproxy hergestellt werden. Das Debuggen in Firefox über Visual Studio wird derzeit nicht unterstützt.

Weitere Informationen finden Sie unter Debuggen von ASP.NET Core Blazor-Apps.

Kompatibilität mit der Inhaltssicherheitsrichtlinie (Content Security Policy, CSP)

Blazor WebAssembly erfordert nicht länger das Aktivieren der unsafe-eval-Skriptquelle beim Angeben einer Inhaltssicherheitsrichtlinie (Content Security Policy, CSP).

Weitere Informationen finden Sie unter Erzwingen einer Inhaltssicherheitsrichtlinie für Blazor in ASP.NET Core.

Behandeln abgefangener Ausnahmen außerhalb des Lebenszyklus einer Razor-Komponente

Verwenden Sie ComponentBase.DispatchExceptionAsync in einer Razor-Komponente, um Ausnahmen zu verarbeiten, die außerhalb der Lebenszyklus-Aufrufliste der Komponente ausgelöst werden. Dadurch kann der Code der Komponente Ausnahmen so behandeln, als ob es sich um Lebenszyklusmethoden-Ausnahmen handelt. Anschließend können Blazor-Fehlerbehandlungsmechanismen wie Fehlerbegrenzungen die Ausnahmen verarbeiten.

Weitere Informationen finden Sie unter Fehlerbehandlung in Blazor-Apps in ASP.NET Core.

Konfigurieren der .NET-WebAssembly-Runtime

Die .NET WebAssembly-Laufzeit kann jetzt für den Blazor-Start konfiguriert werden.

Weitere Informationen finden Sie unter Starten von ASP.NET CoreBlazor.

Konfiguration von Verbindungstimeouts in HubConnectionBuilder

Bisherige Problemumgehungen zum Konfigurieren von Hubverbindungstimeouts können durch eine formale SignalR-Timeoutkonfiguration des Hubverbindungs-Generators ersetzt werden.

Weitere Informationen finden Sie unter

Projektvorlagen ohne Open Iconic

Die Blazor-Projektvorlagen sind nicht mehr von Open Iconic für Symbole abhängig.

Unterstützung für Abbrechen- und Schließen-Ereignisse in Dialogfeldern

Blazor unterstützt jetzt die Ereignisse cancel und close für das HTML-Element dialog.

Im folgenden Beispiel:

  • OnClose wird aufgerufen, wenn das Dialogfeld my-dialog mit der Schaltfläche Schließen geschlossen wird.
  • OnCancel wird aufgerufen, wenn der Dialog mit der Esc-Taste abgebrochen wird. Beachten Sie, dass beim Schließen eines HTML-Dialogs mit der Esc-Taste sowohl das Ereignis cancel als auch das Ereignis close ausgelöst werden.
<div>
    <p>Output: @message</p>

    <button onclick="document.getElementById('my-dialog').showModal()">
        Show modal dialog
    </button>

    <dialog id="my-dialog" @onclose="OnClose" @oncancel="OnCancel">
        <p>Hi there!</p>

        <form method="dialog">
            <button>Close</button>
        </form>
    </dialog>
</div>

@code {
    private string? message;

    private void OnClose(EventArgs e) => message += "onclose, ";

    private void OnCancel(EventArgs e) => message += "oncancel, ";
}

BlazorIdentity Benutzeroberfläche

Blazor unterstützt das Generieren einer vollständigen Blazor-basierten Identity-Benutzeroberfläche, wenn Sie die Authentifizierungsoption für einzelne Konten auswählen. Sie können entweder die Option für individuelle Konten im Dialogfeld „Neues Projekt“ für Blazor-Web-Apps in Visual Studio auswählen oder die auf Individual festgelegte -au|--auth-Option über die Befehlszeile übergeben, wenn Sie ein neues Projekt erstellen.

Weitere Informationen finden Sie in den folgenden Ressourcen:

Schützen von Blazor WebAssembly mit ASP.NET Core Identity

Die Blazor-Dokumentation enthält einen neuen Artikel und eine Beispiel-App, um das Sichern einer eigenständigen Blazor WebAssembly-App mit ASP.NET Core Identityabzudecken.

Weitere Informationen finden Sie in den folgenden Ressourcen:

Blazor Server mit Yarp-Routing

Routing und Deep Linking für Blazor Server mit Yarp funktionieren in .NET 8 ordnungsgemäß.

Weitere Informationen finden Sie unter Migrieren von ASP.NET Core 7.0 zu 8.0.

Blazor Hybrid

Die folgenden Artikel dokumentieren Änderungen für Blazor Hybrid in .NET 8:

  • Problembehandlung in ASP.NET Core Blazor Hybrid: In einem neuen Artikel wird erläutert, wie die BlazorWebView-Protokollierung verwendet wird.
  • Erstellen einer .NET MAUIBlazor Hybrid-App: Der Name .NET MAUI Blazor der Projektvorlage wurde in .NET MAUI Blazor Hybrid geändert.
  • ASP.NET Core Blazor Hybrid: BlazorWebView verfügt über eine TryDispatchAsync-Methode, die eine angegebene Action<ServiceProvider>-Methode asynchron aufruft und die in Razor-Komponenten verfügbaren bereichsbezogenen Dienste übergibt. Auf diese Weise kann Code über die native Benutzeroberfläche auf bereichsbezogene Dienste zugreifen, z. B. NavigationManager.
  • ASP.NET Core Blazor Hybrid-Routing und -Navigation: Verwenden Sie die Eigenschaft BlazorWebView.StartPath, um den Pfad für die anfängliche Navigation im Navigationskontext Blazor abzurufen oder festzulegen, wenn der Ladevorgang der Komponente Razor abgeschlossen wurde.

Das [Parameter]-Attribut ist nicht mehr erforderlich, wenn die Bereitstellung über die Abfragezeichenfolge erfolgt.

Das [Parameter]-Attribut ist nicht mehr erforderlich, wenn ein Parameter über die Abfragezeichenfolge bereitgestellt wird:

- [Parameter]
  [SupplyParameterFromQuery]

SignalR

Neuer Ansatz zum Festlegen von Servertimeout und Keep-Alive Intervall

ServerTimeout (Standardwert 30 Sekunden) und KeepAliveInterval (Standardwert 15 Sekunden) können direkt im HubConnectionBuilder festgelegt werden.

Ehemaliger Ansatz für JavaScript-Clients

Das folgende Beispiel zeigt die Zuweisung von Werten, die doppelt so hoch wie die Standardwerte in ASP.NET Core 7.0 oder früher sind:

var connection = new signalR.HubConnectionBuilder()
  .withUrl("/chatHub")
  .build();

connection.serverTimeoutInMilliseconds = 60000;
connection.keepAliveIntervalInMilliseconds = 30000;

Neuer Ansatz für JavaScript-Clients

Das folgende Beispiel zeigt den neuen Ansatz für die Zuweisung von Werten, die doppelt so hoch wie die Standardwerte in ASP.NET Core 8.0 oder höher sind:

var connection = new signalR.HubConnectionBuilder()
  .withUrl("/chatHub")
  .withServerTimeout(60000)
  .withKeepAlive(30000)
  .build();

Ehemaliger Ansatz für den JavaScript-Client einer Blazor Server-App

Das folgende Beispiel zeigt die Zuweisung von Werten, die doppelt so hoch wie die Standardwerte in ASP.NET Core 7.0 oder früher sind:

Blazor.start({
  configureSignalR: function (builder) {
    let c = builder.build();
    c.serverTimeoutInMilliseconds = 60000;
    c.keepAliveIntervalInMilliseconds = 30000;
    builder.build = () => {
      return c;
    };
  }
});

Neuer Ansatz für den JavaScript-Client der serverseitigen Blazor App

Das folgende Beispiel zeigt den neuen Ansatz für die Zuweisung von Werten, die doppelt so hoch wie die Standardwerte in ASP.NET Core 8.0 oder höher sind für Blazor Web Apps und Blazor Server.

Blazor Web-App:

Blazor.start({
  circuit: {
    configureSignalR: function (builder) {
      builder.withServerTimeout(60000).withKeepAliveInterval(30000);
    }
  }
});

Blazor Server:

Blazor.start({
  configureSignalR: function (builder) {
    builder.withServerTimeout(60000).withKeepAliveInterval(30000);
  }
});

Ehemaliger Ansatz für .NET-Clients

Das folgende Beispiel zeigt die Zuweisung von Werten, die doppelt so hoch wie die Standardwerte in ASP.NET Core 7.0 oder früher sind:

var builder = new HubConnectionBuilder()
    .WithUrl(Navigation.ToAbsoluteUri("/chathub"))
    .Build();

builder.ServerTimeout = TimeSpan.FromSeconds(60);
builder.KeepAliveInterval = TimeSpan.FromSeconds(30);

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

await builder.StartAsync();

Neuer Ansatz für .NET-Clients

Das folgende Beispiel zeigt den neuen Ansatz für die Zuweisung von Werten, die doppelt so hoch wie die Standardwerte in ASP.NET Core 8.0 oder höher sind:

var builder = new HubConnectionBuilder()
    .WithUrl(Navigation.ToAbsoluteUri("/chathub"))
    .WithServerTimeout(TimeSpan.FromSeconds(60))
    .WithKeepAliveInterval(TimeSpan.FromSeconds(30))
    .Build();

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

await builder.StartAsync();

SignalR zustandsbehaftete erneute Verbindung

Die zustandsbehaftete SignalR-Wiederherstellung der Verbindung reduziert die wahrgenommene Ausfallzeit von Clients, die eine vorübergehende Unterbrechung in ihrer Netzwerkverbindung aufweisen, z. B. beim Wechsel von Netzwerkverbindungen oder einem kurzen temporären Zugriffsverlust.

Die zustandsbehaftete Wiederherstellung der Verbindung ermöglicht Folgendes:

  • Vorübergehendes Puffern von Daten auf dem Server und Client.
  • Bestätigen von Nachrichten, die sowohl vom Server als auch vom Client empfangen werden (ACK-ing).
  • Erkennen, wenn eine Verbindung zurückkehrt, und Wiedergeben von Nachrichten, die möglicherweise gesendet wurden, während die Verbindung unterbrochen war.

Zustandsbehaftete erneute Verbindung ist in ASP.NET Core 8.0 und höher verfügbar.

Melden Sie sich an, um eine zustandsbehaftete erneute Verbindung sowohl am Serverhub-Endpunkt als auch am Client herzustellen:

  • Aktualisieren Sie die Konfiguration des Serverhub-Endpunkts, um die Option AllowStatefulReconnects zu aktivieren:

    app.MapHub<MyHub>("/hubName", options =>
    {
        options.AllowStatefulReconnects = true;
    });
    

    Optional kann die vom Server zulässige maximale Puffergröße in Bytes global oder für einen bestimmten Hub mit der StatefulReconnectBufferSize Option festgelegt werden:

    Die StatefulReconnectBufferSize global festgelegte Option:

    builder.AddSignalR(o => o.StatefulReconnectBufferSize = 1000);
    

    Die StatefulReconnectBufferSize für einen bestimmten Hub festgelegte Option:

    builder.AddSignalR().AddHubOptions<MyHub>(o => o.StatefulReconnectBufferSize = 1000);
    

    Die StatefulReconnectBufferSize Option ist optional mit einer Standardeinstellung von 100.000 Bytes.

  • Aktualisieren Sie den JavaScript- oder TypeScript-Clientcode, um die withStatefulReconnect Option zu aktivieren:

    const builder = new signalR.HubConnectionBuilder()
      .withUrl("/hubname")
      .withStatefulReconnect({ bufferSize: 1000 });  // Optional, defaults to 100,000
    const connection = builder.build();
    

    Die bufferSize Option ist optional mit einer Standardeinstellung von 100.000 Bytes.

  • Aktualisieren Sie den .NET-Clientcode, um die WithStatefulReconnect Option zu aktivieren:

      var builder = new HubConnectionBuilder()
          .WithUrl("<hub url>")
          .WithStatefulReconnect();
      builder.Services.Configure<HubConnectionOptions>(o => o.StatefulReconnectBufferSize = 1000);
      var hubConnection = builder.Build();
    

    Die StatefulReconnectBufferSize Option ist optional mit einer Standardeinstellung von 100.000 Bytes.

Weitere Informationen finden Sie unter Zustandsbehaftete erneute Verbindung konfigurieren.

Minimale APIs

In diesem Abschnitt werden neue Features für minimale APIs beschrieben. Weitere relevante Informationen zu minimalen APIs finden Sie auch im Abschnitt zu nativem AOT.

Überschreiben der Kultur durch Benutzer*innen

Ab ASP.NET Core 8.0 ermöglicht die Eigenschaft RequestLocalizationOptions.CultureInfoUseUserOverride der Anwendung, zu entscheiden, ob nicht standardmäßige Windows-Einstellungen für die Eigenschaften CultureInfoDateTimeFormat und NumberFormat verwendet werden dürfen. Dies hat in Linux keine Auswirkungen. Dies ist eine direkte Entsprechung von UseUserOverride.

    app.UseRequestLocalization(options =>
    {
        options.CultureInfoUseUserOverride = false;
    });

Binden an Formulare

Explizite Bindung an Formularwerte mithilfe des [FromForm]-Attributs wird jetzt unterstützt. Parameter, die an die Anforderung mit [FromForm] gebunden sind, enthalten ein Anti-Fälschungstoken. Das Anti-Fälschungstoken wird überprüft, wenn die Anforderung verarbeitet wird.

Die abgeleitete Bindung an Formulare mithilfe von IFormCollection-, IFormFile-und IFormFileCollection-Typen wird ebenfalls unterstützt. OpenAPI-Metadaten werden für Formularparameter abgeleitet, um die Integration mit der Swagger-Benutzeroberfläche zu unterstützen.

Weitere Informationen finden Sie unter

Die Bindung aus Formularen wird jetzt für Folgendes unterstützt:

  • Sammlungen, z. B . Liste und Wörterbuch
  • Komplexe Typen, z. B. Todo oder Project

Weitere Informationen finden Sie unter Binden an Sammlungen und komplexe Typen aus Formularen.

Schutz vor Fälschung mit Minimal-APIs

Diese Version fügt eine Middleware für die Validierung von Antiforgery-Tokens hinzu, die verwendet werden, um siteübergreifende Anforderungsfälschungsangriffe zu entschärfen. Rufen Sie AddAntiforgery auf, um Dienste zum Schutz vor Fälschung in DI zu registrieren. WebApplicationBuilder fügt die Middleware automatisch hinzu, wenn die Fälschungsschutzdienste im DI-Container registriert wurden. Token zum Schutz vor Fälschung werden verwendet, um websiteübergreifende Anforderungsfälschungsangriffe zu entschärfen.

var builder = WebApplication.CreateBuilder();

builder.Services.AddAntiforgery();

var app = builder.Build();

app.UseAntiforgery();

app.MapGet("/", () => "Hello World!");

app.Run();

Für die Middleware zum Schutz vor Fälschung gilt Folgendes:

Das Token zum Schutz vor Fälschung wird nur in folgenden Fällen überprüft:

  • Der Endpunkt enthält Metadaten, die IAntiforgeryMetadata mit RequiresValidation=true implementieren.
  • Die dem Endpunkt zugeordnete HTTP-Methode ist eine relevante HTTP-Methode. Die relevanten Methoden sind alle HTTP-Methoden außer TRACE, OPTIONS, HEAD und GET.
  • Die Anforderung ist einem gültigen Endpunkt zugeordnet.

Weitere Informationen finden Sie unter Schutz vor Fälschung mit Minimal APIs.

Neue IResettable Schnittstelle in ObjectPool

Microsoft.Extensions.ObjectPool bietet Unterstützung für das Poolen von Objektinstanzen im Arbeitsspeicher. Apps können einen Objektpool verwenden, wenn das Zuweisen oder Initialisieren von Werten teuer ist.

In diesem Release haben wir die Verwendung des Objektpools durch Hinzufügen der Schnittstelle IResettable vereinfacht. Wiederverwendbare Typen müssen zwischen den Verwendungen häufig auf einen Standardzustand zurückgesetzt werden. IResettable-Typen werden automatisch zurückgesetzt, wenn sie an einen Objektpool zurückgegeben werden.

Weitere Informationen finden Sie im ObjectPool-Beispiel.

Natives AOT

Es wurde Unterstützung für die native Ahead-of-Time-Kompilierung (AOT) in .NET hinzugefügt. Apps, die mit AOT veröffentlicht werden, können wesentlich bessere Leistung aufweisen: kleinere App-Größe, weniger Arbeitsspeicherauslastung und schnellere Startzeit. Die native AOT wird derzeit von gRPC, minimaler API und Workerdienst-Apps unterstützt. Weitere Informationen finden Sie unter ASP.NET Core-Unterstützung für natives AOT und im Tutorial Veröffentlichen einer ASP.NET Core-App mit nativem AOT. Informationen zu bekannten Problemen mit ASP.NET Core und zur Kompatibilität mit nativem AOT finden Sie im GitHub-Issue dotnet/core #8288.

Bibliotheken und natives AOT

Viele der beliebten Bibliotheken, die in ASP.NET Core-Projekten verwendet werden, weisen derzeit einige Kompatibilitätsprobleme auf, wenn sie in einem Projekt für natives AOT verwendet werden, z. B.:

  • Verwendung der Reflektion zum Untersuchen und Ermitteln von Typen.
  • Bedingtes Laden von Bibliotheken zur Laufzeit.
  • Automatisches Generieren von Code zum Implementieren von Funktionen.

Bibliotheken, die diese dynamischen Features verwenden, müssen aktualisiert werden, um mit nativem AOT zu funktionieren. Sie können mithilfe von Tools wie Roslyn-Quellgeneratoren aktualisiert werden.

Bibliotheksautoren, die natives AOT unterstützen möchten, wird Folgendes empfohlen:

Neue Projektvorlage

Die neue Projektvorlage ASP.NET Core-Web-API (natives AOT) (Kurzname webapiaot) erstellt ein Projekt mit aktivierter AOT-Veröffentlichung. Weitere Informationen finden Sie in der Web-API-Vorlage (natives AOT).

Neue CreateSlimBuilder-Methode

Die in der Web-API-Vorlage (natives AOT) verwendete CreateSlimBuilder()-Methode initialisiert den WebApplicationBuilder mit den minimalen ASP.NET Core-Features, die zum Ausführen einer App erforderlich sind. Die CreateSlimBuilder-Methode enthält die folgenden Features, die für eine effiziente Entwicklungsumgebung erforderlich sind:

  • JSON-Dateikonfiguration für appsettings.json und appsettings.{EnvironmentName}.json.
  • Konfiguration der Benutzergeheimnisse.
  • Konsolenprotokollierung.
  • Konfiguration der Protokollierung.

Weitere Informationen finden Sie unter der CreateSlimBuilder-Methode.

Neue CreateEmptyBuilder-Methode

Es gibt eine weitere neue WebApplicationBuilder-Factorymethode zum Erstellen kleiner Apps, die nur erforderliche Funktionen enthalten: WebApplication.CreateEmptyBuilder(WebApplicationOptions options). Diese WebApplicationBuilder wird ohne integriertes Verhalten erstellt. Die erstellte App enthält nur die Dienste und Middleware, die explizit konfiguriert wurden.

Hier ist ein Beispiel für die Verwendung dieser API zum Erstellen einer kleinen Webanwendung:

var builder = WebApplication.CreateEmptyBuilder(new WebApplicationOptions());
builder.WebHost.UseKestrelCore();

var app = builder.Build();

app.Use(async (context, next) =>
{
    await context.Response.WriteAsync("Hello, World!");
    await next(context);
});

Console.WriteLine("Running...");
app.Run();

Die Veröffentlichung dieses Codes mit nativem AOT und .NET 8 Preview 7 auf einem Linux-x64-Computer führt zu einer eigenständigen nativen ausführbaren Datei von ca. 8,5 MB.

Reduzierte App-Größe mit konfigurierbarer HTTPS-Unterstützung

Wir haben die Binärdateigröße von nativem AOT für Apps, die keine HTTPS- oder HTTP/3-Unterstützung benötigen, weiter reduziert. Der Verzicht auf HTTPS oder HTTP/3 ist bei Apps üblich, die hinter einem TLS-Terminierungsproxy ausgeführt werden (z. B. in Azure gehostet). Bei der neuen WebApplication.CreateSlimBuilder-Methode wird diese Funktionalität standardmäßig ausgelassen. Sie kann hinzugefügt werden, indem builder.WebHost.UseKestrelHttpsConfiguration() für HTTPS oder builder.WebHost.UseQuic() für HTTP/3 aufgerufen wird. Weitere Informationen finden Sie unter der CreateSlimBuilder-Methode.

JSON-Serialisierung von compilergenerierten IAsyncEnumerable<T>-Typen

Neue Features wurden System.Text.Json hinzugefügt, um natives AOT besser zu unterstützen. Diese neuen Features fügen Funktionen für den Quellgenerierungsmodus System.Text.Json hinzu, da die Spiegelung von AOT nicht unterstützt wird.

Eines der neuen Features ist die Unterstützung für JSdie ON-Serialisierung von IAsyncEnumerable<T>-Implementierungen, die vom C#-Compiler implementiert werden. Diese Unterstützung ermöglicht ihre Verwendung in ASP.NET Core-Projekten, die zum Veröffentlichen mit nativem AOT konfiguriert werden.

Diese API ist in Szenarios hilfreich, in denen ein Routenhandler yield return verwendet, um eine Enumeration asynchron zurückzugeben. Ein Beispiel ist das Materialisieren von Zeilen aus einer Datenbankabfrage. Weitere Informationen finden Sie unter Unterstützung für compilergenerierte Typen in der Ankündigung von .NET 8 Preview 4.

Weitere Informationen zu weiteren Verbesserungen bei der System.Text.Json-Quellgenerierung finden Sie unter Serialisierungsverbesserungen in .NET 8.

APIs auf oberster Ebene, die für Warnungen zum Kürzen kommentiert wurden

Die wichtigsten Einstiegspunkte zu Subsystemen, die nicht zuverlässig mit nativem AOT funktionieren, werden jetzt kommentiert. Wenn diese Methoden von einer Anwendung mit aktiviertem nativem AOT aufgerufen werden, wird eine Warnung bereitgestellt. Der folgende Code erzeugt zum Beispiel eine Warnung beim Aufruf von AddControllers, da diese API nicht kürzungssicher ist und von nativem AOT nicht unterstützt wird.

Visual Studio-Fenster mit Warnmeldung IL2026 für die AddControllers-Methode, mit dem Hinweis, dass MVC derzeit keine native AOT-Kompilierung unterstützt

Anforderungsdelegat-Generator

Um Kompatibilität zwischen Minimal-APIs und nativem AOT sicherzustellen, führen wir den Request Delegate Generator (RDG) ein. Der RDG ist ein Quellgenerator, der die gleichen Aufgaben erfüllt wie die RequestDelegateFactory (RDF). Das heißt, er wandelt verschiedene MapGet()-, MapPost()- und ähnliche Aufrufe in RequestDelegate-Instanzen um, die den angegebenen Routen zugeordnet sind. Aber anstatt diese Aufgabe beim Start einer Anwendung im Arbeitsspeicher auszuführen, erledigt der RDG dies zur Kompilierzeit und generiert C#-Code direkt im Projekt. Der RDG:

  • Sorgt dafür, dass dieser Code nicht zur Laufzeit generiert wird.
  • Stellt sicher, dass die in APIs verwendeten Typen von der Toolkette für natives AOT statisch analysiert werden können.
  • Stellt sicher, dass der erforderliche Code nicht weggekürzt wird.

Wir arbeiten daran, dass möglichst viele der Minimal-API-Features vom RDG unterstützt werden und somit mit nativem AOT kompatibel sind.

Der RDG wird automatisch in einem Projekt aktiviert, wenn die Veröffentlichung mit nativem AOT aktiviert ist. Der RDG kann auch ohne natives AOT manuell aktiviert werden, indem Sie <EnableRequestDelegateGenerator>true</EnableRequestDelegateGenerator> in der Projektdatei festlegen. Das kann nützlich sein, wenn Sie zunächst die Eignung eines Projekts für natives AOT beurteilen oder die Startzeit einer App verkürzen möchten.

Verbesserte Leistung mithilfe von Interceptors

Der Anforderungsdelegat-Generator verwendet das neue Compilerfeature für C# 12-Interceptors, um das Abfangen von Aufrufen von Map-Methoden der Minimal-API mit statisch generierten Varianten zur Laufzeit zu unterstützen. Die Verwendung von Interceptors führt zu einer höheren Startleistung für Apps, die mit PublishAot kompiliert wurden.

Protokollierung und Ausnahmebehandlung in zur Kompilierzeit generierten minimalen APIs

Minimale APIs, die zur Laufzeit generiert werden, unterstützen automatische Protokollierung (oder das Auslösen von Ausnahmen in Entwicklungsumgebungen), wenn die Parameterbindung fehlschlägt. .NET 8 führt die gleiche Unterstützung für APIs ein, die zur Kompilierzeit über den Anforderungsdelegat-Generator (Request Delegate Generator, RDG) generiert werden. Weitere Informationen finden Sie unter Protokollierung und Ausnahmebehandlung in zur Kompilierzeit generierten minimalen APIs.

AOT und „System.Text.Json“

Minimal-APIs sind für den Empfang und die Rückgabe von JSON-Nutzdaten unter Verwendung von System.Text.Json optimiert, daher gelten auch die Kompatibilitätsanforderungen für JSON und natives AOT. Die native AOT-Kompilierung erfordert die Verwendung des System.Text.Json-Quellgenerators. Alle Typen, die als Parameter von Anforderungsdelegaten in Minimal-APIs akzeptiert oder von diesen zurückgegeben werden, müssen für einen JsonSerializerContext konfiguriert werden, der über die Abhängigkeitsinjektion von ASP.NET Core registriert ist, z. B.:

// Register the JSON serializer context with DI
builder.Services.ConfigureHttpJsonOptions(options =>
{
    options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
});

...

// Add types used in the minimal API app to source generated JSON serializer content
[JsonSerializable(typeof(Todo[]))]
internal partial class AppJsonSerializerContext : JsonSerializerContext
{

}

Weitere Informationen zur TypeInfoResolverChain-API finden Sie in folgenden Ressourcen:

Bibliotheken und natives AOT

Viele der gängigen Bibliotheken, die derzeit für ASP.NET Core-Projekte verfügbar sind, weisen gewisse Kompatibilitätsprobleme auf, wenn sie in einem Projekt mit nativem AOT verwendet werden. Beliebte Bibliotheken stützen sich häufig auf die dynamische Funktionalität der .NET-Reflektion, um Typen zu untersuchen und zu ermitteln, Bibliotheken zur Laufzeit bedingt zu laden und Code zur Implementierung ihrer Funktionen „on the fly“ zu generieren. Diese Bibliotheken müssen aktualisiert werden, um mit nativem AOT zu funktionieren. Dazu verwenden Sie Tools wie beispielsweise Roslyn-Quellgeneratoren.

Bibliotheksautoren, die mehr über die Vorbereitung ihrer Bibliotheken für natives AOT erfahren möchten, sollten zunächst ihre Bibliothek für Kürzungen vorbereiten und sich über die Kompatibilitätsanforderungen für natives AOT informieren.

Kestrel und HTTP.sys-Server

Es gibt mehrere neue Features für Kestrel und „HTTP.sys“.

Unterstützung für Named Pipes in Kestrel

Named Pipes sind eine beliebte Technologie zum Aufbau der prozessübergreifenden Kommunikation (Inter-Process Communication, IPC) zwischen Windows-Apps. Sie können ab sofort einen IPC-Server mit .NET, Kestrel und Named Pipes erstellen.

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.ListenNamedPipe("MyPipeName");
});

Weitere Informationen zu diesem Feature und zur Verwendung von .NET und gRPC zum Erstellen eines IPC-Servers und -Clients finden Sie unter Prozessübergreifende Kommunikation mit gRPC.

Leistungsverbesserungen beim Transport von Named Pipes

Wir haben die Leistung der Named Pipe-Verbindung verbessert. Der Named Pipe-Transport von Kestrel akzeptiert jetzt parallele Verbindungen und verwendet NamedPipeServerStream-Instanzen wieder .

Zeit zum Erstellen von 100.000 Verbindungen:

  • Vorher: 5.916 Sekunden
  • Nachher: 2,374 Sekunden

Unterstützung für HTTP/2 über TLS (HTTPS) unter macOS in Kestrel

.NET 8 fügt Unterstützung für Application-Layer Protocol Negotiation (ALPN) zu macOS hinzu. ALPN ist ein TLS-Feature, das verwendet wird, um auszuhandeln, welches HTTP-Protokoll eine Verbindung verwendet. Beispielsweise ermöglicht ALPN es Browsern und anderen HTTP-Clients, eine HTTP/2-Verbindung anzufordern. Dieses Feature ist besonders nützlich für gRPC-Apps, die HTTP/2 erfordern. Weitere Informationen finden Sie unter Verwenden von HTTP/2 mit dem ASP.NET Core-Kestrel-Webserver.

Überwachung der Zertifikatdatei in Kestrel

TLS-Zertifikate, die nach Pfad konfiguriert wurden, werden jetzt auf Änderungen überwacht, wenn reloadOnChange an KestrelServerOptions.Configure() übergeben wird. Eine Änderung an der Zertifikatdatei wird genauso behandelt wie eine Änderung am konfigurierten Pfad (d. h. Endpunkte werden erneut geladen).

Beachten Sie, dass Dateilöschungen nicht nachverfolgt werden, da sie vorübergehend sind und der Server abstürzen würde, wenn sie nicht vorübergehend sind.

Warnung, wenn die angegebenen HTTP-Protokolle nicht verwendet werden

Wenn TLS deaktiviert und HTTP/1.x verfügbar ist, werden HTTP/2 und HTTP/3 deaktiviert, selbst wenn sie angegeben wurden. Da dies zu bösen Überraschungen führen kann, wurde eine Warnmeldung hinzugefügt, die Sie in einem solchen Fall informiert.

HTTP_PORTS- und HTTPS_PORTS-Konfigurationsschlüssel

Anwendungen und Container erhalten häufig nur einen Port, dem sie lauschen können, z. B. Port 80, und keine zusätzlichen Einschränkungen für den Host oder Pfad. HTTP_PORTS und HTTPS_PORTS sind neue Konfigurationsschlüssel, die die Lauschports für Kestrel- und HTTP.sys-Server angeben. Diese können mit den Präfixen DOTNET_ oder ASPNETCORE_ der Umgebungsvariable definiert werden oder direkt über andere Konfigurationseingaben wie „appsettings.json“ angegeben werden. Jede ist eine durch Semikolons getrennte Liste der Portwerte. Beispiel:

ASPNETCORE_HTTP_PORTS=80;8080
ASPNETCORE_HTTPS_PORTS=443;8081

Dies ist eine Abkürzung für folgenden Code, der das Schema (HTTP oder HTTPS) und alle Hosts oder IP-Adressen angibt:

ASPNETCORE_URLS=http://*:80/;http://*:8080/;https://*:443/;https://*:8081/

Weitere Informationen finden Sie unter Konfigurieren von Endpunkten für die ASP.NET Core Kestrel-Webserver und HTTP.sys-Webserverimplementierung in ASP.NET Core.

SNI-Hostname in ITlsHandshakeFeature

Der Hostname der Servernamensanzeige (Server Name Indication, SNI) wird jetzt in der HostName-Eigenschaft der ITlsHandshakeFeature-Schnittstelle verfügbar gemacht.

Die Servernamensanzeige (Server Name Indication, SNI) ist Teil des TLS-Handshakeprozesses. Damit können Clients den Hostnamen angeben, mit dem sie eine Verbindung herstellen möchten, wenn der Server mehrere virtuelle Hosts oder Domänen hostet. Um das richtige Sicherheitszertifikat während des Handshakeprozesses zu präsentieren, muss der Server den für jede Anforderung ausgewählten Hostnamen kennen.

Normalerweise wird der Hostname nur innerhalb des TLS-Stapels behandelt und zum Auswählen des übereinstimmenden Zertifikats verwendet. Durch die Offenlegung können jedoch andere Komponenten in einer App diese Informationen zu Diagnose-, Ratenbegrenzungs-, Routing- und Abrechnungszwecken verwenden.

Die Offenlegung des Hostnamens ist nützlich für große Dienste, die Tausende von SNI-Bindungen verwalten. Dieses Feature kann die Debugeffizienz bei Kundeneskalationen erheblich verbessern. Die erhöhte Transparenz ermöglicht eine schnellere Problemlösung und eine höhere Zuverlässigkeit des Diensts.

Weitere Informationen finden Sie unter ITlsHandshakeFeature.HostName.

IHttpSysRequestTimingFeature

IHttpSysRequestTimingFeature stellt detaillierte Informationen zum Zeitablauf für Anforderungen bereit, wenn Sie den HTTP.sys-Server und das In-Process-Hosting mit IIS verwenden:

  • Zeitstempel werden mithilfe von QueryPerformanceCounter abgerufen.
  • Die Zeitstempelhäufigkeit kann über QueryPerformanceFrequency abgerufen werden.
  • Der Index der Zeitangaben kann in HttpSysRequestTimingType umgewandelt werden, um zu ermitteln, wofür die Zeitangaben stehen.
  • Der Wert kann 0 lauten, wenn keine Zeitangaben für die aktuelle Anforderung verfügbar sind.

IHttpSysRequestTimingFeature.TryGetTimestamp ruft den Zeitstempel für den angegebenen Zeittyp ab:

using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.HttpSys;
var builder = WebApplication.CreateBuilder(args);

builder.WebHost.UseHttpSys();

var app = builder.Build();

app.Use((context, next) =>
{
    var feature = context.Features.GetRequiredFeature<IHttpSysRequestTimingFeature>();

    var loggerFactory = context.RequestServices.GetRequiredService<ILoggerFactory>();
    var logger = loggerFactory.CreateLogger("Sample");

    var timingType = HttpSysRequestTimingType.RequestRoutingEnd;

    if (feature.TryGetTimestamp(timingType, out var timestamp))
    {
        logger.LogInformation("Timestamp {timingType}: {timestamp}",
                                          timingType, timestamp);
    }
    else
    {
        logger.LogInformation("Timestamp {timingType}: not available for the "
                                           + "current request",    timingType);
    }

    return next(context);
});

app.MapGet("/", () => Results.Ok());

app.Run();

Weitere Informationen finden Sie unter Abrufen detaillierter Zeitangaben mit „IHttpSysRequestTimingFeature“ und unter Zeitangaben und In-Process-Hosting mit IIS.

HTTP.sys: Opt-In-Unterstützung für Kernelmodus-Antwortpufferung

In einigen Szenarien können hohe Mengen kleiner Schreibvorgänge mit hoher Latenz zu erheblichen Leistungseinbußen für HTTP.sys führen. Diese Auswirkung ist auf das Fehlen eines Pipe-Puffers in der HTTP.sys-Implementierung zurückzuführen. Um die Leistung in diesen Szenarien zu verbessern, wurde die Unterstützung für Antwortpuffer in HTTP.sys hinzugefügt. Aktivieren Sie die Pufferung, indem Sie HttpSysOptions.EnableKernelResponseBuffering auf true festlegen.

Die Antwortpufferung sollte von einer App aktiviert werden, die synchrone E/A- oder asynchrone E/A-Vorgänge mit jeweils nicht mehr als einem ausstehenden Schreibvorgang ausführt. In diesen Szenarien kann die Antwortpufferung den Durchsatz gegenüber Verbindungen mit hoher Latenz erheblich verbessern.

Apps, die asynchrone E/A-Vorgänge verwenden und bei denen möglicherweise mehrere Schreibvorgänge gleichzeitig ausstehen, sollten dieses Flag nicht verwenden. Das Aktivieren dieses Flags kann zu einer höheren CPU- und Arbeitsspeicherauslastung durch HTTP.Sys führen.

Authentifizierung und Autorisierung

ASP.NET Core 8 fügt der Authentifizierung und Autorisierung neue Features hinzu.

Identity-API-Endpunkte

MapIdentityApi<TUser> ist eine neue Erweiterungsmethode, die zwei API-Endpunkte (/register und /login) hinzufügt. Das Hauptziel von MapIdentityApi besteht darin, Entwicklern die Verwendung von ASP.NET Core Identity für die Authentifizierung in JavaScript-basierten Single-Page-Apps (SPA) oder Blazor-Apps zu erleichtern. Anstatt die Standardbenutzeroberfläche zu verwenden, die von ASP.NET Core Identity bereitgestellt wird, die auf Razor Pages, MapIdentity basiert, fügt API JSON API-Endpunkte hinzu, die für SPA-Apps und Nicht-Browser-Apps besser geeignet sind. Weitere Informationen finden Sie unter Identity-API-Endpunkte.

IAuthorizationRequirementData

Vor ASP.NET Core 8 musste zum Hinzufügen einer parametrisierten Autorisierungsrichtlinie zu einem Endpunkt Folgendes implementiert werden:

  • AuthorizeAttribute für jede Richtlinie.
  • AuthorizationPolicyProvider zum Verarbeiten einer benutzerdefinierten Richtlinie aus einem zeichenfolgenbasierten Vertrag.
  • AuthorizationRequirement für die Richtlinie.
  • AuthorizationHandler für jede Anforderung.

Sehen Sie sich beispielsweise das folgende Beispiel an, das für ASP.NET Core 7.0 geschrieben wurde:

using AuthRequirementsData.Authorization;
using Microsoft.AspNetCore.Authorization;

var builder = WebApplication.CreateBuilder();

builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddAuthorization();
builder.Services.AddControllers();
builder.Services.AddSingleton<IAuthorizationPolicyProvider, MinimumAgePolicyProvider>();
builder.Services.AddSingleton<IAuthorizationHandler, MinimumAgeAuthorizationHandler>();

var app = builder.Build();

app.MapControllers();

app.Run();
using Microsoft.AspNetCore.Mvc;

namespace AuthRequirementsData.Controllers;

[ApiController]
[Route("api/[controller]")]
public class GreetingsController : Controller
{
    [MinimumAgeAuthorize(16)]
    [HttpGet("hello")]
    public string Hello() => $"Hello {(HttpContext.User.Identity?.Name ?? "world")}!";
}
using Microsoft.AspNetCore.Authorization;
using System.Globalization;
using System.Security.Claims;

namespace AuthRequirementsData.Authorization;

class MinimumAgeAuthorizationHandler : AuthorizationHandler<MinimumAgeRequirement>
{
    private readonly ILogger<MinimumAgeAuthorizationHandler> _logger;

    public MinimumAgeAuthorizationHandler(ILogger<MinimumAgeAuthorizationHandler> logger)
    {
        _logger = logger;
    }

    // Check whether a given MinimumAgeRequirement is satisfied or not for a particular
    // context.
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                               MinimumAgeRequirement requirement)
    {
        // Log as a warning so that it's very clear in sample output which authorization
        // policies(and requirements/handlers) are in use.
        _logger.LogWarning("Evaluating authorization requirement for age >= {age}",
                                                                    requirement.Age);

        // Check the user's age
        var dateOfBirthClaim = context.User.FindFirst(c => c.Type ==
                                                                 ClaimTypes.DateOfBirth);
        if (dateOfBirthClaim != null)
        {
            // If the user has a date of birth claim, check their age
            var dateOfBirth = Convert.ToDateTime(dateOfBirthClaim.Value, CultureInfo.InvariantCulture);
            var age = DateTime.Now.Year - dateOfBirth.Year;
            if (dateOfBirth > DateTime.Now.AddYears(-age))
            {
                // Adjust age if the user hasn't had a birthday yet this year.
                age--;
            }

            // If the user meets the age criterion, mark the authorization requirement
            // succeeded.
            if (age >= requirement.Age)
            {
                _logger.LogInformation("Minimum age authorization requirement {age} satisfied",
                                         requirement.Age);
                context.Succeed(requirement);
            }
            else
            {
                _logger.LogInformation("Current user's DateOfBirth claim ({dateOfBirth})" +
                    " does not satisfy the minimum age authorization requirement {age}",
                    dateOfBirthClaim.Value,
                    requirement.Age);
            }
        }
        else
        {
            _logger.LogInformation("No DateOfBirth claim present");
        }

        return Task.CompletedTask;
    }
}

Das vollständige Beispiel finden Sie hier im AspNetCore.Docs.Samples-Repository.

In ASP.NET Core 8 wird die IAuthorizationRequirementData-Schnittstelle eingeführt. Über die IAuthorizationRequirementData-Schnittstelle können mit der Attributdefinition die Anforderungen angegeben werden, die der Autorisierungsrichtlinie zugeordnet sind. Mit IAuthorizationRequirementData kann der vorangehende benutzerdefinierte Autorisierungsrichtliniencode mit weniger Codezeilen geschrieben werden. Die aktualisierte Program.cs-Datei:

  using AuthRequirementsData.Authorization;
  using Microsoft.AspNetCore.Authorization;
  
  var builder = WebApplication.CreateBuilder();
  
  builder.Services.AddAuthentication().AddJwtBearer();
  builder.Services.AddAuthorization();
  builder.Services.AddControllers();
- builder.Services.AddSingleton<IAuthorizationPolicyProvider, MinimumAgePolicyProvider>();
  builder.Services.AddSingleton<IAuthorizationHandler, MinimumAgeAuthorizationHandler>();
  
  var app = builder.Build();
  
  app.MapControllers();
  
  app.Run();

Der aktualisierte MinimumAgeAuthorizationHandler:

using Microsoft.AspNetCore.Authorization;
using System.Globalization;
using System.Security.Claims;

namespace AuthRequirementsData.Authorization;

- class MinimumAgeAuthorizationHandler : AuthorizationHandler<MinimumAgeRequirement>
+ class MinimumAgeAuthorizationHandler : AuthorizationHandler<MinimumAgeAuthorizeAttribute>
{
    private readonly ILogger<MinimumAgeAuthorizationHandler> _logger;

    public MinimumAgeAuthorizationHandler(ILogger<MinimumAgeAuthorizationHandler> logger)
    {
        _logger = logger;
    }

    // Check whether a given MinimumAgeRequirement is satisfied or not for a particular
    // context
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
-                                              MinimumAgeRequirement requirement)
+                                              MinimumAgeAuthorizeAttribute requirement)
    {
        // Remaining code omitted for brevity.

Das vollständige aktualisierte Beispiel finden Sie hier.

Eine ausführliche Untersuchung des neuen Beispiels finden Sie unter Benutzerdefinierte Autorisierungsrichtlinien mit IAuthorizationRequirementData.

Schützen von Endpunkten der Swagger-Benutzeroberfläche

Endpunkte der Swagger-Benutzeroberfläche können jetzt in Produktionsumgebungen durch Aufrufen von MapSwagger().RequireAuthorization gesichert werden. Weitere Informationen finden Sie unter Sichern von Endpunkten der Swagger-Benutzeroberfläche.

Sonstiges

In den folgenden Abschnitten werden verschiedene neue Features in ASP.NET Core 8 beschrieben.

Unterstützung von Schlüsseldiensten in Abhängigkeitsinjektion

Schlüsseldienste bezieht sich auf einen Mechanismus für die Registrierung und den Abruf von Dependency Injection (DI) Services unter Verwendung von Schlüsseln. Ein Dienst wird mit einem Schlüssel verknüpft, indem Sie AddKeyedSingleton (oder AddKeyedScoped oder AddKeyedTransient) aufrufen, um ihn zu registrieren. Greifen Sie auf einen registrierten Dienst zu, indem Sie den Schlüssel mit dem [FromKeyedServices] Attribut angeben. Der folgende Code zeigt, wie Sie Schlüsseldienste verwenden können:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;

var builder = WebApplication.CreateBuilder(args);

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

var app = builder.Build();

app.MapGet("/big", ([FromKeyedServices("big")] ICache bigCache) => bigCache.Get("date"));
app.MapGet("/small", ([FromKeyedServices("small")] ICache smallCache) =>
                                                               smallCache.Get("date"));

app.MapControllers();

app.Run();

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

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

[ApiController]
[Route("/cache")]
public class CustomServicesApiController : Controller
{
    [HttpGet("big-cache")]
    public ActionResult<object> GetOk([FromKeyedServices("big")] ICache cache)
    {
        return cache.Get("data-mvc");
    }
}

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

Visual Studio-Projektvorlagen für SPA-Apps mit ASP.NET Core-Back-End

Visual Studio-Projektvorlagen sind jetzt die empfohlene Methode zum Erstellen von Single-Page-Apps (SPAs), die über ein ASP.NET-Core-Back-End verfügen. Es sind Vorlagen vorhanden, die Apps basierend auf den JavaScript-Frameworks Angular, React und Vue erstellen. Diese Vorlagen:

  • Erstellen eine Visual Studio-Projektmappe mit einem Front-End-Projekt und einem Back-End-Projekt.
  • Verwenden den Visual Studio-Projekttyp für JavaScript und TypeScript (.esproj) für das Front-End.
  • Verwenden ein ASP.NET Core-Projekt für das Back-End.

Weitere Informationen zu den Visual Studio-Vorlagen und zum Zugriff auf die Legacyvorlagen finden Sie unter Übersicht über Single-Page-Apps (SPAs) in ASP.NET Core.

Unterstützung für generische Attribute

Attribute, die bisher einen Type-Parameter erforderten, sind jetzt in bereinigten generischen Varianten verfügbar. Dies wird durch die Unterstützung generischer Attribute in C# 11 ermöglicht. Beispielsweise kann die Syntax zum Kommentieren des Antworttyps einer Aktion wie folgt geändert werden:

[ApiController]
[Route("api/[controller]")]
public class TodosController : Controller
{
  [HttpGet("/")]
- [ProducesResponseType(typeof(Todo), StatusCodes.Status200OK)]
+ [ProducesResponseType<Todo>(StatusCodes.Status200OK)]
  public Todo Get() => new Todo(1, "Write a sample", DateTime.Now, false);
}

Generische Varianten werden für die folgenden Attribute unterstützt:

  • [ProducesResponseType<T>]
  • [Produces<T>]
  • [MiddlewareFilter<T>]
  • [ModelBinder<T>]
  • [ModelMetadataType<T>]
  • [ServiceFilter<T>]
  • [TypeFilter<T>]

Code analysis in ASP.NET Core apps (Codeanalyse in ASP.NET Core-Apps)

Die in der folgenden Tabelle gezeigten neuen Analysetools sind in ASP.NET Core 8.0 verfügbar.

Diagnose-ID Betroffen/Nicht betroffen Beschreibung
ASP0016 Nicht betroffen Keine Rückgabe eines Werts von RequestDelegate
ASP0019 Nicht betroffen Empfehlung zur Verwendung von „IHeaderDictionary.Append“ oder dem Indexer
ASP0020 Nicht betroffen Komplexe Typen, auf die von Routenparametern verwiesen wird, müssen analysierbar sein.
ASP0021 Nicht betroffen Der Rückgabetyp der BindAsync-Methode muss ValueTask<T> sein.
ASP0022 Nicht betroffen Zwischen Routenhandlern wurde ein Routenkonflikt erkannt.
ASP0023 Nicht betroffen Model View Controller (MVC): Zwischen Routenhandlern wurde ein Routenkonflikt erkannt.
ASP0024 Nicht betroffen Der Routenhandler verfügt über mehrere Parameter mit dem [FromBody]-Attribut.
ASP0025 Nicht betroffen Verwenden von AddAuthorizationBuilder

Routingtools

ASP.NET Core basiert auf dem Routing. Minimal-APIs, Web-APIs, Razor Pages und Blazor verwenden Routen, um die Zuordnung von HTTP-Anforderungen zum Code anzupassen.

In .NET 8 haben wir in eine Reihe neuer Features investiert, damit Routenplanung einfacher erlernt und genutzt werden kann. Zu diesen neuen Features gehören folgende:

Weitere Informationen finden Sie unter Routingtools in .NET 8.

ASP.NET Core-Metriken

Metriken sind im Laufe der Zeit gemeldete Messwerte. Sie werden am häufigsten verwendet, um die Integrität einer App zu überwachen und Warnungen zu generieren. Beispielsweise kann ein Leistungsindikator, der fehlerhafte HTTP-Anforderungen meldet, in Dashboards angezeigt werden oder Warnungen generieren, wenn Fehler einen Schwellenwert überschreiten.

Diese Vorschau fügt neue Metriken in ASP.NET Core unter Verwendung von System.Diagnostics.Metrics hinzu. Metrics ist eine moderne API zum Melden und Erfassen von Informationen zu Apps.

Metriken bieten eine Reihe von Verbesserungen im Vergleich zu vorhandenen Ereignisindikatoren:

  • Neue Arten von Messungen mit Zählern, Messgeräten und Histogrammen.
  • Leistungsstarke Berichterstellung mit mehrdimensionalen Werten.
  • Integration in das breitere cloudnative Ökosystem durch Angleichung an OpenTelemetry-Standards.

Metriken wurden für ASP.NET Core-Hosting, Kestrel und SignalR hinzugefügt. Weitere Informationen finden Sie unter System.Diagnostics.Metrics.

IExceptionHandler

IExceptionHandler ist eine Schnittstelle, die dem Entwickler die Möglichkeit zum Rückruf und Behandeln bekannter Ausnahmen an einem zentralen Ort bietet.

IExceptionHandler-Implementierungen werden durch Aufrufen von IServiceCollection.AddExceptionHandler<T> registriert. Es können mehrere Implementierungen hinzugefügt werden, die in der registrierten Reihenfolge aufgerufen werden. Wenn ein Ausnahmehandler eine Anforderung verarbeitet, kann er true zurückgeben, um die Verarbeitung zu beenden. Wenn eine Ausnahme von keinem Ausnahmehandler behandelt wird, greift das Steuerelement auf das Standardverhalten und die Standardoptionen der Middleware zurück.

Weitere Informationen finden Sie unter IExceptionHandler.

Verbesserte Debugfunktionen

Attribute zur Anpassung des Debuggens wurden Typen wie HttpContext, HttpRequest, HttpResponse, ClaimsPrincipal und WebApplication hinzugefügt. Die erweiterten Debuggeranzeigen für diese Typen erleichtern das Auffinden wichtiger Informationen im Debugger einer IDE. Die folgenden Screenshots zeigen den Unterschied, den diese Attribute in der Anzeige von HttpContext des Debuggers machen.

.NET 7:

Wenig hilfreiche Debuggeranzeige des HttpContext-Typs in .NET 7.

.NET 8:

Hilfreiche Debuggeranzeige des HttpContext-Typs in .NET 8.

Die Debuggeranzeige für WebApplication hebt wichtige Informationen wie konfigurierte Endpunkte, Middleware und IConfiguration-Werte hervor.

.NET 7:

Wenig hilfreiche Debuggeranzeige des WebApplication-Typs in .NET 7.

.NET 8:

Hilfreiche Debuggeranzeige des WebApplication-Typs in .NET 8.

Weitere Informationen zu Verbesserungen beim Debuggen in .NET 8 finden Sie in:

IPNetwork.Parse und TryParse

Die neuen Parse- und TryParse-Methoden auf IPNetwork fügen Unterstützung für die Erstellung eines IPNetwork mithilfe einer Eingabezeichenfolge in der CIDR-Notation oder „Schrägstrichnotation“ hinzu.

Hier finden Sie IPv4-Beispiele:

// Using Parse
var network = IPNetwork.Parse("192.168.0.1/32");
// Using TryParse
bool success = IPNetwork.TryParse("192.168.0.1/32", out var network);
// Constructor equivalent
var network = new IPNetwork(IPAddress.Parse("192.168.0.1"), 32);

Und hier finden Sie Beispiele für IPv6:

// Using Parse
var network = IPNetwork.Parse("2001:db8:3c4d::1/128");
// Using TryParse
bool success = IPNetwork.TryParse("2001:db8:3c4d::1/128", out var network);
// Constructor equivalent
var network = new IPNetwork(IPAddress.Parse("2001:db8:3c4d::1"), 128);

Redis-basierte Ausgabezwischenspeicherung

In ASP.NET Core 8 wurde Unterstützung für die Verwendung von Redis als verteiltem Cache für die Ausgabezwischenspeicherung hinzugefügt. Die Ausgabezwischenspeicherung ist ein Feature, mit dem eine App die Ausgabe eines minimalen API-Endpunkts, einer Controlleraktion oder einer Razor Page zwischenspeichern kann. Weitere Informationen finden Sie unter Ausgabezwischenspeicherung.

Kurzschluss der Middleware nach dem Routing

Wenn das Routing mit einem Endpunkt übereinstimmt, lässt es in der Regel den Rest der Middlewarepipeline ausführen, bevor die Endpunktlogik aufgerufen wird. Dienste können die Ressourcennutzung reduzieren, indem sie bekannte Anforderungen frühzeitig in der Pipeline herausfiltern. Verwenden Sie die ShortCircuit-Erweiterungsmethode, um das Routing zu veranlassen, die Endpunktlogik sofort aufzurufen und dann die Anforderung zu beenden. Beispielsweise muss eine bestimmte Route möglicherweise keine Authentifizierung oder CORS-Middleware durchlaufen. Im folgenden Beispiel werden Kurzschlüsse angefordert, die mit der /short-circuit-Route übereinstimmen:

app.MapGet("/short-circuit", () => "Short circuiting!").ShortCircuit();

Verwenden Sie die MapShortCircuit-Methode, um Kurzschlüsse für mehrere Routen gleichzeitig einzurichten, indem Sie ihr ein Parameterarray von URL-Präfixen übergeben. Beispielsweise testen Browser und Bots häufig Server auf bekannte Pfade wie robots.txt und favicon.ico. Wenn die App nicht über diese Dateien verfügt, kann eine Codezeile beide Routen konfigurieren:

app.MapShortCircuit(404, "robots.txt", "favicon.ico");

Weitere Informationen finden Sie unter Kurzschluss der Middleware nach dem Routing.

ERWEITERBARKEIT von HTTP-Protokollierungs-Middleware

Die MIDDLEWARE für die HTTP-Protokollierung verfügt über mehrere neue Funktionen:

  • HttpLoggingFields.Duration: Wenn diese Option aktiviert ist, gibt die Middleware am Ende der Anforderung ein neues Protokoll und eine Antwort aus, das die Gesamtzeit für die Verarbeitung misst. Dieses neue Feld wurde dem HttpLoggingFields.All-Satz hinzugefügt.
  • HttpLoggingOptions.CombineLogs: Wenn diese Option aktiviert ist, konsolidiert die Middleware alle aktivierten Protokolle für eine Anforderung und Antwort in einem Protokoll am Ende. Eine einzelne Protokollmeldung enthält die Anfrage, den Anfragetext, die Antwort, den Antworttext und die Dauer.
  • IHttpLoggingInterceptor: Eine neue Schnittstelle für einen Dienst, der implementiert und registriert werden kann (mithilfe vonAddHttpLoggingInterceptor), um Rückrufe pro Anfrage und pro Antwort zu erhalten, mit denen Sie anpassen können, welche Details protokolliert werden. Alle endpunktspezifischen Protokolleinstellungen werden zuerst angewendet und können dann in diesen Rückrufen überschrieben werden. Eine Implementierung kann:
    • Überprüfen Sie eine Anforderung und Antwort.
    • alle HttpLoggingFields aktivieren oder deaktivieren
    • anpassen, welcher Anteil des Anforderungs- oder Antworttexts protokolliert wird
    • benutzerdefinierte Felder zu Protokollen hinzufügen

Weitere Informationen finden Sie unter HTTP-Protokollierung in .NET Core und ASP.NET Core.

Neue APIs in ProblemDetails zur Unterstützung stabilerer Integrationen

In .NET 7 wurde der ProblemDetails-Dienst eingeführt, um das Benutzererlebnis beim Generieren von Fehlerantworten zu verbessern, die der ProblemDetails-Spezifikation entsprechen. In .NET 8 wurde eine neue API hinzugefügt, um das Implementieren von Fallbackverhalten zu vereinfachen, wenn IProblemDetailsService nicht in der Lage ist, ProblemDetails zu generieren. Das folgende Beispiel veranschaulicht die Verwendung der neuen TryWriteAsync-API:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddProblemDetails();

var app = builder.Build();

app.UseExceptionHandler(exceptionHandlerApp =>
{
    exceptionHandlerApp.Run(async httpContext =>
    {
        var pds = httpContext.RequestServices.GetService<IProblemDetailsService>();
        if (pds == null
            || !await pds.TryWriteAsync(new() { HttpContext = httpContext }))
        {
            // Fallback behavior
            await httpContext.Response.WriteAsync("Fallback: An error occurred.");
        }
    });
});

app.MapGet("/exception", () =>
{
    throw new InvalidOperationException("Sample Exception");
});

app.MapGet("/", () => "Test by calling /exception");

app.Run();

Weitere Informationen finden Sie unter IProblemDetailsService-Fallback.

Zusätzliche Ressourcen