Migrieren von ASP.NET Core 2.2 zu 3.0

Von Scott Addie und Rick Anderson

In diesem Artikel wird erläutert, wie Sie ein vorhandenes ASP.NET Core 2.2-Projekt auf ASP.NET Core 3.0 aktualisieren. Die Erstellung eines neuen ASP.NET Core 3.0-Projekts kann für Folgendes hilfreich sein:

  • Vergleich mit dem ASP.NET Core 2.2-Code
  • Kopieren relevanter Änderungen in Ihr ASP.NET Core 3.0-Projekt

Voraussetzungen

Aktualisieren der .NET Core SDK-Version in „global.json“

Wenn Ihre Lösung von einer Datei vom Typ global.json abhängig ist, um eine bestimmte .NET Core SDK-Version als Ziel zu verwenden, aktualisieren Sie ihre version-Eigenschaft auf die auf Ihrem Computer installierte Version 3.0:

{
  "sdk": {
    "version": "3.0.100"
  }
}

Aktualisieren der Projektdatei

Aktualisieren des Zielframeworks

ASP.NET Core 3.0 oder höher kann nur in .NET Core ausgeführt werden. Legen Sie den Zielframeworkmoniker (Target Framework Moniker, TFM) auf netcoreapp3.0 fest:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
  </PropertyGroup>

</Project>

Entfernen von Verweisen auf veraltete Pakete

Eine große Anzahl von NuGet-Paketen ist nicht für ASP.NET Core 3.0 konzipiert. Entsprechende Paketverweise müssen aus der Projektdatei entfernt werden. Sehen Sie sich die folgende Projektdatei für eine ASP.NET Core 2.2-Web-App an:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>
    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App"/>
    <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
  </ItemGroup>

</Project>

Aktualisierte Projektdatei für ASP.NET Core 3.0:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
  </PropertyGroup>

</Project>

Für die aktualisierte ASP.NET Core 3.0-Projektdatei gilt Folgendes:

  • In <PropertyGroup>:

    • Der Zielframeworkmoniker wird auf netcoreapp3.0 aktualisiert.
    • Das <AspNetCoreHostingModel>-Element wird entfernt. Weitere Informationen finden Sie unter In-Process-Hostingmodell in diesem Dokument.
  • In <ItemGroup>:

    • Microsoft.AspNetCore.App wurde entfernt. Weitere Informationen finden Sie unter Framework-Referenz in diesem Dokument.
    • Microsoft.AspNetCore.Razor.Design wird entfernt und befindet sich in der folgenden Liste der Pakete, die nicht mehr produziert werden.

Um die vollständige Liste der Pakete anzuzeigen, die nicht mehr produziert werden, können Sie die folgende Erweiterungsliste auswählen:

Klicken Sie hier, um die Liste der Pakete zu erweitern, die nicht mehr produziert werden.
  • Microsoft.AspNetCore
  • Microsoft.AspNetCore.All
  • Microsoft.AspNetCore.App
  • Microsoft.AspNetCore.Antiforgery
  • Microsoft.AspNetCore.Authentication
  • Microsoft.AspNetCore.Authentication.Abstractions
  • Microsoft.AspNetCore.Authentication.Cookies
  • Microsoft.AspNetCore.Authentication.Core
  • Microsoft.AspNetCore.Authentication.OAuth
  • Microsoft.AspNetCore.Authorization.Policy
  • Microsoft.AspNetCore.CookiePolicy
  • Microsoft.AspNetCore.Cors
  • Microsoft.AspNetCore.Diagnostics
  • Microsoft.AspNetCore.Diagnostics.HealthChecks
  • Microsoft.AspNetCore.HostFiltering
  • Microsoft.AspNetCore.Hosting
  • Microsoft.AspNetCore.Hosting.Abstractions
  • Microsoft.AspNetCore.Hosting.Server.Abstractions
  • Microsoft.AspNetCore.Http
  • Microsoft.AspNetCore.Http.Abstractions
  • Microsoft.AspNetCore.Http.Connections
  • Microsoft.AspNetCore.Http.Extensions
  • Microsoft.AspNetCore.HttpOverrides
  • Microsoft.AspNetCore.HttpsPolicy
  • Microsoft.AspNetCore.Identity
  • Microsoft.AspNetCore.Localization
  • Microsoft.AspNetCore.Localization.Routing
  • Microsoft.AspNetCore.Mvc
  • Microsoft.AspNetCore.Mvc.Abstractions
  • Microsoft.AspNetCore.Mvc.Analyzers
  • Microsoft.AspNetCore.Mvc.ApiExplorer
  • Microsoft.AspNetCore.Mvc.Api.Analyzers
  • Microsoft.AspNetCore.Mvc.Core
  • Microsoft.AspNetCore.Mvc.Cors
  • Microsoft.AspNetCore.Mvc.DataAnnotations
  • Microsoft.AspNetCore.Mvc.Formatters.Json
  • Microsoft.AspNetCore.Mvc.Formatters.Xml
  • Microsoft.AspNetCore.Mvc.Localization
  • Microsoft.AspNetCore.Mvc.Razor
  • Microsoft.AspNetCore.Mvc.Razor.ViewCompilation
  • Microsoft.AspNetCore.Mvc.RazorPages
  • Microsoft.AspNetCore.Mvc.TagHelpers
  • Microsoft.AspNetCore.Mvc.ViewFeatures
  • Microsoft.AspNetCore.Razor
  • Microsoft.AspNetCore.Razor.Runtime
  • Microsoft.AspNetCore.Razor.Design
  • Microsoft.AspNetCore.ResponseCaching
  • Microsoft.AspNetCore.ResponseCaching.Abstractions
  • Microsoft.AspNetCore.ResponseCompression
  • Microsoft.AspNetCore.Rewrite
  • Microsoft.AspNetCore.Routing
  • Microsoft.AspNetCore.Routing.Abstractions
  • Microsoft.AspNetCore.Server.HttpSys
  • Microsoft.AspNetCore.Server.IIS
  • Microsoft.AspNetCore.Server.IISIntegration
  • Microsoft.AspNetCore.Server.Kestrel
  • Microsoft.AspNetCore.Server.Kestrel.Core
  • Microsoft.AspNetCore.Server.Kestrel.Https
  • Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions
  • Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
  • Microsoft.AspNetCore.Session
  • Microsoft.AspNetCore.SignalR
  • Microsoft.AspNetCore.SignalR.Core
  • Microsoft.AspNetCore.StaticFiles
  • Microsoft.AspNetCore.WebSockets
  • Microsoft.AspNetCore.WebUtilities
  • Microsoft.Net.Http.Headers

Überprüfen von Breaking Changes

Überprüfen von Breaking Changes

Framework-Referenz

