從 ASP.NET Core 5.0 移轉至 6.0

本文說明如何將現有的 ASP.NET Core 5.0 專案更新為 ASP.NET Core 6.0。 如需如何從 ASP.NET Core 3.1 移轉至 ASP.NET Core 6.0 的指示,請參閱從 ASP.NET Core 3.1 移轉至 6.0

必要條件

更新 global.json 中的 .NET SDK 版本

如果您依賴 global.json 檔案以特定 .NET SDK 版本為目標,請將 version 屬性更新為已安裝的 .NET 6.0 SDK 版本。 例如:

{
  "sdk": {
-    "version": "5.0.100"
+    "version": "6.0.100"
  }
}

更新目標 Framework

將專案檔 的目標 Framework Moniker (TFM) 更新為 net6.0

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

  <PropertyGroup>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>

</Project>

更新套件參考

在專案檔中,將每個 Microsoft.AspNetCore.*Microsoft.Extensions.* 套件參考的 Version 屬性更新為 6.0.0 或更新版本。 例如:

<ItemGroup>
-    <PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="5.0.3" />
-    <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="5.0.0" />
+    <PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="6.0.0" />
+    <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="6.0.0" />
</ItemGroup>

新的裝載模型

適用于 ASP.NET Core應用程式的新 .NET 6 最小裝載模型只需要一個檔案和幾行程式碼。 移轉至 6.0 的應用程式不需要使用新的最小裝載模型。 如需詳細資訊,請參閱下一節中移 轉至 6.0 的應用程式不需要使用新的最小裝載模型

ASP.NET Core空白範本中的下列程式碼會使用新的最小裝載模型來建立應用程式:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

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

app.Run();

最小裝載模型:

  • 大幅減少建立應用程式所需的檔案和程式程式碼數。 有四行程式碼只需要一個檔案。
  • 將 和 Program.cs 整合 Startup.cs 成單 Program.cs 一檔案。
  • 使用 最上層語句 ,將應用程式所需的程式碼最小化。
  • 使用全域 using 指示詞來消除或最小化所需的語句行數using

下列程式碼會顯示 Startup.cs ASP.NET Core 5 Web 應用程式範本中的 和 Program.cs 檔案, (Razor Pages) 已移除未 using 使用的語句:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
// Unused usings removed.

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

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
            });
        }
    }
}
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
// Unused usings removed.

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

在 ASP.NET Core 6 中,上述程式碼會由下列程式碼取代:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorPages();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

上述 ASP.NET Core 6 範例示範如何:

本檔稍後會提供將 ASP.NET Core 5 Startup 個程式碼移轉至 ASP.NET Core 6 的詳細範例。

Web 應用程式範本所產生的其他檔案有一些變更:

- public string RequestId { get; set; }
+ public string? RequestId { get; set; }
  • appsettings.Development.json 中的 appsettings.json 記錄層級預設值已變更:
- "Microsoft": "Warning",
- "Microsoft.Hosting.Lifetime": "Information"
+ "Microsoft.AspNetCore": "Warning"

在上述 ASP.NET Core範本程式碼中, "Microsoft": "Warning" 已變更為 "Microsoft.AspNetCore": "Warning" 。 這項變更會導致記錄命名空間中的所有參考訊息 Microsoft,但除外Microsoft.AspNetCore 。 例如, Microsoft.EntityFrameworkCore 現在會記錄在資訊層級。

如需新裝載模型的詳細資訊,請參閱 常見問題一 節。 如需採用 NRT 和 .NET 編譯器 Null 狀態分析的詳細資訊,請參閱 NRT () 和 .NET 編譯器 Null 狀態靜態分析 一節。

移轉至 6.0 的應用程式不需要使用新的最小裝載模型

Startup完全支援使用 ASP.NET Core 3.1 和 5.0 範本所使用的和泛型主機

搭配新的最小裝載模型使用啟動

ASP.NET Core 3.1 和 5.0 應用程式可以使用其 Startup 程式碼搭配新的最小裝載模型。 請考慮 ASP.NET Core 3.1 或 5.0 Razor Pages 範本所產生的下列程式碼:

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>();
            });
}
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

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

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

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseRouting();

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

上述程式碼已移轉至新的最小裝載模型:

using Microsoft.AspNetCore.Builder;

var builder = WebApplication.CreateBuilder(args);

var startup = new Startup(builder.Configuration);

startup.ConfigureServices(builder.Services);

var app = builder.Build();

startup.Configure(app, app.Environment);

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

    public IConfiguration Configuration { get; }

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

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (!env.IsDevelopment())
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseRouting();

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

