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

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

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

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

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

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

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

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

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

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

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

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

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

    • 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 問題 重大變更:預設主控台記錄器格式設定為 JS ON

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

專案範本使用 Duende Identity 伺服器

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

重要

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

若要瞭解如何使用Microsoft Azure Active Directory進行 ASP.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 中新的最小裝載模型

檢閱重大變更

請參閱下列資源:

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

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

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

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

ASP.NET Core模組 (ANCM)

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

應用程式名稱變更

在 .NET 6 中, WebApplicationBuilder 將結尾 DirectorySeparatorChar 的內容根路徑正規化為 。 大部分從 或 移 HostBuilder 轉的應用程式 WebHostBuilder 都不會有相同的應用程式名稱,因為它們未正規化。 如需詳細資訊,請參閱 SetApplicationName

其他資源