Features von ASP.NET Core, die über eines der oben aufgeführten Pakete verfügbar waren, sind als Teil des freigegebenen Frameworks Microsoft.AspNetCore.App verfügbar. Das freigegebene Framework ist der Satz von Assemblys (DLL-Dateien), die auf dem Computer installiert werden und eine Laufzeitkomponente sowie ein Zielpaket enthalten. Weitere Informationen finden Sie unter The shared framework (Das freigegebene Framework).

  • Projekte, die auf das Microsoft.NET.Sdk.Web SDK abzielen, verweisen implizit auf das Microsoft.AspNetCore.App-Framework.

    Für diese Projekte sind keine weiteren Verweise erforderlich:

    <Project Sdk="Microsoft.NET.Sdk.Web">
      <PropertyGroup>
        <TargetFramework>netcoreapp3.0</TargetFramework>
      </PropertyGroup>
        ...
    </Project>
    
  • Bei Projekten, die auf das Microsoft.NET.Sdk oder Microsoft.NET.Sdk.Razor SDK ausgerichtet sind, muss ein explizites FrameworkReference-Element zu Microsoft.AspNetCore.App hinzugefügt werden:

    <Project Sdk="Microsoft.NET.Sdk.Razor">
      <PropertyGroup>
        <TargetFramework>netcoreapp3.0</TargetFramework>
      </PropertyGroup>
    
      <ItemGroup>
        <FrameworkReference Include="Microsoft.AspNetCore.App" />
      </ItemGroup>
        ...
    </Project>
    

Frameworkabhängige Builds mit Docker

Frameworkabhängige Builds von Konsolen-Apps, die ein Paket verwenden, das vom freigegebenen ASP.NET Core-Framework abhängt, können den folgenden Laufzeitfehler verursachen:

It was not possible to find any compatible framework version
The specified framework 'Microsoft.AspNetCore.App', version '3.0.0' was not found.
  - No frameworks were found.

Microsoft.AspNetCore.App ist das freigegebene Framework, das die ASP.NET Core-Runtime enthält, und nur im Docker-Image „dotnet/core/aspnet“ vorhanden. Das 3.0 SDK reduziert die Größe frameworkabhängiger Builds mithilfe von ASP.NET Core, indem doppelte Kopien von Bibliotheken, die im freigegebenen Framework verfügbar sind, nicht eingeschlossen werden. Dies ist eine potenzielle Einsparung von bis zu 18 MB. Es erfordert aber, dass die ASP.NET Core Runtime vorhanden bzw. installiert ist, um die App auszuführen.

Um festzustellen, ob die App eine (direkte oder indirekte) Abhängigkeit vom freigegebenen ASP.NET Core-Framework aufweist, überprüfen Sie die Datei runtimeconfig.json, die während eines Build-/Veröffentlichungsvorgangs Ihrer App generiert wurde. Die folgende JSON-Datei enthält eine Abhängigkeit vom freigegebenen ASP.NET Core-Framework:

{
  "runtimeOptions": {
    "tfm": "netcoreapp3.0",
    "framework": {
      "name": "Microsoft.AspNetCore.App",
      "version": "3.0.0"
    },
    "configProperties": {
      "System.GC.Server": true
    }
  }
}

Wenn Ihre App Docker verwendet, verwenden Sie ein Basisimage, das ASP.NET Core 3.0 enthält. Beispiel: docker pull mcr.microsoft.com/dotnet/core/aspnet:3.0.

Hinzufügen von Paketverweisen für entfernte Assemblys

ASP.NET Core 3.0 entfernt einige Assemblys, die zuvor Teil des Microsoft.AspNetCore.App-Paketverweises waren. Vergleichen Sie die beiden Ordner des freigegebenen Frameworks, um zu sehen, welche Assemblys entfernt wurden. Hier sehen Sie beispielsweise einen Vergleich der Versionen 2.2.7 und 3.0.0:

shared framework assemblies comparison

Verweisen Sie auf die 3.0-Versionen der entsprechenden Pakete, um weiterhin Features zu verwenden, die von den entfernten Assemblys bereitgestellt werden:

Startänderungen

Die folgende Abbildung zeigt die gelöschten und geänderten Zeilen in einer Razor Pages-Web-App für ASP.NET Core 2.2:

the deleted and changed lines in an ASP.NET Core 2.2 Razor Web app

In der obigen Abbildung ist gelöschter Code rot dargestellt. Der gelöschte Code zeigt keinen cookie-Optionscode. Dieser wurde gelöscht, bevor die Dateien verglichen wurden.

Die folgende Abbildung zeigt die hinzugefügten und geänderten Zeilen in einer Razor Pages-Web-App für ASP.NET Core 3.0:

the added and changed lines in an ASP.NET Core 3.0 Razor Web app

In der obigen Abbildung ist hinzugefügter Code grün dargestellt. Weitere Informationen zu den folgenden Änderungen:

  • services.AddMvc in services.AddRazorPages: Weitere Informationen finden Sie unter MVC-Dienstregistrierung in diesem Dokument.
  • CompatibilityVersion: Weitere Informationen finden Sie unter Kompatibilitätsversion für ASP.NET Core MVC.
  • IHostingEnvironment in IWebHostEnvironment: Weitere Informationen finden Sie in dieser GitHub-Ankündigung.
  • app.UseAuthorization wurde den Vorlagen hinzugefügt, um die Reihenfolge anzuzeigen, in der Autorisierungsmiddleware hinzugefügt werden muss. Wenn die App keine Autorisierung verwendet, können Sie den Aufruf von app.UseAuthorization problemlos entfernen.
  • app.UseEndpoints: Weitere Informationen finden Sie unter Razor Pages oder unter Migrate Startup.Configure in diesem Dokument.

Unterstützung des Analysetools

Projekte, die implizit auf Microsoft.NET.Sdk.Web ausgerichtet sind, verweisen implizit auf Analysetools, die zuvor als Teil des Pakets Microsoft.AspNetCore.Mvc.Analyzers bereitgestellt wurden. Es sind keine zusätzlichen Verweise erforderlich, um sie zu aktivieren.

Wenn Ihre App API-Analysetools verwendet, die zuvor mit dem Paket Microsoft.AspNetCore.Mvc.Api.Analyzers bereitgestellt wurden, bearbeiten Sie Ihre Projektdatei, um auf die Analysetools zu verweisen, die im .NET Core Web SDK enthalten sind:

<Project Sdk="Microsoft.NET.Sdk.Web">
    <PropertyGroup>
        <TargetFramework>netcoreapp3.0</TargetFramework>
        <IncludeOpenAPIAnalyzers>true</IncludeOpenAPIAnalyzers>
    </PropertyGroup>

    ...
</Project>

Razor-Klassenbibliothek

Bei Razor-Klassenbibliotheksprojekten, die Benutzeroberflächenkomponenten für MVC bereitstellen, muss die AddRazorSupportForMvc-Eigenschaft in der Projektdatei festgelegt werden:

<PropertyGroup>
  <AddRazorSupportForMvc>true</AddRazorSupportForMvc>
</PropertyGroup>

In-Process-Hostingmodell

Projekte werden ab ASP.NET Core 3.0 standardmäßig im In-Process-Hostingmodell ausgeführt. Sie können in der Projektdatei optional die <AspNetCoreHostingModel>-Eigenschaft entfernen, wenn sie den Wert InProcess hat.

Kestrel

Konfiguration

Migrieren Sie die Kestrel-Konfiguration zum Webhost-Generator, der von ConfigureWebHostDefaults (Program.cs) bereitgestellt wird:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.ConfigureKestrel(serverOptions =>
            {
                // Set properties and call methods on options
            })
            .UseStartup<Startup>();
        });

Wenn die App den Host manuell mit ConfigureWebHost anstelle von ConfigureWebHostDefaultserstellt, rufen Sie UseKestrel im Webhost-Generator auf:

public static void Main(string[] args)
{
    var host = new HostBuilder()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .ConfigureWebHost(webBuilder =>
        {
            webBuilder.UseKestrel(serverOptions =>
            {
                // Set properties and call methods on options
            })
            .UseIISIntegration()
            .UseStartup<Startup>();
        })
        .Build();

    host.Run();
}