在上述程式碼中 if (env.IsDevelopment()) ,會移除 區塊,因為在 開發模式中,預設會啟用開發人員例外狀況頁面中介軟體。 如需詳細資訊,請參閱下一節中的ASP.NET Core 5 和 6 裝載模型之間的差異

使用自訂相依性插入 (DI) 容器時,請新增下列醒目提示的程式碼:

using Autofac;
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Hosting;

var builder = WebApplication.CreateBuilder(args);

var startup = new Startup(builder.Configuration);

startup.ConfigureServices(builder.Services);

// Using a custom DI container.
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(startup.ConfigureContainer);

var app = builder.Build();

startup.Configure(app, app.Environment);

app.Run();
using Autofac;
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

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

    //  Using a custom DI container
    public void ConfigureContainer(ContainerBuilder builder)
    {
        // Configure custom container.
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (!env.IsDevelopment())
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseRouting();

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

使用最小裝載模型時,端點路由中介軟體會包裝整個中介軟體管線,因此不需要明確呼叫 UseRoutingUseEndpoints 註冊路由。 UseRouting 仍然可以用來指定路由比對發生的位置,但如果 UseRouting 中介軟體管線的開頭應該比對路由,則不需要明確呼叫。

在下列程式碼中,會從 Startup 中移除 對 UseRoutingUseEndpoints 的呼叫。 MapRazorPages 在 中 Program.cs 呼叫 :

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

    public IConfiguration Configuration { get; }

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

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (!env.IsDevelopment())
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        //app.UseRouting();

        //app.UseEndpoints(endpoints =>
        //{
        //    endpoints.MapRazorPages();
        //});
    }
}
using Microsoft.AspNetCore.Builder;

var builder = WebApplication.CreateBuilder(args);

var startup = new Startup(builder.Configuration);

startup.ConfigureServices(builder.Services);

var app = builder.Build();

startup.Configure(app, app.Environment);

app.MapRazorPages();

app.Run();

搭配新的最小裝載模型使用 Startup 時,請記住下列差異:

  • Program.cs 控制 類別的 Startup 具現化和存留期。
  • 插入 方法的任何其他服務 Configure 都必須由 Program 類別手動解析。

ASP.NET Core 5 和 6 裝載模型之間的差異

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

// WebHost

