Share via


從 .NET 7 中的 ASP.NET Core 移轉至 .NET 8

此文章說明如何將現有的 ASP.NET Core 7.0 專案更新為 ASP.NET Core 8.0。

必要條件

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

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

{
  "sdk": {
-    "version": "7.0.100"
+    "version": "8.0.100"
  }
}

更新目標 Framework

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

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

  <PropertyGroup>
-    <TargetFramework>net7.0</TargetFramework>
+    <TargetFramework>net8.0</TargetFramework>
  </PropertyGroup>

</Project>

更新套件參考

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

<ItemGroup>
-   <PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="7.0.12" />
-   <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.12" />
-   <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="7.0.0" />
-   <PackageReference Include="System.Net.Http.Json" Version="7.0.1" />
+   <PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="8.0.0" />
+   <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.0" />
+   <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="8.0.0" />
+   <PackageReference Include="System.Net.Http.Json" Version="8.0.0" />
</ItemGroup>

Blazor

涵蓋支援下列移轉案例:

如需將 Blazor 支援新增至 ASP.NET Core 應用程式的指導,請參閱 將 ASP.NET CoreRazor 元件整合至 ASP.NET Core 應用程式

更新 Blazor Server 應用程式

我們建議在 .NET 8 中使用 Blazor Web 應用程式,但 Blazor Server 受到支援。 若要繼續使用 Blazor Server .NET 8,請遵循本文前三節中的指導:

針對 Blazor Web 應用程式引進的新 Blazor 功能不適用於更新為在 .NET 8 下執行的 Blazor Server 應用程式。 如果您想要採用新的 .NET 8 Blazor 功能,請遵循下列任一節中的指導:

採用所有 Blazor Web 應用程式慣例

若要選擇性地採用所有新的 Blazor Web 應用程式慣例,我們建議以下流程:

  • 從 Blazor Web 應用程式專案範本建立新的應用程式。 如需詳細資訊,請參閱 ASP.NET Core Blazor 工具。
  • 將應用程式的元件和程式碼移至新的 Blazor Web 應用程式,以進行修改以採用新功能。
  • 更新 Blazor Web 應用程式的版面配置和樣式。

ASP.NET Core 8.0 的新功能 涵蓋新的 .NET 8 功能。 從 .NET 6 或更早版本更新應用程式時,請參閱移轉和版本資訊 (新功能 文章) 以介入版本。

將 Blazor Server 應用程式轉換成 Blazor Web 應用程式

.NET 8 中支援 Blazor Server 應用程式,而不需要變更任何程式碼。 使用下列指導將 Blazor Server 應用程式轉換成對等的 .NET 8 Blazor Web 應用程式,讓所有 新的 .NET 8 功能 都可供使用。

重要