Verbindungsmiddleware ersetzt Verbindungsadapter.

Verbindungsadapter (Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal.IConnectionAdapter) wurden aus Kestrel entfernt. Ersetzen Sie Verbindungsadapter durch Verbindungsmiddleware. Verbindungsmiddleware ähnelt der HTTP-Middleware in der ASP.NET Core-Pipeline, ist aber für Verbindungen auf niedrigerer Ebene konzipiert. HTTPS- und Verbindungsprotokollierung:

  • Wurden von Verbindungsadaptern zu Verbindungsmiddleware migriert.
  • Diese Erweiterungsmethoden funktionieren wie in früheren Versionen von ASP.NET Core.

Weitere Informationen finden Sie im TlsFilterConnectionHandler-Beispiel im Abschnitt „ListenOptions.Protocols“ des Kestrel-Artikels.

Datentransportabstraktionen wurden verschoben und öffentlich gemacht.

Die Kestrel-Transportschicht wurde in Connections.Abstractions als öffentliche Schnittstelle verfügbar gemacht. Im Zuge dieser Updates wurde Folgendes geändert:

  • Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions und zugeordnete Typen wurden entfernt.
  • NoDelay wurde von ListenOptions in die Datentransportoptionen verschoben.
  • Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal.SchedulingMode wurde aus KestrelServerOptions entfernt.

Weitere Informationen finden Sie in den folgenden GitHub-Ressourcen:

Kestrel-Anforderungstrailer-Header

Für Apps, die auf frühere Versionen von ASP.NET Core ausgerichtet sind, gilt Folgendes:

  • Kestrel fügt der Anforderungsheadersammlung aufgeteilte HTTP/1.1-Trailer-Header hinzu.
  • Trailer sind verfügbar, nachdem der Anforderungstext bis zum Ende gelesen wurde.

Aufgrund von Bedenken hinsichtlich Unklarheiten zwischen Headern und Trailern wurden Trailer in 3.0 in eine neue Sammlung (RequestTrailerExtensions) verschoben.

HTTP/2-Anforderungstrailer sind:

  • in ASP.NET Core 2.2 nicht verfügbar.
  • in 3.0 als RequestTrailerExtensions verfügbar.

Für den Zugriff auf diese Trailer sind neue Anforderungserweiterungsmethoden vorhanden. Genau wie bei HTTP/1.1 sind Trailer verfügbar, nachdem der Anforderungstext bis zum Ende gelesen wurde.

Für das Release 3.0 sind folgende RequestTrailerExtensions-Methoden verfügbar:

  • GetDeclaredTrailers: Ruft den Anforderungsheader „Trailer“ ab, in dem aufgelistet wird, welche Trailer nach dem Text erwartet werden.
  • SupportsTrailers: Gibt an, ob die Anforderung den Empfang von Trailer-Headern unterstützt.
  • CheckTrailersAvailable: Überprüft, ob die Anforderung Trailer unterstützt und ob diese zum Lesen verfügbar sind. Bei dieser Überprüfung wird nicht davon ausgegangen, dass Trailer zum Lesen vorhanden sind. Es sind möglicherweise keine Trailer zum Lesen vorhanden, auch wenn von dieser Methode true zurückgegeben wird.
  • GetTrailer: Ruft den angeforderten Trailer-Header aus der Antwort ab. Überprüfen Sie SupportsTrailers, bevor Sie GetTrailer aufrufen. Andernfalls tritt möglicherweise eine Ausnahme vom Typ NotSupportedException auf, wenn die Anforderung keine Trailer-Header unterstützt.

