本文介绍如何将 .NET 7 项目中的现有 ASP.NET Core 更新为 .NET 8。
Prerequisites
具有 ASP.NET 和 Web 开发工作负载的 Visual Studio 2022。
更新 global.json 中的 .NET SDK 版本
如果依赖 global.json 文件以特定 .NET SDK 版本为目标,请将 version 属性更新为已安装的 .NET 8 SDK 版本。 例如:
{
"sdk": {
- "version": "7.0.100"
+ "version": "8.0.100"
}
}
更新目标框架
将项目文件的 目标框架标识符 (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 Server更新应用
- 采用所有 Blazor Web App 约定
- 将 Blazor Server 应用转换为 Blazor Web App
- Blazor WebAssembly更新应用
- 将托管 Blazor WebAssembly 应用转换为 Blazor Web App
- 更新服务和终结点选项配置
- 使用 Yarp 路由解决方法删除Blazor Server
-
迁移布局组件中的部分
CascadingValue -
BlazorEnableCompression迁移 MSBuild 属性 -
将
<CascadingAuthenticationState>组件迁移到级联身份验证状态服务 - 新文章:迁移过程中的 HTTP 缓存问题
- 新文章:有关具有静态服务器端呈现的类库的新文章(静态 SSR)
- 发现来自其他程序集的组件
-
从查询字符串提供参数时删除
[Parameter]属性 - Blazor Server 脚本回退策略授权
有关向 ASP.NET Core 应用添加 Blazor 支持的指导,请参阅 将 ASP.NET Core Razor 组件与 MVC 或 Razor Pages 集成。
更新 Blazor Server 应用
建议在 .NET 8 中使用 Blazor Web App,但支持 Blazor Server。 若要继续在 .NET 8 中使用 Blazor Server,请按照本文前三个部分中的指导进行操作:
为 Blazor 引入的新 Blazor Web App 功能不适用于已更新为在 .NET 8 中运行的 Blazor Server 应用。 如果你想要采用新的 .NET 8 Blazor 功能,请按照以下任一部分中的指导进行操作:
采用所有 Blazor Web App 约定
若要选择采用所有新的 Blazor Web App 约定,建议执行以下过程:
- 从 Blazor Web App 项目模板创建新应用。 有关详细信息,请参阅 ASP.NET Core Blazor的工具。
- 将应用的组件和代码移动到新的 Blazor Web App,进行修改以采用新功能。
- 更新 Blazor Web App 的布局和样式。
.NET 8 中的新增功能在 .NET 8 ASP.NET Core 中的新增功能中进行了介绍。 从 .NET 6 或更早版本更新应用时,请参阅中间版本的迁移和发行说明(最新功能文章)。
将 Blazor Server 应用转换为 Blazor Web App
.NET 8 支持 Blazor Server 应用,无需进行任何代码更改。 使用以下指南将应用转换为 Blazor Server 等效的 .NET 8 Blazor Web App,使 所有新的 .NET 8 功能 都可用。
Important
本部分重点介绍将 .NET 7 Blazor Server 应用转换为 .NET 8 Blazor Web App 所需的最小更改。 若要采用所有新 Blazor Web App 约定,请按照“ 采用所有 Blazor Web App 约定 ”部分中的指导进行作。
按照本文前三部分中的指导进行操作:
将
App组件 (App.razor) 的内容移动到添加到项目的根文件夹中的新Routes组件文件 (Routes.razor)。 将空App.razor文件保留在项目的根文件夹中的应用中。向
_Imports.razor文件添加一个条目,使速记呈现模式可供应用使用:@using static Microsoft.AspNetCore.Components.Web.RenderMode将
_Host页 (Pages/_Host.cshtml) 中的内容移动到空的App.razor文件中。 继续对App组件进行以下更改。Note
在下面的示例中,项目的命名空间为
BlazorServerApp。 调整命名空间以匹配项目。从文件的顶部删除以下行:
- @page "/" - @using Microsoft.AspNetCore.Components.Web - @namespace BlazorServerApp.Pages - @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers将前面的行替换为用于注入 IHostEnvironment 实例的行:
@inject IHostEnvironment Env从
~标记的href中删除波形符 (<base>),并替换为应用的基本路径:- <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" />Note
上述配置假定应用的组件采用交互式服务器呈现。 有关详细信息,包括如何采用静态服务器端呈现(SSR),请参阅 ASP.NET 核心 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>删除
Pages/_Host.cshtml文件,更新
Program.cs:Note
在下面的示例中,项目的命名空间为
BlazorServerApp。 调整命名空间以匹配项目。将
using语句添加到项目命名空间的文件顶部:using BlazorServerApp;将 AddServerSideBlazor 替换为 AddRazorComponents 和对 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();在添加 HTTPS 重定向中间件的行之后,将 Antiforgery 中间件 添加到请求处理管道(
app.UseHttpsRedirection):app.UseAntiforgery();上述调用
app.UseAntiforgery必须在调用(如果存在)和app.UseAuthenticationapp.UseAuthorization之后进行。 无需显式添加反forgery 服务(builder.Services.AddAntiforgery),因为它们是自动添加的 AddRazorComponents,前面已涵盖。如果 Blazor Server 应用配置为禁用预呈现,则可以继续禁用更新的应用预呈现。 在
App组件中,更改分配给@rendermode和 Razor 组件的 HeadOutletRoutes指令属性的值。更改
@rendermode和 HeadOutlet 组件的Routes指令属性的值以禁用预呈现:- @rendermode="InteractiveServer" + @rendermode="new InteractiveServerRenderMode(prerender: false)"有关详细信息,请参阅 ASP.NET 核心 Blazor 呈现模式。
更新 Blazor WebAssembly 应用
按照本文前三部分中的指导进行操作:
对采用延迟程序集加载的应用程序,请在应用程序的实现中将文件扩展名从.dll更改为.wasm,以体现Blazor WebAssembly对Webcil程序集打包的采用。
在 .NET 8 发布之前, ASP.NET Core 托管 Blazor WebAssembly 应用的部署布局 指南介绍了阻止客户端下载和执行多部分捆绑方法的 DLL 的环境。 在 .NET 8 或更高版本中,Blazor 使用 Webcil 文件格式解决此问题。 .NET 8 或更高版本中的 应用不支持使用 Blazor文章中所述的试验 NuGet 包进行多部分捆绑。 如果想要继续在 .NET 8 或更高版本应用中使用多部分捆绑包,则可以按照本文中的指导创建自己的多部分捆绑 NuGet 包,但 Microsoft 不支持该包。
将托管的 Blazor WebAssembly 应用转换为 Blazor Web App
.NET 8 支持 Blazor WebAssembly 应用,无需进行任何代码更改。 使用以下指南将 ASP.NET Core 托管 Blazor WebAssembly 的应用转换为等效的 .NET 8 Blazor Web App,使所有 新的 .NET 8 功能 都可用。
Important
本部分重点介绍将 .NET 7 ASP.NET Core 托管的 Blazor WebAssembly 应用转换为 .NET 8 Blazor Web App 所需的最小更改。 若要采用所有新 Blazor Web App 约定,请按照“ 采用所有 Blazor Web App 约定 ”部分中的指导进行作。
按照本文前三部分中的指导进行操作:
Important
使用前面的指导更新解决方案的
.Client、.Server和.Shared项目。在
.Client项目文件 (.csproj) 中,添加以下 MS Build 属性:<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile> <StaticWebAssetProjectMode>Default</StaticWebAssetProjectMode>另外,请从
.Client项目文件中移除Microsoft.AspNetCore.Components.WebAssembly.DevServer包引用:- <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer"... />将文件内容从
.Client/wwwroot/index.html文件移动到在App项目的根目录中创建的新App.razor组件文件 (.Server)。 移动文件的内容后,删除index.html文件。将
App.razor项目中的.Client重命名为Routes.razor。在
Routes.razor中,将AppAssembly属性的值更新为typeof(Program).Assembly。在
.Client项目中,向_Imports.razor文件添加一个条目,使速记呈现模式可供应用使用:@using static Microsoft.AspNetCore.Components.Web.RenderMode创建
.Client项目的_Imports.razor文件的副本,并将其添加到.Server项目中。对
App.razor文件进行以下更改:将网站的默认网站标题 (
<title>...</title>) 替换为 HeadOutlet 组件。 记下该网站标题供以后使用,并移除标题标签和标题:- <title>...</title>在移除标题的位置,放置一个分配交互式 WebAssembly 呈现模式(禁用预呈现)的 HeadOutlet 组件:
<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>-
打开
.Client项目的布局文件 (.Client/Shared/MainLayout.razor),并添加具有网站默认标题(PageTitle 占位符)的{TITLE}组件:<PageTitle>{TITLE}</PageTitle>从
.Client/Program.cs中删除以下行:- builder.RootComponents.Add<App>("#app"); - builder.RootComponents.Add<HeadOutlet>("head::after");更新
.Server/Program.cs:向项目添加 Razor 组件和交互式 WebAssembly 组件服务。 通过对 AddRazorComponents 的链式调用来调用 AddInteractiveWebAssemblyComponents。 默认情况下,调用 AddRazorComponents 会添加防伪服务 (AddAntiforgery)。
builder.Services.AddRazorComponents() .AddInteractiveWebAssemblyComponents();将 Antiforgery 中间件 添加到请求处理管道。
在调用
app.UseHttpsRedirection后放置以下行。app.UseAntiforgery调用必须在调用后(如果存在)和app.UseAuthenticationapp.UseAuthorization。 无需显式添加反forgery 服务(builder.Services.AddAntiforgery),因为它们是自动添加的 AddRazorComponents,前面已涵盖。app.UseAntiforgery();删除以下行:
- app.UseBlazorFrameworkFiles();删除以下行:
- app.MapFallbackToFile("index.html");将前面的行替换为对 MapRazorComponents 的调用,将
App组件作为根组件类型提供,并向 AddInteractiveWebAssemblyRenderMode 和 AddAdditionalAssemblies 添加链式调用:app.MapRazorComponents<App>() .AddInteractiveWebAssemblyRenderMode() .AddAdditionalAssemblies(typeof({CLIENT APP NAMESPACE}._Imports).Assembly);在前面的示例中,
{CLIENT APP NAMESPACE}占位符是.Client项目的命名空间(例如,HostedBlazorApp.Client)。从
.Server项目运行解决方案:对于 Visual Studio,确认在运行应用时在
.Server中选择了 项目。如果使用 .NET CLI,请从
.Server项目的文件夹运行项目。
更新服务和终结点选项配置
随着 .NET 8 中 Blazor Web App 的发布,Blazor 服务和终结点选项配置已更新,引入了用于交互式组件服务和组件终结点配置的新 API。
更新的配置指南出现在以下位置:
- 设置和读取应用的环境:包含更新的指南,尤其是在标题为在Blazor Web App中客户端读取环境的部分。
- 服务器端电路处理程序选项:涵盖新的 Blazor电路SignalR 和集线器选项配置。
- 从 JavaScript 呈现Razor组件:介绍动态组件注册。RegisterForJavaScript
-
Blazor自定义元素:Blazor Web App注册:涵盖根组件自定义元素注册。
RegisterCustomElement - Blazor WebAssembly资产前缀:涉及控制指示资产前缀的路径字符串Blazor WebAssembly。
- 临时重定向 URL 的有效期:涵盖对服务器端呈现发出的临时重定向 URL 的数据保护有效性的生存期控制。
- 详细错误:涵盖如何为 Razor 组件服务器端渲染启用详细错误。
- 预呈现配置:默认为 Blazor Web Apps 启用预呈现。 如果存在需要应用禁用预呈现的特殊情况,请单击此链接获取有关如何禁用预呈现的指南。
- 表单绑定选项:涵盖表单绑定选项配置。
使用 Yarp 路由解决方法删除 Blazor Server
如果您之前遵循了文章“
在布局组件中迁移CascadingValue组件
级联参数不会跨呈现模式边界传递数据,并且布局以静态方式呈现在其他交互式应用中。 因此,寻求在交互式呈现的组件中使用级联参数的应用将无法级联布局中的值。
迁移的两种方法为:
- (推荐)将状态作为根级级联值传递。 有关详细信息,请参阅有关 根级级级联值 和 包含通知的根级级联值的指南。
- 使用
Routes组件将路由器包装在CascadingValue组件中,并使Routes组件以交互方式呈现。 有关示例,请参阅CascadingValue组件。
有关详细信息,请参阅 级联值/参数和呈现模式边界。
迁移BlazorEnableCompression MSBuild 属性
对于禁用压缩和面向 .NET 7 或更早版本但使用 .NET 8 SDK 生成的Blazor WebAssembly应用,BlazorEnableCompression MSBuild 属性已更改为CompressionEnabled:
<PropertyGroup>
- <BlazorEnableCompression>false</BlazorEnableCompression>
+ <CompressionEnabled>false</CompressionEnabled>
</PropertyGroup>
使用 .NET CLI 发布命令时,请使用新属性:
dotnet publish -p:CompressionEnabled=false
有关详细信息,请参阅以下资源:
将 <CascadingAuthenticationState> 组件迁移到级联身份验证状态服务
在 .NET 7 或更早版本中,组件 CascadingAuthenticationState 包装在 UI 树的某些部分(例如围绕路由器周围 Blazor)以提供级联身份验证状态:
<CascadingAuthenticationState>
<Router ...>
...
</Router>
</CascadingAuthenticationState>
在 .NET 8 中,请勿使用 CascadingAuthenticationState 组件:
- <CascadingAuthenticationState>
<Router ...>
...
</Router>
- </CascadingAuthenticationState>
而是通过在 AddCascadingAuthenticationState 文件中调用 Program,将级联身份验证状态服务添加到服务集合:
builder.Services.AddCascadingAuthenticationState();
有关详细信息,请参阅以下资源:
- ASP.NET 核心 Blazor 身份验证和授权 文章
- ASP.NET 核心 Blazor 身份验证和授权
有关 HTTP 缓存问题的新文章
我们添加了一篇新文章,讨论在跨主要版本升级 Blazor 应用时可能发生的一些常见 HTTP 缓存问题,以及如何解决 HTTP 缓存问题。
有关详细信息,请参阅 在升级 ASP.NET Core Blazor 应用时避免 HTTP 缓存问题。
关于使用静态服务器端呈现(静态 SSR)的类库的新文章
我们新增了一篇文章,其中讨论了使用静态服务器端呈现(静态 SSR)的 Razor 类库 (RCL) 中的组件库创作。
有关详细信息,请参阅 ASP.NET 具有静态服务器端呈现(静态 SSR)的核心 Razor 类库(RCL)。
从其他程序集中发现组件
从应用迁移到 a Blazor ServerBlazor Web App时,如果应用使用其他程序集(例如组件类库)中的可路由组件,则访问 ASP.NET 核心 Blazor 路由和导航 中的指南。
从查询字符串提供参数时删除 [Parameter] 属性
从查询字符串提供参数时,不再需要 [Parameter] 属性:
- [Parameter]
[SupplyParameterFromQuery]
Blazor Server 脚本回退策略授权
在 .NET 7 中,脚本 Blazor Server(blazor.server.js)由静态文件中间件托管。 在 .NET 7 应用中,只需在请求处理管道中将静态文件中间件(UseStaticFiles)的调用放在授权中间件(UseAuthorization)之前,就可以为匿名用户提供 Blazor 脚本。
在 .NET 8 中,Blazor Server脚本通过终结点路由在其专属终结点上提供服务。 此更改是通过修复 bug 引入的 - 将选项传递给 UseStaticFiles 中断Blazor Server(dotnet/aspnetcore#45897)。
请考虑多租户场景,其中:
- 默认策略和回退策略的设置方式都相同。
- 使用请求路径中的第一段(例如
tld.com/tenant-name/...)解析租户。 - 向租户终结点发出的请求通过其他身份验证方案进行身份验证,该方案向请求主体添加其他标识。
- 回退授权策略要求通过其他标识检查声明。
针对 Blazor 脚本文件 (blazor.server.js) 的请求在 /_framework/blazor.server.js 中提供,此服务器在框架中进行了硬编码。 对文件的请求不经过租户其他身份验证方案的验证,但仍会被备用策略验证,从而导致返回未经授权的结果。
此问题正在评估,以用于MapRazorComponents 中因 FallbackPolicy RequireAuthenticatedUser (dotnet/aspnetcore 51836)而中断的新框架功能,这项功能目前计划于 2024 年 11 月发布.NET 9。 在此之前,可以使用以下三种方法中的任何一种方法解决此问题:
不使用回退策略。 在
[Authorize]文件中应用_Imports.razor属性,将其应用于应用的所有组件。 对于非 blazor 终结点,显式使用[Authorize]或RequireAuthorization。将
[AllowAnonymous]添加到/_framework/blazor.server.js文件中的Program终结点:app.MapBlazorHub().Add(endpointBuilder => { if (endpointBuilder is RouteEndpointBuilder { RoutePattern: { RawText: "/_framework/blazor.server.js" } }) { endpointBuilder.Metadata.Add(new AllowAnonymousAttribute()); } });
Docker
更新 Docker 映像
对于使用 Docker 的应用,请更新 Dockerfile 语句和脚本FROM。 使用包含 .NET 8 运行时的基本映像。 请考虑在 .NET 7 和 .NET 8 中 ASP.NET Core 之间的以下命令 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 中重大更改 的文章查找在将应用升级到较新版本 .NET 时可能应用的中断性变更。