本章節會著重在將 .NET 7 Blazor Server 應用程式轉換成 .NET 8 Blazor Web 應用程式所需的最小變更。 若要採用所有新的 Blazor Web 應用程式慣例,請遵循採用所有 Blazor Web 應用程式慣例一節中的指導。

  1. 請遵循本文前三個章節的指導:

  2. App 元件的內容 (App.razor) 移至新增至專案根資料夾的新 Routes 元件檔案 (Routes.razor)。 將空白 App.razor 檔案保留在專案的根資料夾中的應用程式中。

  3. 將專案新增至 _Imports.razor 檔案,讓速記轉譯模式可供應用程式使用:

    @using static Microsoft.AspNetCore.Components.Web.RenderMode
    
  4. _Host 頁面中的內容 (Pages/_Host.cshtml) 移至空白的 App.razor 檔案。 繼續對 App 元件進行下列變更。

    注意

    在下列範例中,專案的命名空間為 BlazorServerApp。 調整命名空間以符合您的專案。

    從檔案頂端移除下列幾行:

    - @page "/"
    - @using Microsoft.AspNetCore.Components.Web
    - @namespace BlazorServerApp.Pages
    - @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
    

    將上述幾行取代為插入 IHostEnvironment 執行個體的行:

    @inject IHostEnvironment Env
    

    <base> 標籤的 href 移除 tilde (~),並以您應用程式的基底路徑取代:

    - <base href="~/" />
    + <base href="/" />
    

    移除 HeadOutlet 元件的元件標籤協助程式,並以 HeadOutlet 元件取代它。

    移除下列程式碼:

    - <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
    

    將上述一行取代為以下內容:

    <HeadOutlet @rendermode="InteractiveServer" />
    

    移除 App 元件的元件標籤協助程式,並以 Routes 元件取代它。

    移除下列程式碼:

    - <component type="typeof(App)" render-mode="ServerPrerendered" />
    

    將上述一行取代為以下內容:

    <Routes @rendermode="InteractiveServer" />
    

    注意

    上述設定假設應用程式的元件採用互動式伺服器轉譯。 如需詳細資訊,包括如何採用靜態伺服器端轉譯 (SSR),請參閱 ASP.NET Core Blazor 轉譯模式

    移除錯誤 UI 的環境標記協助程式,並以下列 Razor 標記取代它們。

    移除下列各行:

    - <environment include="Staging,Production">
    -     An error has occurred. This application may no longer respond until reloaded.
    - </environment>
    - <environment include="Development">
    -     An unhandled exception has occurred. See browser dev tools for details.
    - </environment>
    

    將上述幾行取代為以下內容:

    @if (Env.IsDevelopment())
    {
        <text>
            An unhandled exception has occurred. See browser dev tools for details.
        </text>
    }
    else
    {
        <text>
            An error has occurred. This app may no longer respond until reloaded.
        </text>
    }
    

    將 Blazor 指令碼從 blazor.server.js 變更為 blazor.web.js:

    - <script src="_framework/blazor.server.js"></script>
    + <script src="_framework/blazor.web.js"></script>
    
  5. 刪除 Pages/_Host.cshtml 檔案。

  6. 更新 Program.cs

    注意

    在下列範例中,專案的命名空間為 BlazorServerApp。 調整命名空間以符合您的專案。

    using 陳述式新增至專案命名空間檔案的頂端:

    using BlazorServerApp;
    

    AddRazorComponents 取代 AddServerSideBlazor,並鏈結呼叫至 AddInteractiveServerComponents

    移除下列程式碼:

    - builder.Services.AddServerSideBlazor();
    

    使用 Razor 元件和互動式伺服器元件服務來取代上一行。 呼叫 AddRazorComponents 預設會新增防偽服務 (AddAntiforgery)。

    builder.Services.AddRazorComponents()
        .AddInteractiveServerComponents();
    

    移除下列程式碼:

    - app.MapBlazorHub();
    

    將上一行取代為對 MapRazorComponents 的呼叫,提供 App 元件做為根元件類型,並將鏈結呼叫新增至 AddInteractiveServerRenderMode

    app.MapRazorComponents<App>()
        .AddInteractiveServerRenderMode();
    

    移除下列程式碼:

    - app.MapFallbackToPage("/_Host");
    

    在呼叫 app.UseRouting 之後,將 Antiforgery 中介軟體新增至要求處理管線。 如果有對 app.UseRoutingapp.UseEndpoints 發出呼叫,則對 app.UseAntiforgery 的呼叫必須介於這兩者之間。 對 app.UseAntiforgery 發出的呼叫必須在放置對 app.UseAuthenticationapp.UseAuthorization 發出的呼叫之後。 無需新增防偽服務 (builder.Services.AddAntiforgery()),因為它們是由前面介紹過的 AddRazorComponents 自動新增的。

    app.UseAntiforgery();
    
  7. 如果 Blazor Server 應用程式已設定為停用預先轉譯,您可以繼續停用已更新應用程式的預先轉譯。 在 App 元件中,變更指派給 HeadOutletRoutes 元件的 @rendermodeRazor 指示詞屬性的值。

    變更 HeadOutletRoutes 元件的 @rendermode 指示詞屬性值,以停用預先呈現:

    - @rendermode="InteractiveServer"
    + @rendermode="new InteractiveServerRenderMode(prerender: false)"
    

    如需詳細資訊,請參閱 ASP.NET Core Blazor 轉譯模式

更新 Blazor WebAssembly 應用程式

請遵循本文前三個章節的指導:

將裝載的 Blazor WebAssembly 應用程式轉換成 Blazor Web 應用程式

.NET 8 中支援 Blazor WebAssembly 應用程式,不需要變更任何程式碼。 使用下列指導將 ASP.NET Core 裝載的 Blazor WebAssembly 應用程式轉換成對等的 .NET 8 Blazor Web 應用程式,讓所有 新的 .NET 8 功能 都可供使用。

重要