Weitere Informationen finden Sie unter Put request trailers in a separate collection (dotnet/AspNetCore #10410).

AllowSynchronousIO deaktiviert

AllowSynchronousIO aktiviert oder deaktiviert synchrone E/A-APIs wie HttpRequest.Body.Read, HttpResponse.Body.Write und Stream.Flush. Diese APIs sind eine Quelle für einen Ressourcenmangel im Thread, der zu App-Abstürzen führt. In 3.0 ist AllowSynchronousIO standardmäßig deaktiviert. Weitere Informationen finden Sie im Abschnitt zu synchroner E/A im Kestrel-Artikel.

Synchrone E/A kann bei Bedarf durch Konfigurieren der AllowSynchronousIO-Option auf dem verwendeten Server konfiguriert werden (beim Aufrufen von ConfigureKestrel – z. B. bei Verwendung von Kestrel). Beachten Sie, dass Server (Kestrel, HttpSys, TestServer usw.) alle über eine eigene AllowSynchronousIO-Option verfügen, die sich nicht auf andere Server auswirkt. Synchrone E/A-Vorgänge können für alle Server auf Anforderungsbasis mit der Option IHttpBodyControlFeature.AllowSynchronousIO aktiviert werden:

var syncIOFeature = HttpContext.Features.Get<IHttpBodyControlFeature>();

if (syncIOFeature != null)
{
    syncIOFeature.AllowSynchronousIO = true;
}

Wenn Sie Probleme mit TextWriter-Implementierungen oder anderen Streams haben, die synchrone APIs in Dispose aufrufen, rufen Sie stattdessen die neue DisposeAsync-API auf.

Weitere Informationen finden Sie unter [Announcement] AllowSynchronousIO disabled in all servers (dotnet/AspNetCore #7644).

Pufferung des Ausgabeformatierers

Auf Newtonsoft.Json, XmlSerializer und DataContractSerializer basierende Ausgabeformatierer unterstützen nur synchrone Serialisierung. Damit diese Formatierer mit den AllowSynchronousIO-Einschränkungen des Servers funktionieren, puffert MVC die Ausgabe dieser Formatierer vor dem Schreiben auf den Datenträger. Aufgrund der Pufferung schließt MVC den Content-Length-Header bei Antworten mit diesen Formatierern ein.

System.Text.Json unterstützt asynchrone Serialisierung. Daher puffert der System.Text.Json-basierte Formatierer nicht. Erwägen Sie die Verwendung dieses Formatierers, um die Leistung zu verbessern.

Um die Pufferung zu deaktivieren, können Anwendungen SuppressOutputFormatterBuffering in der Startkonfiguration festlegen:

services.AddControllers(options => options.SuppressOutputFormatterBuffering = true)

Beachten Sie, dass dies zu einer Laufzeitausnahme führen kann, wenn nicht auch AllowSynchronousIO konfiguriert ist.

Assembly „Microsoft.AspNetCore.Server.Kestrel.Https“ entfernt

In ASP.NET Core 2.1 wurde der Inhalt von Microsoft.AspNetCore.Server.Kestrel.Https.dll in Microsoft.AspNetCore.Server.Kestrel.Core.dll verschoben. Dies war ein Nonbreaking Update mithilfe von TypeForwardedTo-Attributen. Für 3.0 wurden die leere Assembly Microsoft.AspNetCore.Server.Kestrel.Https.dll und das NuGet-Paket entfernt.

In Bibliotheken, die auf Microsoft.AspNetCore.Server.Kestrel.Https verweisen, müssen ASP.NET Core-Abhängigkeiten mindestens auf 2.1 aktualisiert werden.

In Apps und Bibliotheken, die auf ASP.NET Core 2.1 oder höher ausgerichtet sind, müssen alle direkten Verweise auf das Paket Microsoft.AspNetCore.Server.Kestrel.Https entfernt werden.

Unterstützung von Newtonsoft.Json (Json.NET)

Im Rahmen der Verbesserung des freigegebenen ASP.NET Core-Frameworks wurde Newtonsoft.Json (Json.NET) aus dem freigegebenen ASP.NET Core-Framework entfernt.

Das standardmäßige JSON-Serialisierungsmodul für ASP.NET Core ist jetzt System.Text.Json (neu in .NET Core 3.0). Verwenden Sie nach Möglichkeit System.Text.Json. Es ist äußerst leistungsfähig und erfordert keine zusätzliche Bibliotheksabhängigkeit. Da System.Text.Json jedoch neu ist, fehlen möglicherweise derzeit Features, die Ihre App benötigt. Weitere Informationen finden Sie unter Migrieren von Newtonsoft.Json zu System.Text.Json.

Verwenden von Newtonsoft.Json in einem SignalR-Projekt für ASP.NET Core 3.0

  • Installieren Sie das NuGet-Paket Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson.

  • Verketten Sie auf dem Client einen AddNewtonsoftJsonProtocol-Methodenaufruf mit der HubConnectionBuilder-Instanz:

    new HubConnectionBuilder()
        .WithUrl("/chathub")
        .AddNewtonsoftJsonProtocol(...)
        .Build();
    
  • Verketten Sie auf dem Server einen AddNewtonsoftJsonProtocol-Methodenaufruf mit dem AddSignalR-Methodenaufruf in Startup.ConfigureServices:

    services.AddSignalR()
        .AddNewtonsoftJsonProtocol(...);
    

Verwenden von Newtonsoft.Json in einem MVC-Projekt für ASP.NET Core 3.0

  • Installieren Sie das Microsoft.AspNetCore.Mvc.NewtonsoftJson-Paket.

  • Aktualisieren Sie Startup.ConfigureServices, um AddNewtonsoftJson aufzurufen.

    services.AddMvc()
        .AddNewtonsoftJson();
    

    AddNewtonsoftJson ist mit den folgenden neuen MVC-Dienstregistrierungsmethoden kompatibel:

    • AddRazorPages
    • AddControllersWithViews
    • AddControllers
    services.AddControllers()
        .AddNewtonsoftJson();
    

    Newtonsoft.Json-Einstellungen können im Aufruf von AddNewtonsoftJson festgelegt werden:

    services.AddMvc()
        .AddNewtonsoftJson(options =>
               options.SerializerSettings.ContractResolver =
                  new CamelCasePropertyNamesContractResolver());
    

    Hinweis: Falls die AddNewtonsoftJson-Methode nicht verfügbar ist, vergewissern Sie sich, dass Sie das Paket Microsoft.AspNetCore.Mvc.NewtonsoftJson installiert haben. Ein häufiger Fehler ist die Installation des Pakets Newtonsoft.Json anstelle des Pakets Microsoft.AspNetCore.Mvc.NewtonsoftJson.

Weitere Informationen finden Sie unter Hinzufügen von Newtonsoft.Json-basierter Unterstützung für das JSON-Format.

MVC-Dienstregistrierung

In ASP.NET Core 3.0 werden neue Optionen zum Registrieren von MVC-Szenarien in Startup.ConfigureServices hinzugefügt.

Drei neue Erweiterungsmethoden auf oberster Ebene im Zusammenhang mit MVC-Szenarien für IServiceCollection sind verfügbar. Vorlagen verwenden diese neuen Methoden anstelle von AddMvc. AddMvc verhält sich jedoch weiterhin wie in früheren Releases.

Im folgenden Beispiel wird Unterstützung von Controllern und API-bezogenen Features hinzugefügt, aber keine Unterstützung von Ansichten oder Seiten. Die API-Vorlage verwendet den folgenden Code:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
}

Im folgenden Beispiel wird Unterstützung von Controllern, API-bezogenen Features und Ansichten hinzugefügt, aber keine Unterstützung von Seiten. Die Vorlage „Webanwendung (MVC)“ verwendet den folgenden Code:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
}

Im folgenden Beispiel werden Unterstützung von Razor Pages sowie minimale Controllerunterstützung hinzugefügt. Die Vorlage „Webanwendung“ verwendet den folgenden Code:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
}

Die neuen Methoden können auch kombiniert werden. Das folgende Beispiel entspricht dem Aufruf von AddMvc in ASP.NET Core 2.2:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddRazorPages();
}

Routing von Startcode

Wenn eine App UseMvc oder UseSignalR aufruft, migrieren Sie die App nach Möglichkeit zu Endpunktrouting. Um die Endpunktrouting-Kompatibilität mit früheren Versionen von MVC zu verbessern, haben wir einige der in ASP.NET Core 2.2 eingeführten Änderungen bei der URL-Generierung rückgängig gemacht. Sollten bei der Verwendung von Endpunktrouting in Version 2.2 Probleme aufgetreten sein, können Sie in ASP.NET Core 3.0 Verbesserungen erwarten. Es gibt jedoch ein paar Ausnahmen:

  • Wenn die App IRouter implementiert oder von Route erbt, verwenden Sie DynamicRouteValuesTransformer als Ersatz.
  • Wenn die App direkt auf RouteData.Routers in MVC zugreift, um URLs zu analysieren, können Sie dies durch die Verwendung von LinkParser.ParsePathByEndpointName ersetzen.
    • Definieren Sie die Route mit einem Routennamen.
    • Verwenden Sie LinkParser.ParsePathByEndpointName, und übergeben Sie den gewünschten Routennamen.

Endpunktrouting unterstützt die gleiche Routenmustersyntax und die gleichen Features für die Routenmustererstellung wie IRouter. Endpunktrouting unterstützt IRouteConstraint. Endpunktrouting unterstützt [Route], [HttpGet] und die anderen MVC-Routingattribute.

Bei den meisten Anwendungen sind nur für Startup Änderungen erforderlich.

Migrieren von Startup.Configure

Allgemeine Tipps:

  • Fügen Sie UseRoutinghinzu.

  • Wenn die App UseStaticFiles aufruft, platzieren Sie UseStaticFilesvorUseRouting.

  • Wenn die App Authentifizierungs-/Autorisierungsfeatures wie AuthorizePage oder [Authorize] verwendet, platzieren Sie den Aufruf von UseAuthentication und UseAuthorizationnachUseRouting und UseCors, aber vor UseEndpoints:

    public void Configure(IApplicationBuilder app)
    {
      ...
    
      app.UseStaticFiles();
    
      app.UseRouting();
      app.UseCors();
    
      app.UseAuthentication();
      app.UseAuthorization();
    
      app.UseEndpoints(endpoints => {
         endpoints.MapControllers();
      });
    
  • Ersetzen Sie UseMvc oder UseSignalR durch UseEndpoints.

  • Wenn die App CORS-Szenarien verwendet (z. B. [EnableCors]), platzieren Sie den Aufruf von UseCors vor jeder anderen Middleware, die CORS verwendet. Platzieren Sie also beispielsweise UseCors vor UseAuthentication, UseAuthorization und UseEndpoints.

  • Ersetzen Sie IHostingEnvironment durch IWebHostEnvironment, und fügen Sie eine using-Anweisung für den Microsoft.AspNetCore.Hosting-Namespace hinzu.

  • Ersetzen Sie IApplicationLifetime durch IHostApplicationLifetime (Microsoft.Extensions.Hosting-Namespace).

  • Ersetzen Sie EnvironmentName durch Environments (Microsoft.Extensions.Hosting-Namespace).

Der folgende Code ist ein Beispiel für Startup.Configure in einer typischen ASP.NET Core 2.2-App:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseStaticFiles();

    app.UseAuthentication();

    app.UseSignalR(hubs =>
    {
        hubs.MapHub<ChatHub>("/chat");
    });

    app.UseMvc(routes =>
    {
        routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
    });
}

