本文介绍如何将 .NET 7 项目中的现有 ASP.NET Core 更新为 .NET 8。
先决条件
具有 ASP.NET 和 Web 开发工作负载的 Visual Studio 2022。
更新 global.json
中的 .NET SDK 版本
如果依赖 global.json
文件以特定 .NET Core 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 功能 都可用。
重要
本部分重点介绍将 .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
组件进行以下更改。注意
在下面的示例中,项目的命名空间为
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" />
注意
上述配置假定应用的组件采用交互式服务器呈现。 有关详细信息,包括如何采用静态服务器端呈现(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
:注意
在下面的示例中,项目的命名空间为
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.UseAuthentication
app.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 功能 都可用。
重要
本部分重点介绍将 .NET 7 ASP.NET Core 托管的 Blazor WebAssembly 应用转换为 .NET 8 Blazor Web App 所需的最小更改。 若要采用所有新 Blazor Web App 约定,请按照“ 采用所有 Blazor Web App 约定 ”部分中的指导进行作。
按照本文前三部分中的指导进行操作:
重要
使用前面的指导更新解决方案的
.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.UseAuthentication
app.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 7 到 .NET 8 的重大更改,请参阅 .NET 8 中的重大更改,其中包括 ASP.NET Core 和 Entity Framework Core 部分。