本章節會著重在將 .NET 7 ASP.NET Core 裝載的 Blazor WebAssembly 應用程式轉換成 .NET 8 Blazor Web 應用程式所需的最小變更。 若要採用所有新的 Blazor Web 應用程式慣例,請遵循採用所有 Blazor Web 應用程式慣例一節中的指導。

  1. 請遵循本文前三個章節的指導:

    重要

    使用上述指導,更新解決方案的 .Client.Server.Shared 專案。

  2. .Client 專案檔 (.csproj) 中,新增下列 MSBuild 屬性:

    <NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
    <StaticWebAssetProjectMode>Default</StaticWebAssetProjectMode>
    

    另外,在 .Client 專案檔中,移除 Microsoft.AspNetCore.Components.WebAssembly.DevServer 套件參考:

    - <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer"... />
    
  3. 將檔案內容從 .Client/wwwroot/index.html 檔案移至在 .Server 專案的根所建立的新 App 元件檔案 (App.razor)。 在您移動檔案的內容之後,請刪除 index.html 檔案。

    .Client 專案中的 App.razor 重新命名為 Routes.razor

    Routes.razor中,將 AppAssembly 屬性值更新為 typeof(Program).Assembly

  4. .Client 專案中,將項目新增至 _Imports.razor 檔案,讓速記轉譯模式可供應用程式使用:

    @using static Microsoft.AspNetCore.Components.Web.RenderMode
    

    製作 .Client 專案的 _Imports.razor 檔案的複本,並將其新增至 .Server 專案。

  5. App.razor 檔案進行下列變更:

    將網站的預設網站標題 (<title>...</title>) 取代為 HeadOutlet 元件。 請記下網站標題以供稍後使用,並移除標題標籤和標題:

    - <title>...</title>
    

    在您移除標題的位置,放置 HeadOutlet 元件,指派互動式 WebAssembly 轉譯模式 (已停用預先轉譯):

    <HeadOutlet @rendermode="new InteractiveWebAssemblyRenderMode(prerender: false)" />
    

    變更 CSS 樣式組合

    - <link href="{CLIENT PROJECT ASSEMBLY NAME}.styles.css" rel="stylesheet">
    + <link href="{SERVER PROJECT ASSEMBLY NAME}.styles.css" rel="stylesheet">
    

    上面程式碼中的預留位置:

    • {CLIENT PROJECT ASSEMBLY NAME}:用戶端專案組件名稱。 範例: BlazorSample.Client
    • {SERVER PROJECT ASSEMBLY NAME}:伺服器專案組件名稱。 範例: BlazorSample.Server

    找到下列 <div>...</div> HTML 標記:

    - <div id="app">
    -     ...
    - </div>
    

    使用互動式 WebAssembly 轉譯模式 (停用預先轉譯) 將上面的 <div>...</div> HTML 標記取代為 Routes 元件:

    <Routes @rendermode="new InteractiveWebAssemblyRenderMode(prerender: false)" />
    

    blazor.webassembly.js 指令碼更新為 blazor.web.js:

    - <script src="_framework/blazor.webassembly.js"></script>
    + <script src="_framework/blazor.web.js"></script>
    
  6. 開啟 .Client 專案的配置檔案 (.Client/Shared/MainLayout.razor),並新增具有網站預設標題 ({TITLE} 預留位置) 的 PageTitle 元件:

    <PageTitle>{TITLE}</PageTitle>
    

    注意

    其他配置檔案應該也會收到具有預設網站標題的 PageTitle 元件。

    如需詳細資訊,請參閱在 ASP.NET Core Blazor 應用程式中控制標題內容 (部分機器翻譯)。

  7. .Client/Program.cs 移除下列行:

    - builder.RootComponents.Add<App>("#app");
    - builder.RootComponents.Add<HeadOutlet>("head::after");
    
  8. 更新 .Server/Program.cs

    將 Razor 元件和互動式 WebAssembly 元件服務新增至專案。 透過對 AddInteractiveWebAssemblyComponents 的鏈結呼叫來呼叫 AddRazorComponents。 呼叫 AddRazorComponents 預設會新增防偽服務 (AddAntiforgery)。

    builder.Services.AddRazorComponents()
        .AddInteractiveWebAssemblyComponents();
    

    防偽中介軟體新增至要求處理管線。

    放置下列程式碼:

    • 在對 app.UseRouting 的呼叫之後。
    • 如果有對 app.UseRoutingapp.UseEndpoints 發出呼叫,則對 app.UseAntiforgery 的呼叫必須介於這兩者之間。
    • app.UseAntiforgery 的呼叫必須放置在對 app.UseAuthorization 的呼叫之後 (如果有的話)。
    • 無需新增防偽服務 (builder.Services.AddAntiforgery()),因為它們是由前面介紹過的 AddRazorComponents 自動新增的。
    app.UseAntiforgery();
    

    移除下列程式碼:

    - app.UseBlazorFrameworkFiles();
    

    移除下列程式碼:

    - app.MapFallbackToFile("index.html");
    

    將上一行取代為對 MapRazorComponents 的呼叫,提供 App 元件做為根元件類型,並將鏈結呼叫新增至 AddInteractiveWebAssemblyRenderModeAddAdditionalAssemblies

    app.MapRazorComponents<App>()
        .AddInteractiveWebAssemblyRenderMode()
        .AddAdditionalAssemblies(typeof({CLIENT APP NAMESPACE}._Imports).Assembly);
    

    在上述範例中,預留位置 {CLIENT APP NAMESPACE}.Client 專案的命名空間 (例如,HostedBlazorApp.Client)。

  9. .Server 專案執行解決方案:

    針對 Visual Studio,請確認 在執行應用程式時,已在 [方案總管] 中選取 .Server 專案。

    如果使用 .NET CLI,請從 .Server 專案的資料夾中執行專案。