Nach der Aktualisierung des vorherigen Startup.Configure-Codes:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseStaticFiles();

    app.UseRouting();

    app.UseCors();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapHub<ChatHub>("/chat");
        endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
    });
}

Warnung

Für die meisten Apps müssen Aufrufe von UseAuthentication, UseAuthorization und UseCors zwischen den Aufrufen von UseRouting und UseEndpoints platziert werden, um wirksam zu sein.

Integritätsprüfungen

Integritätsprüfungen verwenden das Endpunktrouting mit dem generischen Host. Rufen Sie in Startup.Configure auf der Endpunkterstellung mit der Endpunkt-URL oder dem relativen Pfad MapHealthChecks auf:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health");
});

Für Endpunkte für Integritätsprüfungen gilt Folgendes:

  • Sie geben mindestens einen zugelassenen Host oder Port an.
  • Sie erfordern Autorisierung.
  • Sie erfordern CORS.

Weitere Informationen finden Sie unter Integritätsprüfungen in ASP.NET Core.

Leitfaden für Sicherheitsmiddleware

Die Unterstützung von Autorisierung und CORS ist auf Basis des Middlewareansatzes vereinheitlicht. Dies ermöglicht die Verwendung der gleichen Middleware und Funktionen in allen diesen Szenarien. In diesem Release wird eine aktualisierte Autorisierungsmiddleware bereitgestellt, und die CORS-Middleware wurde erweitert, um die von MVC-Controllern verwendeten Attribute verstehen zu können.

CORS

Früher war CORS nicht immer einfach zu konfigurieren. Zwar wurde Middleware für die Verwendung in einigen Anwendungsfällen bereitgestellt, in anderen Anwendungsfällen waren MVC-Filter aber für die Verwendung ohne Middleware vorgesehen. Bei Verwendung von ASP.NET Core 3.0 sollten alle Apps, die CORS erfordern, die CORS-Middleware zusammen mit Endpunktrouting verwenden. UseCors kann mit einer Standardrichtlinie bereitgestellt werden, und die Attribute [EnableCors] und [DisableCors] können verwendet werden, um die Standardrichtlinie bei Bedarf außer Kraft zu setzen.

Im folgenden Beispiel:

  • CORS ist für alle Endpunkte mit der Standardrichtlinie (default) aktiviert.
  • Die MyController-Klasse deaktiviert CORS mit dem [DisableCors]-Attribut.
public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseCors("default");

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
    });
}

[DisableCors]
public class MyController : ControllerBase
{
    ...
}

Autorisierung

In früheren Versionen von ASP.NET Core wurde die Autorisierungsunterstützung über das [Authorize]-Attribut bereitgestellt. Autorisierungsmiddleware war nicht verfügbar. In ASP.NET Core 3.0 ist Autorisierungsmiddleware erforderlich. Es wird empfohlen, die ASP.NET Core-Autorisierungsmiddleware (UseAuthorization) direkt nach zu UseAuthentication platzieren. Die Autorisierungsmiddleware kann auch mit einer Standardrichtlinie konfiguriert werden. Diese kann außer Kraft gesetzt werden.

Ab ASP.NET Core Version 3.0 wird UseAuthorization in Startup.Configure aufgerufen, und für den folgenden Home-Controller (HomeController) wird ein angemeldeter Benutzer bzw. eine angemeldete Benutzerin benötigt:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
    });
}

public class HomeController : Controller
{
    [Authorize]
    public IActionResult BuyWidgets()
    {
        ...
    }
}

Bei Verwendung von Endpunktrouting wird empfohlen, nicht AuthorizeFilter zu konfigurieren und stattdessen die Autorisierungsmiddleware zu verwenden. Wenn die App einen Autorisierungsfilter (AuthorizeFilter) als globalen Filter in MVC verwendet, wird empfohlen, den Code umzugestalten, um im Aufruf von AddAuthorization eine Richtlinie bereitzustellen.

Die Standardrichtlinie (DefaultPolicy) ist zunächst so konfiguriert, dass eine Authentifizierung erforderlich ist. Daher ist keine zusätzliche Konfiguration erforderlich. Im folgenden Beispiel werden MVC-Endpunkte als RequireAuthorization gekennzeichnet, sodass alle Anforderungen basierend auf der Standardrichtlinie (DefaultPolicy) autorisiert werden müssen. Aufgrund von [AllowAnonymous] lässt der Home-Controller (HomeController) jedoch Zugriffe zu, ohne dass sich Benutzer*innen bei der App anmelden:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute().RequireAuthorization();
    });
}

[AllowAnonymous]
public class HomeController : Controller
{
    ...
}

Autorisierung für bestimmte Endpunkte

Die Autorisierung kann auch für bestimmte Endpunktklassen konfiguriert werden. Der folgende Code ist ein Beispiel für die Konvertierung einer MVC-App mit einem konfigurierten globalen Autorisierungsfilter (AuthorizeFilter) in eine App mit einer bestimmten Richtlinie, die eine Autorisierung erfordert:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    static readonly string _RequireAuthenticatedUserPolicy = 
                            "RequireAuthenticatedUserPolicy";
    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));
        services.AddDefaultIdentity<IdentityUser>(
                 options => options.SignIn.RequireConfirmedAccount = true)
            .AddEntityFrameworkStores<ApplicationDbContext>();

        // Pre 3.0:
        // services.AddMvc(options => options.Filters.Add(new AuthorizeFilter(...));

        services.AddControllersWithViews();
        services.AddRazorPages();
        services.AddAuthorization(o => o.AddPolicy(_RequireAuthenticatedUserPolicy,
                        builder => builder.RequireAuthenticatedUser()));

    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute()
                .RequireAuthorization(_RequireAuthenticatedUserPolicy);
            endpoints.MapRazorPages();
        });
    }
}

Richtlinien können auch angepasst werden. Die Standardrichtlinie (DefaultPolicy) ist so konfiguriert, dass eine Authentifizierung erforderlich ist:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));
        services.AddDefaultIdentity<IdentityUser>(
                 options => options.SignIn.RequireConfirmedAccount = true)
            .AddEntityFrameworkStores<ApplicationDbContext>();

        services.AddControllersWithViews();
        services.AddRazorPages();
        services.AddAuthorization(options =>
        {
            options.DefaultPolicy = new AuthorizationPolicyBuilder()
              .RequireAuthenticatedUser()
              .Build();
        });

    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute().RequireAuthorization();
            endpoints.MapRazorPages();
        });
    }
}
[AllowAnonymous]
public class HomeController : Controller
{

Durch Konfigurieren einer Ausweichrichtlinie (FallbackPolicy) können alle Endpunkte auch ohne [Authorize] oder RequireAuthorization so konfiguriert werden, dass eine Autorisierung erforderlich ist. Die Ausweichrichtlinie (FallbackPolicy) unterscheidet sich von der Standardrichtlinie (DefaultPolicy). Die Standardrichtlinie (DefaultPolicy) wird durch [Authorize] oder RequireAuthorization ausgelöst. Die Ausweichrichtlinie (FallbackPolicy) wird dagegen ausgelöst, wenn keine andere Richtlinie festgelegt ist. Die Ausweichrichtlinie (FallbackPolicy) ist zunächst so konfiguriert, dass Anforderungen ohne Autorisierung zugelassen werden.

Das folgende Beispiel ist identisch mit dem vorherigen Beispiel für die Standardrichtlinie (DefaultPolicy), verwendet jedoch die Ausweichrichtlinie (FallbackPolicy), um immer eine Authentifizierung für alle Endpunkte erforderlich zu machen – es sei denn, [AllowAnonymous] wird angegeben:

public void ConfigureServices(IServiceCollection services)
{
    ...

    services.AddAuthorization(options =>
    {
        options.FallbackPolicy = new AuthorizationPolicyBuilder()
          .RequireAuthenticatedUser()
          .Build();
    });
}

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
    });
}