try
{
    builder.WebHost.UseContentRoot(Directory.GetCurrentDirectory());
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

try
{
    builder.WebHost.UseEnvironment(Environments.Staging);
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

try
{
    builder.WebHost.UseSetting(WebHostDefaults.ApplicationKey, "ApplicationName2");
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

try
{
    builder.WebHost.UseSetting(WebHostDefaults.ContentRootKey, Directory.GetCurrentDirectory());
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

try
{
    builder.WebHost.UseSetting(WebHostDefaults.EnvironmentKey, Environments.Staging);
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

// Host
try
{
    builder.Host.UseEnvironment(Environments.Staging);
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

try
{
    // TODO: This does not throw
    builder.Host.UseContentRoot(Directory.GetCurrentDirectory());
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();
  • Startup類別無法從 WebApplicationBuilder.HostWebApplicationBuilder.WebHost 使用。 下列醒目提示的程式碼會擲回例外狀況:

    var builder = WebApplication.CreateBuilder(args);
    
    try
    {
        builder.Host.ConfigureWebHostDefaults(webHostBuilder =>
        {
            webHostBuilder.UseStartup<Startup>();
        });
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
        throw;    
    }
    
    builder.Services.AddRazorPages();
    
    var app = builder.Build();
    
    var builder = WebApplication.CreateBuilder(args);
    
    try
    {
        builder.WebHost.UseStartup<Startup>();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
        throw;    
    }
    
    builder.Services.AddRazorPages();
    
    var app = builder.Build();
    
  • IHostBuilder (WebApplicationBuilder.Host) 上的 WebApplicationBuilder 實作不會延遲 、 ConfigureAppConfigurationConfigureHostConfiguration 方法的執行 ConfigureServices 。 不順延強制可讓程式碼使用 WebApplicationBuilder 來觀察 對 和 IConfiguration 所做的 IServiceCollection 變更。 下列範例只會新增 Service1IService

    using Microsoft.Extensions.DependencyInjection.Extensions;
    
    var builder = WebApplication.CreateBuilder(args);
    
    builder.Host.ConfigureServices(services =>
    {
        services.TryAddSingleton<IService, Service1>();
    });
    
    builder.Services.TryAddSingleton<IService, Service2>();
    
    var app = builder.Build();
    
    // Displays Service1 only.
    Console.WriteLine(app.Services.GetRequiredService<IService>());
    
    app.Run();
    
    class Service1 : IService
    {
    }
    
    class Service2 : IService
    {
    }
    
    interface IService
    {
    }
    

在上述程式碼中,回 builder.Host.ConfigureServices 呼會內嵌呼叫,而不是延遲直到呼叫為止 builder.Build 。 這表示 Service1 會在 之前 Service2 加入 , IServiceCollection 並導致 Service1 解析 。 IService

建置 ASP.NET Core 6 的程式庫

現有的 .NET 生態系統在 、 IHostBuilderIWebHostBuilder 周圍 IServiceCollection 建置擴充性。 這些屬性可在 上 WebApplicationBuilder 以 、 HostWebHost 的形式 Services 提供。

WebApplication 會同時 Microsoft.AspNetCore.Builder.IApplicationBuilder 實作 和 Microsoft.AspNetCore.Routing.IEndpointRouteBuilder

我們預期程式庫作者在建置 ASP.NET Core特定元件時,會繼續以 、 IWebHostBuilderIApplicationBuilderIEndpointRouteBuilder 為目標 IHostBuilder 。 這可確保您的中介軟體、路由處理常式或其他擴充點可跨不同的裝載模型繼續運作。

常見問題集 (FAQ)

  • 新的最小裝載模型是否較不支援?

    不可以。 新的裝載模型在功能上相當於 和 IWebHostBuilder 支援的 98% 案例 IHostBuilder 。 有一些進階案例需要 上的 IHostBuilder 特定因應措施,但我們預期這些情況非常罕見。

  • 泛型裝載模型是否已被取代?

    不可以。 泛型裝載模型是無限期支援的替代模型。 泛型主機會支援新的裝載模型,而且仍然是裝載背景工作角色型應用程式的主要方式。

  • 我是否需要移轉至新的裝載模型?

    不可以。 新的裝載模型是使用 .NET 6 和更新版本來裝載新應用程式的慣用方式,但您不會強制變更現有應用程式中的專案配置。 這表示應用程式可以從 .NET 5 升級至 .NET 6,方法是將專案檔中的目標 Framework 從 net5.0 變更為 net6.0 。 如需詳細資訊,請參閱本文中的 更新目標 Framework 一節。 不過,我們建議應用程式移轉至新的裝載模型,以利用僅適用于新裝載模型的新功能。

  • 我是否需要使用最上層語句?

    不可以。 新的專案範本全都使用 最上層語句,但新的裝載 API 可用於任何 .NET 6 應用程式來裝載 Web 服務器或 Web 應用程式。

  • 我要在哪裡放置儲存為 或 Startup 類別中 Program 欄位的狀態?

    強烈建議使用相依性插入 (DI) ,在 ASP.NET Core應用程式中流動狀態。

    在 DI 外部儲存狀態的方法有兩種:

    • Microsoft Store另一個類別中的狀態。 儲存在類別中會假設可從應用程式的任何位置存取的靜態狀態。

    • Program使用最上層語句所產生的類別來儲存狀態。 使用 Program 來儲存狀態是語意方法:

      var builder = WebApplication.CreateBuilder(args);
      
      ConfigurationValue = builder.Configuration["SomeKey"] ?? "Hello";
      
      var app = builder.Build();
      
      app.MapGet("/", () => ConfigurationValue);
      
      app.Run();
      
      partial class Program
      {
          public static string? ConfigurationValue { get; private set; }
      }
      
  • 如果我使用自訂相依性插入容器,該怎麼辦?

    支援自訂 DI 容器。 如需範例,請參閱 自訂相依性插入 (DI) 容器

  • 是否 WebApplicationFactoryTestServer 可運作?

    是。 WebApplicationFactory<TEntryPoint> 是測試新裝載模型的方式。 如需範例,請參閱使用 WebApplicationFactoryTestServer 進行測試

Blazor

遵循本文稍早的指引,將應用程式更新為 6.0 之後,請遵循ASP.NET Core 6.0 新功能中的連結,採用特定功能。

若要 針對 Blazor 應用程式採用所有新的 6.0 功能,建議您執行下列程式:

  • 從其中 Blazor 一個專案範本建立新的 6.0 Blazor 專案。 如需詳細資訊,請參閱ASP.NET Core Blazor 的工具
  • 將應用程式的元件和程式碼移至 6.0 應用程式進行修改,以採用新的 6.0 功能。

更新 Docker 映射

針對使用 Docker 的應用程式,請更新您的 DockerfileFROM 語句和腳本。 使用包含 ASP.NET Core 6.0 執行時間的基底映射。 請考慮 ASP.NET Core 5.0 和 6.0 之間的下列 docker pull 命令差異:

- docker pull mcr.microsoft.com/dotnet/aspnet:5.0
+ docker pull mcr.microsoft.com/dotnet/aspnet:6.0

請參閱GitHub問題重大變更:預設主控台記錄器格式設定為 JSON

ASP.NET Core Razor SDK 的變更

編譯器 Razor 現在會利用新的 來源產生器功能 ,從專案中的 Razor 檢視和頁面產生已編譯的 C# 檔案。 在舊版中:

  • 編譯依賴 RazorGenerateRazorCompile 目標來產生產生的程式碼。 這些目標不再有效。 在 .NET 6 中,對編譯器的單一呼叫支援程式碼產生和編譯。 RazorComponentGenerateDependsOn 仍支援指定建置執行之前所需的相依性。
  • 已產生個別 Razor 的元件 AppName.Views.dll ,其中包含應用程式中已編譯的檢視類型。 此行為已被取代,而且會產生單一元件 AppName.dll ,其中包含應用程式類型和產生的檢視。
  • 中的 AppName.Views.dll 應用程式類型是公用的。 在 .NET 6 中,應用程式類型位於 , AppName.dll 但 為 internal sealed 。 在 上 AppName.Views.dll 執行類型探索的應用程式將無法在 上 AppName.dll 執行類型探索。 以下顯示 API 變更:
- public class Views_Home_Index : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic>
+ internal sealed class Views_Home_Index : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic>

進行下列變更:

  • 下列屬性不再適用于單一步驟編譯模型。
    • RazorTargetAssemblyAttribute
    • RazorTargetName
    • EnableDefaultRazorTargetAssemblyInfoAttributes
    • UseRazorBuildServer
    • GenerateRazorTargetAssemblyInfo
    • GenerateMvcApplicationPartsAssemblyAttributes

如需詳細資訊,請參閱Razor 編譯器不再產生 Views 元件

Project範本使用 Duende Identity伺服器

Project範本現在使用Duende Identity Server。 如需移轉指引,請參閱Identity Server4 v4.1 至 Duende Identity Server v5

重要

Duende Identity Server 是具有相互授權合約的開放原始碼產品。 如果您打算在生產環境中使用 Duende 伺服器,您可能需要從DuendeIdentity Software 取得商業授權,並支付授權費用。 如需詳細資訊,請參閱 Duende Software:授權

若要瞭解如何針對 使用Microsoft Azure Active DirectoryASP.NET Core Identity ,請參閱Identity (dotnet/aspnetcore GitHub 存放庫)

DbSet<Key>將名為 Keys 的屬性新增至每個 IdentityDbContext ,以滿足 更新版本的 IPersistedGrantDbContext 新需求。 金鑰是 Duende Identity Server 存放區合約的一部分。

public DbSet<Key> Keys { get; set; }

注意

必須針對 Duende Identity Server 重新建立現有的移轉。

移轉至 ASP.NET Core 6.0 的程式碼範例

在 6.0 中移轉至新的最小裝載模型的程式碼範例

檢閱重大變更

請參閱下列資源:

NRT (可為 Null 的參考類型,) 和 .NET 編譯器 null 狀態靜態分析

ASP.NET Core專案範本會使用可為 Null 的參考類型 (NRT) ,而 .NET 編譯器會執行 null 狀態靜態分析。 這些功能是使用 C# 8 發行,預設會針對使用 ASP.NET Core 6.0 (C# 10) 或更新版本所產生的應用程式啟用。

.NET 編譯器的 Null 狀態靜態分析警告可作為更新檔範例或本機範例應用程式或忽略的指南。 如果編譯器警告在學習 .NET 時分心,則可以在應用程式的專案檔中將 設定 Nullabledisable ,以停用 Null 狀態靜態分析,只有在編譯器警告干擾時,才建議使用檔範例和範例應用程式。 不建議停用生產專案中的 Null 狀態檢查。

如需 NRT、MSBuild Nullable 屬性和更新應用程式的詳細資訊, (包括 #pragma 指引) ,請參閱 C# 檔中的下列資源:

ASP.NET CORE模組 (ANCM)

如果安裝 ASP.NET Core Visual Studio或系統上已安裝舊版 ANCM 時, (ANCM) (模組 (未選取元件,請下載最新的.NET Core 裝載套件組合安裝程式, (直接下載) 並執行安裝程式。 如需詳細資訊,請參閱 裝載套件組合

其他資源