更新服務和端點選項群組態

隨著 .NET 8 中 Blazor Web Apps 的發行,Blazor 服務和端點選項組態會隨著新 API 的引入而更新,以支援互動式元件服務和元件端點組態。

更新的組態指引出現在下列位置:

使用 Yarp 路由因應措施卸除Blazor Server

如果您先前遵循在累加移轉中使用 Yarp 啟用 ASP.NET Core Blazor Server 支援中的指引,將 Blazor Server Yarp 移轉至 .NET 6 或 .NET 7 的應用程式,您可以反轉遵循本文指引時採取的因應措施步驟。 使用 Yarp 的 Blazor Server 路由和深層連結可在 .NET 8 中正確運作。

移轉配置元件中的 CascadingValue 元件

階層式參數不會跨轉譯模式界限傳遞資料,而且配置會在其他互動式應用程式中以靜態方式呈現。 因此,尋求在互動式轉譯元件中使用階層式參數的應用程式將無法層疊配置中的值。

有以下兩種移轉方式:

如需詳細資訊,請參閱階層式值/參數和轉譯模式界限

移轉 BlazorEnableCompression MSBuild 屬性

對於停用壓縮並以 .NET 7 或更早版本為目標但使用 .NET 8 SDK 建置的 Blazor WebAssembly 應用程式,BlazorEnableCompression MSBuild 屬性已變更為 CompressionEnabled

<PropertyGroup>
-   <BlazorEnableCompression>false</BlazorEnableCompression>
+   <CompressionEnabled>false</CompressionEnabled>
</PropertyGroup>

使用 .NET CLI publish 命令時,請使用新的屬性:

dotnet publish -p:CompressionEnabled=false

如需詳細資訊,請參閱以下資源:

<CascadingAuthenticationState> 元件移轉至階層式驗證狀態服務

在 .NET 7 或更早版本中,CascadingAuthenticationState 元件會圍繞 UI 樹狀結構的某些部分 (例如 Blazor Router) 進行包裝,以提供階層式驗證狀態:

<CascadingAuthenticationState>
    <Router ...>
        ...
    </Router>
</CascadingAuthenticationState>

在 .NET 8 中,不要使用 CascadingAuthenticationState 元件:

- <CascadingAuthenticationState>
      <Router ...>
          ...
      </Router>
- </CascadingAuthenticationState>

而是透過呼叫 Program 檔中的 AddCascadingAuthenticationState 來將階層式驗證狀態服務新增至服務集合:

builder.Services.AddCascadingAuthenticationState();

如需詳細資訊,請參閱以下資源:

有關 HTTP 快取問題的新文章

我們已新增了一篇新文章,討論在主要版本之間升級 Blazor 應用程式時可能出現的一些常見 HTTP 快取問題,以及如何解決 HTTP 快取問題。

如需詳細資訊,請參閱在升級 ASP.NET Core Blazor 應用程式時避免 HTTP 快取問題 (英文)。

關於使用靜態伺服器端轉譯 (靜態 SSR) 的類別庫的新文章