[AllowAnonymous]
public class HomeController : Controller
{
    ...
}

Die Autorisierung durch Middleware funktioniert, ohne dass das Framework über spezifische Autorisierungsinformationen verfügt. Integritätsprüfungen verfügen beispielsweise über keine spezifischen Autorisierungsinformationen, durch die Middleware kann aber eine konfigurierbare Autorisierungsrichtlinie auf sie angewendet werden.

Darüber hinaus können die Autorisierungsanforderungen jedes Endpunkts angepasst werden. Im folgenden Beispiel verarbeitet UseAuthorization die Autorisierung mit der Standardrichtlinie (DefaultPolicy), aber der Integritätsprüfungsendpunkt /healthz erfordert eine*n admin-Benutzer*in:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints
            .MapHealthChecks("/healthz")
            .RequireAuthorization(new AuthorizeAttribute(){ Roles = "admin", });
    });
}

Für einige Szenarien wird Schutz implementiert. Endpunktmiddleware löst eine Ausnahme aus, wenn eine Autorisierungs- oder CORS-Richtlinie aufgrund fehlender Middleware übersprungen wird. Analysetoolunterstützung, um zusätzliches Feedback zu Fehlkonfigurationen zu geben, ist in Arbeit.

Benutzerdefinierte Autorisierungshandler

Wenn die App benutzerdefinierte Autorisierungshandler verwendet, übergibt das Endpunktrouting einen anderen Ressourcentyp an Handler als MVC. Handler, die erwarten, dass die Autorisierungshandlerkontext-Ressource vom Typ AuthorizationFilterContext ist (der von MVC-Filtern bereitgestellte Ressourcentyp), müssen aktualisiert werden, um Ressourcen vom Typ RouteEndpoint zu behandeln (der Ressourcentyp, der vom Endpunktrouting an Autorisierungshandler übergeben wird).

MVC verwendet weiterhin AuthorizationFilterContext-Ressourcen. Wenn die App also MVC-Autorisierungsfilter zusammen mit der Endpunktroutingautorisierung verwendet, müssen möglicherweise beide Arten von Ressourcen behandelt werden.

SignalR

Die Zuordnung von SignalR-Hubs erfolgt jetzt in UseEndpoints.

Ordnen Sie die einzelnen Hubs mit MapHub zu. Wie in früheren Versionen wird jeder Hub explizit aufgeführt.

Im folgenden Beispiel wird Unterstützung für den ChatHubSignalR-Hub hinzugefügt:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapHub<ChatHub>();
    });
}

Es gibt eine neue Option zum Steuern von Nachrichtengrößenbeschränkungen von Clients. Gehen Sie beispielsweise in Startup.ConfigureServices folgendermaßen vor:

services.AddSignalR(hubOptions =>
{
    hubOptions.MaximumReceiveMessageSize = 32768;
});

In ASP.NET Core 2.2 können Sie TransportMaxBufferSize festlegen, um die maximale Nachrichtengröße zu steuern. In ASP.NET Core 3.0 steuert diese Option jetzt nur die maximale Größe bis zum Auftreten eines Rückstaus.

SignalR-Assemblys im freigegebenen Framework

Serverseitige SignalR-Assemblys von ASP.NET Core werden jetzt mit dem .NET Core SDK installiert. Weitere Informationen finden Sie unter Entfernen von Verweisen auf veraltete Pakete in diesem Dokument.

MVC-Controller

Die Zuordnung von Controllern erfolgt jetzt in UseEndpoints.

Fügen Sie MapControllers hinzu, wenn die App Attributrouting verwendet. Das Routing beinhaltet die Unterstützung vieler Frameworks ab ASP.NET Core 3.0. Daher ist das Hinzufügen von Controllern mit attributbasiertem Routing optional.

Ersetzen Sie Folgendes:

  • MapRoute mit MapControllerRoute
  • MapAreaRoute mit MapAreaControllerRoute

Da das Routing jetzt mehr als nur MVC unterstützt, hat sich die Terminologie geändert, damit klar ist, was die jeweilige Methode bewirkt. Konventionelle Routen wie MapControllerRoute/MapAreaControllerRoute/MapDefaultControllerRoute werden in der Reihenfolge angewendet, in der sie hinzugefügt werden. Platzieren Sie spezifischere Routen (z. B. Routen für einen Bereich) weiter vorn.

Im folgenden Beispiel:

  • MapControllers fügt Unterstützung von Controllern mit attributbasiertem Routing hinzu.
  • MapAreaControllerRoute fügt eine konventionelle Route für Controller in einem Bereich hinzu.
  • MapControllerRoute fügt eine konventionelle Route für Controller hinzu.
public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
        endpoints.MapAreaControllerRoute(
            "admin",
            "admin",
            "Admin/{controller=Home}/{action=Index}/{id?}");
        endpoints.MapControllerRoute(
            "default", "{controller=Home}/{action=Index}/{id?}");
    });
}

Entfernung des Async-Suffix aus Controlleraktionsnamen

In ASP.NET Core 3.0 entfernt ASP.NET Core MVC das Suffix Async aus Controlleraktionsnamen. Dieser neue Standard wirkt sich sowohl auf das Routing als auch auf die Linkgenerierung aus. Beispiel:

public class ProductsController : Controller
{
    public async Task<IActionResult> ListAsync()
    {
        var model = await _dbContext.Products.ToListAsync();
        return View(model);
    }
}

Vor ASP.NET Core 3.0:

  • Auf die vorherige Aktion konnte unter der Route Products/ListAsync zugegriffen werden.

  • Für die Linkgenerierung musste das Suffix Async angegeben werden. Beispiel:

    <a asp-controller="Products" asp-action="ListAsync">List</a>
    

In ASP.NET Core 3.0:

  • Auf die vorherige Aktion kann über die Route Products/List zugegriffen werden.

  • Für die Linkgenerierung muss das Suffix Async nicht angegeben werden. Beispiel:

    <a asp-controller="Products" asp-action="List">List</a>
    

Diese Änderung hat keine Auswirkungen auf Namen, die mit dem [ActionName]-Attribut angegeben werden. Dieses Standardverhalten kann mit folgendem Code in Startup.ConfigureServices deaktiviert werden:

services.AddMvc(options =>
    options.SuppressAsyncSuffixInActionNames = false);

Es gibt einige Unterschiede bei der Linkgenerierung (z. B. mithilfe von Url.Link und ähnlichen APIs). Dazu gehören:

  • Bei Verwendung des Endpunktroutings bleibt die Groß- und Kleinschreibung von Routenparametern in generierten URIs standardmäßig nicht unbedingt erhalten. Dieses Verhalten kann mit der IOutboundParameterTransformer-Schnittstelle gesteuert werden.
  • Die Generierung eines URI für eine ungültige Route (ein Controller/eine Aktion oder eine Seite, der bzw. die nicht vorhanden ist) hat eine leere Zeichenfolge unter dem Endpunktrouting zur Folge anstatt einen ungültigen URI.
  • Umgebungswerte (Routenparameter aus dem aktuellen Kontext) werden bei der Linkgenerierung mit Endpunktrouting nicht automatisch verwendet. Bisher wurden beim Generieren eines Links zu einer anderen Aktion (oder Seite) nicht angegebene Routenwerte von den aktuellen Umgebungswerten von Routen abgeleitet. Bei Verwendung des Endpunktroutings müssen während der Linkgenerierung alle Routenparameter explizit angegeben werden.

Razor Pages

Die Zuordnung von Razor Pages erfolgt jetzt in UseEndpoints.

Fügen Sie MapRazorPages hinzu, wenn die App Razor Pages verwendet. Da das Endpunktrouting die Unterstützung vieler Frameworks beinhaltet, ist das Hinzufügen von Razor Pages jetzt optional.

In der folgenden Startup.Configure-Methode wird durch MapRazorPages die Unterstützung von Razor Pages hinzugefügt:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

Verwenden von MVC ohne Endpunktrouting

Die Verwendung von MVC über UseMvc oder UseMvcWithDefaultRoute in ASP.NET Core 3.0 erfordert eine explizite Aktivierung innerhalb von Startup.ConfigureServices. Dies ist erforderlich, da MVC wissen muss, ob es sich während der Initialisierung auf die Autorisierungs- und CORS-Middleware verlassen kann. Es wird ein Analysetool bereitgestellt, das eine Warnung ausgibt, wenn die App versucht, eine nicht unterstützte Konfiguration zu verwenden.

Wenn die App Legacyunterstützung von IRouter erfordert, deaktivieren Sie EnableEndpointRouting mithilfe eines der folgenden Ansätze in Startup.ConfigureServices:

services.AddMvc(options => options.EnableEndpointRouting = false);
services.AddControllers(options => options.EnableEndpointRouting = false);
services.AddControllersWithViews(options => options.EnableEndpointRouting = false);
services.AddRazorPages().AddMvcOptions(options => options.EnableEndpointRouting = false);

Integritätsprüfungen

Integritätsprüfungen können als Routinglösung mit Endpunktrouting verwendet werden.

Fügen Sie MapHealthChecks hinzu, um Integritätsprüfungen mit Endpunktrouting zu verwenden. Die MapHealthChecks-Methode akzeptiert Argumente wie UseHealthChecks. Der Vorteil der Verwendung von MapHealthChecks gegenüber UseHealthChecks ist die Möglichkeit, Autorisierung zu verwenden und eine präzisere Kontrolle über die Abgleichsrichtlinie zu haben.

Im folgenden Beispiel wird MapHealthChecks für einen Integritätsprüfungsendpunkt unter /healthz aufgerufen:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapHealthChecks("/healthz", new HealthCheckOptions() { });
    });
}

HostBuilder ersetzt WebHostBuilder

Die ASP.NET Core 3.0-Vorlagen verwenden den allgemeinen Host. In vorherigen Versionen wurde der Webhost verwendet. Der folgende Code zeigt die per ASP.NET Core 3.0-Vorlage generierte Program-Klasse:

// requires using Microsoft.AspNetCore.Hosting;
// requires using Microsoft.Extensions.Hosting;

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

Der folgende Code zeigt die per ASP.NET Core 2.2-Vorlage generierte Program-Klasse:

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

IWebHostBuilder bleibt in 3.0 und ist der Typ von webBuilder aus dem vorherigen Codebeispiel. WebHostBuilder wird in einem zukünftigen Release als veraltet markiert und durch HostBuilder ersetzt.

Die wichtigste Änderung zwischen WebHostBuilder und HostBuilder betrifft die Abhängigkeitsinjektion (Dependency Injection, DI). Bei Verwendung von HostBuilder kann nur Folgendes in den Konstruktor von Startup eingefügt werden:

Für die Einschränkungen der HostBuilder-Abhängigkeitsinjektion gilt:

  • Sie ermöglichen die einmalige Erstellung des Abhängigkeitsinjektionscontainers.
  • Sie beugen den resultierenden Problemen mit der Objektlebensdauer vor (etwa beim Auflösen mehrerer Singletons).

Weitere Informationen finden Sie unter Avoiding Startup service injection in ASP.NET Core 3.

AddAuthorization in andere Assembly verschoben

Für die AddAuthorization-Methoden von ASP.NET Core 2.2 und niedrigeren Versionen in Microsoft.AspNetCore.Authorization.dll gilt:

  • Sie wurden in AddAuthorizationCore umbenannt.
  • Sie wurden in Microsoft.AspNetCore.Authorization.Policy.dll verschoben.

Apps, die sowohl Microsoft.AspNetCore.Authorization.dll als auch Microsoft.AspNetCore.Authorization.Policy.dll verwenden, sind davon nicht betroffen.

Für Apps, die nicht Microsoft.AspNetCore.Authorization.Policy.dll verwenden, muss eine der folgenden Aktionen ausgeführt werden:

  • Fügen Sie einen Verweis auf Microsoft.AspNetCore.Authorization.Policy.dll hinzu. Dieser Ansatz funktioniert für die meisten Apps, und mehr ist nicht nötig.
  • Wechseln Sie zur Verwendung von AddAuthorizationCore.

Weitere Informationen finden Sie unter Breaking change in AddAuthorization(o =>) overload lives in a different assembly #386.

Identity-BENUTZEROBERFLÄCHE

Aktualisierungen für die Identity-Benutzeroberfläche für ASP.NET Core 3.0:

  • Fügen Sie einen Paketverweis auf Microsoft.AspNetCore.Identity.UI hinzu.
  • Apps, die nicht Razor Pages verwenden, müssen MapRazorPages aufrufen. Weitere Informationen finden Sie unter Razor Pages in diesem Dokument.
  • Bootstrap 4 ist das Standardframework für die Benutzeroberfläche. Legen Sie eine IdentityUIFrameworkVersion-Projekteigenschaft fest, um die Standardeinstellung zu ändern. Weitere Informationen finden Sie in dieser GitHub-Ankündigung.

SignalR

Der SignalR-JavaScript-Client wurde von @aspnet/signalr in @microsoft/signalr geändert. Um auf diese Änderung zu reagieren, ändern Sie die Verweise in Dateien vom Typ package.json, in require-Anweisungen und in ECMAScript-import-Anweisungen.

System.Text.Json ist das Standardprotokoll.

System.Text.Json ist jetzt das Standardhubprotokoll und wird sowohl vom Client als auch vom Server verwendet.

Rufen Sie AddJsonProtocol in Startup.ConfigureServices auf, um Serialisierungsmoduloptionen festzulegen.

Server:

services.AddSignalR(...)
        .AddJsonProtocol(options =>
        {
            options.PayloadSerializerOptions.WriteIndented = false;
        })

Client:

new HubConnectionBuilder()
    .WithUrl("/chathub")
    .AddJsonProtocol(options =>
    {
        options.PayloadSerializerOptions.WriteIndented = false;
    })
    .Build();

Wechseln zu Newtonsoft.Json