我們已新增了一篇新文章,討論在 Razor 類庫 (RCL) 中使用靜態伺服器端轉譯 (靜態 SSR) 進行元件庫的撰寫。

如需詳細資訊,請參閱使用靜態伺服器端轉譯 (靜態 SSR) 的 ASP.NET Core Razor 類別庫 (RCL) (英文)。

從其他組件中探索元件

從 Blazor Server 應用程式移轉至 Blazor Web 應用程式時,如果應用程式使用其他組件 (例如元件類別庫) 中的可路由元件,請造訪 ASP.NET Core Blazor 路由傳送和導覽中的指引。

當參數從查詢字串中提供時卸除 [Parameter] 屬性

從查詢字串中提供參數時不再需要 [Parameter] 屬性:

- [Parameter]
  [SupplyParameterFromQuery]

Blazor Server 指令碼後援原則授權

在 .NET 7 中,Blazor Server 指令碼 (blazor.server.js) 是由靜態檔案中介軟體提供。 在 .NET 7 應用程式中,在對授權中介軟體 (UseAuthorization) 的呼叫之前,在要求處理管線中放置對靜態檔案中介軟體 (UseStaticFiles) 的呼叫足以為匿名使用者提供 Blazor 指令碼。

在 .NET 8 中,Blazor Server 指令碼是由自己的端點使用端點路由傳送來提供。 此變更是由 Fixed bug - Passing options to UseStaticFiles breaks Blazor Server (dotnet/aspnetcore #45897) 引入的。

考慮一個多租用戶的場景,其中:

  • 預設和後援原則的設定相同。
  • 租用戶是使用要求路徑中的第一個區段 (例如 tld.com/tenant-name/...) 解析的。
  • 對租用戶端點的要求會透過額外的驗證配置 (此配置會將額外的身分識別新增至要求主體) 進行驗證。
  • 後援授權原則具有透過額外身分識別檢查宣告的需求。

對 Blazor 指令碼檔 (blazor.server.js) 的要求是在 /_framework/blazor.server.js 提供 (該檔案在架構中進行硬編碼)。 對該檔案的要求不會透過租用戶的額外驗證配置進行驗證,但仍會受到後援原則的質疑,這會導致傳回未經授權的結果。

此問題正在針對 MapRazorComponents broken with FallbackPolicy RequireAuthenticatedUser (dotnet/aspnetcore 51836) 中的新架構功能進行評估,目前已計劃於 2024 年 11 月在 .NET 9 的發行中解決。 在那個日期之前,您可以使用下列三種方法中的任何一種方法來暫時解決此問題:

  • 不要使用後援原則。 在 _Imports.razor 檔案中套用 [Authorize] 屬性,以將其套用至應用程式的所有元件。 針對非 Blazor 端點,請明確使用 [Authorize]RequireAuthorization

  • [AllowAnonymous] 新增至 Program 檔案中的 /_framework/blazor.server.js 端點:

    app.MapBlazorHub().Add(endpointBuilder =>
    {
        if (endpointBuilder is 
            RouteEndpointBuilder
            { 
                RoutePattern: { RawText: "/_framework/blazor.server.js" }
            })
        {
            endpointBuilder.Metadata.Add(new AllowAnonymousAttribute());
        }
    });
    
  • 註冊一個自訂 AuthorizationHandler檢查 HttpContext 以允許 /_framework/blazor.server.js 檔案通過。

Docker

更新 Docker 映像

針對使用 Docker 的應用程式,更新 DockerfileFROM 陳述式和指令碼。 使用包含 ASP.NET Core 8.0 執行階段的基底映像。 請考慮 ASP.NET Core 7.0 和 8.0 之間的下列 docker pull 命令差異:

- docker pull mcr.microsoft.com/dotnet/aspnet:7.0
+ docker pull mcr.microsoft.com/dotnet/aspnet:8.0

更新 Docker 連接埠

在 .NET 容器映像中設定的預設 ASP.NET Core 連接埠已從 80 更新為 8080。

已新增了新的 ASPNETCORE_HTTP_PORTS 環境變數,作為 ASPNETCORE_URLS 的更簡單替代方案。

如需詳細資訊,請參閱

檢閱中斷性變更

如需從 .NET Core .NET 7.0 到 8.0 的中斷性變更,請參閱 .NET 8 中的中斷性變更,其中包括 ASP.NET CoreEntity Framework Core 章節。