Wenn Sie Features von Newtonsoft.Json verwenden, die in System.Text.Json nicht unterstützt werden, können Sie zu Newtonsoft.Json zurückwechseln. Weitere Informationen finden Sie weiter oben in diesem Artikel unter Verwenden von Newtonsoft.Json in einem SignalR-Projekt für ASP.NET Core 3.0.

Verteilte Redis-Caches

Das Paket Microsoft.Extensions.Caching.Redis ist nicht für Apps ab ASP.NET Core 3.0 verfügbar. Ersetzen Sie den Paketverweis durch Microsoft.Extensions.Caching.StackExchangeRedis. Weitere Informationen finden Sie unter Verteiltes Zwischenspeichern in ASP.NET Core.

Aktivieren der Laufzeitkompilierung

Vor ASP.NET Core 3.0 war die Laufzeitkompilierung von Ansichten ein implizites Feature des Frameworks. Die Laufzeitkompilierung ergänzt die Buildzeitkompilierung von Ansichten. Es ermöglicht dem Framework, Razor-Ansichten und -Seiten (.cshtml-Dateien) zu kompilieren, wenn die Dateien geändert werden, ohne die gesamte App neu erstellen zu müssen. Dieses Feature unterstützt das Szenario einer schnellen Bearbeitung in der IDE mit anschließender Aktualisierung des Browsers, um die Änderungen anzuzeigen.

In ASP.NET Core 3.0 ist die Laufzeitkompilierung ein optionales Szenario. Die Buildzeitkompilierung ist der einzige Mechanismus für die Ansichtskompilierung, der standardmäßig aktiviert ist. Die Runtime basiert auf Visual Studio oder dotnet-watch in Visual Studio Code, um das Projekt neu zu erstellen, wenn Änderungen an Dateien vom Typ .cshtml erkannt werden. In Visual Studio lösen Änderungen an Dateien vom Typ .cs, .cshtml oder .razor eine Neukompilierung des Projekts aus. Das gilt allerdings nur für Projekte, die mithilfe von STRG+F5 ausgeführt werden, aber nicht für Projekte, die mithilfe von F5 gedebuggt werden.

So aktivieren Sie die Laufzeitkompilierung in Ihrem ASP.NET Core 3.0-Projekt

  1. Installieren Sie das NuGet-Paket Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation.

  2. Aktualisieren Sie Startup.ConfigureServices, um AddRazorRuntimeCompilation aufzurufen:

    Verwenden Sie für ASP.NET Core MVC den folgenden Code:

    services.AddControllersWithViews()
        .AddRazorRuntimeCompilation(...);
    

    Verwenden Sie für ASP.NET Core Razor Pages den folgenden Code:

    services.AddRazorPages()
        .AddRazorRuntimeCompilation(...);
    

Das Beispiel unter https://github.com/aspnet/samples/tree/main/samples/aspnetcore/mvc/runtimecompilation zeigt ein Beispiel für die bedingte Aktivierung der Laufzeitkompilierung in Entwicklungsumgebungen.

Weitere Informationen zur Kompilierung von Razor-Dateien finden Sie unter Kompilieren einer Razor-Datei in ASP.NET Core.

Migrieren von Bibliotheken durch Festlegung von Zielversionen

Bibliotheken müssen häufig mehrere Versionen von ASP.NET Core unterstützen. Die meisten Bibliotheken, die für frühere Versionen von ASP.NET Core kompiliert wurden, sollten ohne Probleme weiter funktionieren. In folgenden Fällen muss die App kreuzkompiliert werden:

  • Wenn die Bibliothek auf einem Feature basiert, für das ein binärer Breaking Change vorgenommen wurde.
  • Wenn die Bibliothek neue Features in ASP.NET Core 3.0 nutzen soll.

Beispiel:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>netcoreapp3.0;netstandard2.0</TargetFrameworks>
  </PropertyGroup>

  <ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>

  <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
    <PackageReference Include="Microsoft.AspNetCore" Version="2.1.0" />
  </ItemGroup>
</Project>

Verwenden Sie #ifdefs, um spezifische APIs für ASP.NET Core 3.0 zu aktivieren:

var webRootFileProvider =
#if NETCOREAPP3_0
    GetRequiredService<IWebHostEnvironment>().WebRootFileProvider;
#elif NETSTANDARD2_0
    GetRequiredService<IHostingEnvironment>().WebRootFileProvider;
#else
#error unknown target framework
#endif

Weitere Informationen zur Verwendung von ASP.NET Core-APIs in einer Klassenbibliothek finden Sie unter Verwenden von ASP.NET Core-APIs in einer Klassenbibliothek.

Verschiedene Änderungen

Das Validierungssystem in .NET Core 3.0 und höher behandelt Non-Nullable-Parameter oder gebundene Eigenschaften so, als würden sie ein [Required]-Attribut aufweisen. Weitere Informationen finden Sie unter Modellvalidierung in ASP.NET Core MVC und Razor Pages.

Veröffentlichen

Löschen Sie die Ordner bin und obj im Projektverzeichnis.

TestServer

Erstellen Sie für Apps, die TestServer direkt mit dem generischen Host verwenden, den Testserver (TestServer) für ein IWebHostBuilder-Element in ConfigureWebHost:

[Fact]
public async Task GenericCreateAndStartHost_GetTestServer()
{
    using var host = await new HostBuilder()
        .ConfigureWebHost(webBuilder =>
        {
            webBuilder
                .UseTestServer()
                .Configure(app => { });
        })
    .StartAsync();

    var response = await host.GetTestServer().CreateClient().GetAsync("/");

    Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}

Breaking Changes für APIs

Sehen Sie sich die Breaking Changes an:

Endpunktrouting mit Catch-All-Parameter

Warnung

Ein catch-all-Parameter kann aufgrund eines Fehlers beim Routing nicht ordnungsgemäß mit Routen übereinstimmen. Apps, die von diesem Fehler betroffen sind, weisen die folgenden Merkmale auf:

  • Eine catch-all-Route, zum Beispiel {**slug}"
  • Die catch-all-Route kann nicht mit Anforderungen abgeglichen werden, die abgeglichen werden sollen.
  • Durch das Entfernen anderer Routen funktioniert die catch-all-Route.

Weitere Beispiele zu diesem Fehler finden Sie in den GitHub-Issues 18677 und 16579.

Eine Opt-in-Behebung für diesen Fehler ist im .NET Core 3.1.301 SDK und höher enthalten. Der folgende Code legt einen internen Switch fest, mit dem dieser Fehler behoben wird:

public static void Main(string[] args)
{
   AppContext.SetSwitch("Microsoft.AspNetCore.Routing.UseCorrectCatchAllBehavior", 
                         true);
   CreateHostBuilder(args).Build().Run();
}
// Remaining code removed for brevity.

.NET Core 3.0 in Azure App Service

Der Rollout von .NET Core in Azure App Service ist abgeschlossen. .NET Core 3.0 ist in allen Azure App Service-Rechenzentren verfügbar.

ASP.NET Core-Modul (ANCM)

Wenn das ASP.NET Core-Modul (ANCM) bei der Installation von Visual Studio keine ausgewählte Komponente war oder wenn eine frühere Version des ANCM auf dem System installiert wurde, laden Sie den neuesten Installer für das .NET Core Hosting-Paket (direkter Download) herunter, und führen Sie das Installationsprogramm aus. Weitere Informationen finden Sie unter Das .NET Core-Hostingbundle.