从 ASP.NET Core 2.2 迁移到 3.0
作者:Scott Addie 和 Rick Anderson
本文介绍如何将现有 ASP.NET Core 2.2 项目更新为 ASP.NET Core 3.0。 创建新 3.0 ASP.NET Core 可能有助于:
- 与 ASP.NET Core 2.2 代码进行比较。
- 将相关更改复制到 ASP.NET Core 3.0 项目。
先决条件
- Visual Studio 2019 与 ASP.NET 和 Web 开发工作负载
- .NET Core 3.0 SDK
在 global.json 中更新 .NET Core SDK 版本
如果解决方案依靠 global.json 文件来面向特定的 .NET Core SDK 版本,请将其 version
属性更新为计算机上安装的 3.0 版本:
{
"sdk": {
"version": "3.0.100"
}
}
更新项目文件
更新目标框架
ASP.NET Core 3.0 以及更高版本只能在 .NET Core 中运行。 将目标框架名字对象 (TFM) 设置为 netcoreapp3.0
:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
</Project>
删除已过时的包引用
不会为 ASP.NET Core 3.0 生成大量 NuGet 包。 应从项目文件中删除此类包引用。 请考虑以下适用于 ASP.NET Core 2.2 Web 应用的项目文件:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App"/>
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
</ItemGroup>
</Project>
针对 ASP.NET Core 3.0 更新后的项目文件:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
</Project>
更新后的 ASP.NET Core 3.0 项目文件:
在
<PropertyGroup>
中:- 将 TFM 更新为
netcoreapp3.0
- 删除了
<AspNetCoreHostingModel>
元素。 有关详细信息,请参阅本文档中的进程内托管模型。
- 将 TFM 更新为
在
<ItemGroup>
中:- 删除了
Microsoft.AspNetCore.App
。 有关详细信息,请参阅本文档中的框架引用。 - 删除了
Microsoft.AspNetCore.Razor.Design
,它处于以下不再生成的包列表中。
- 删除了
若要查看不再生成的包的完整列表,请选择以下展开列表:
单击可展开不再生成的包列表
- Microsoft.AspNetCore
- Microsoft.AspNetCore.All
- Microsoft.AspNetCore.App
- Microsoft.AspNetCore.Antiforgery
- Microsoft.AspNetCore.Authentication
- Microsoft.AspNetCore.Authentication.Abstractions
- Microsoft.AspNetCore.Authentication.Cookies
- Microsoft.AspNetCore.Authentication.Core
- Microsoft.AspNetCore.Authentication.OAuth
- Microsoft.AspNetCore.Authorization.Policy
- Microsoft.AspNetCore.CookiePolicy
- Microsoft.AspNetCore.Cors
- Microsoft.AspNetCore.Diagnostics
- Microsoft.AspNetCore.Diagnostics.HealthChecks
- Microsoft.AspNetCore.HostFiltering
- Microsoft.AspNetCore.Hosting
- Microsoft.AspNetCore.Hosting.Abstractions
- Microsoft.AspNetCore.Hosting.Server.Abstractions
- Microsoft.AspNetCore.Http
- Microsoft.AspNetCore.Http.Abstractions
- Microsoft.AspNetCore.Http.Connections
- Microsoft.AspNetCore.Http.Extensions
- Microsoft.AspNetCore.HttpOverrides
- Microsoft.AspNetCore.HttpsPolicy
- Microsoft.AspNetCore.Identity
- Microsoft.AspNetCore.Localization
- Microsoft.AspNetCore.Localization.Routing
- Microsoft.AspNetCore.Mvc
- Microsoft.AspNetCore.Mvc.Abstractions
- Microsoft.AspNetCore.Mvc.Analyzers
- Microsoft.AspNetCore.Mvc.ApiExplorer
- Microsoft.AspNetCore.Mvc.Api.Analyzers
- Microsoft.AspNetCore.Mvc.Core
- Microsoft.AspNetCore.Mvc.Cors
- Microsoft.AspNetCore.Mvc.DataAnnotations
- Microsoft.AspNetCore.Mvc.Formatters.Json
- Microsoft.AspNetCore.Mvc.Formatters.Xml
- Microsoft.AspNetCore.Mvc.Localization
- Microsoft.AspNetCore.Mvc.Razor
- Microsoft.AspNetCore.Mvc.Razor.ViewCompilation
- Microsoft.AspNetCore.Mvc.RazorPages
- Microsoft.AspNetCore.Mvc.TagHelpers
- Microsoft.AspNetCore.Mvc.ViewFeatures
- Microsoft.AspNetCore.Razor
- Microsoft.AspNetCore.Razor.Runtime
- Microsoft.AspNetCore.Razor.Design
- Microsoft.AspNetCore.ResponseCaching
- Microsoft.AspNetCore.ResponseCaching.Abstractions
- Microsoft.AspNetCore.ResponseCompression
- Microsoft.AspNetCore.Rewrite
- Microsoft.AspNetCore.Routing
- Microsoft.AspNetCore.Routing.Abstractions
- Microsoft.AspNetCore.Server.HttpSys
- Microsoft.AspNetCore.Server.IIS
- Microsoft.AspNetCore.Server.IISIntegration
- Microsoft.AspNetCore.Server.Kestrel
- Microsoft.AspNetCore.Server.Kestrel.Core
- Microsoft.AspNetCore.Server.Kestrel.Https
- Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions
- Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
- Microsoft.AspNetCore.Session
- Microsoft.AspNetCore.SignalR
- Microsoft.AspNetCore.SignalR.Core
- Microsoft.AspNetCore.StaticFiles
- Microsoft.AspNetCore.WebSockets
- Microsoft.AspNetCore.WebUtilities
- Microsoft.Net.Http.Headers
查看中断性变更
框架引用
通过上面列出的包提供的 ASP.NET Core 功能作为 Microsoft.AspNetCore.App
共享框架的一部分提供。 共享框架是安装在计算机上并包括运行时组件和目标包的一组程序集(.dll 文件)。 有关详细信息,请参阅共享框架。
面向
Microsoft.NET.Sdk.Web
SDK 的项目隐式引用Microsoft.AspNetCore.App
框架。对于这些项目,不需要其他引用:
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>netcoreapp3.0</TargetFramework> </PropertyGroup> ... </Project>
面向
Microsoft.NET.Sdk
或Microsoft.NET.Sdk.Razor
SDK 的项目应将显式FrameworkReference
添加到Microsoft.AspNetCore.App
:<Project Sdk="Microsoft.NET.Sdk.Razor"> <PropertyGroup> <TargetFramework>netcoreapp3.0</TargetFramework> </PropertyGroup> <ItemGroup> <FrameworkReference Include="Microsoft.AspNetCore.App" /> </ItemGroup> ... </Project>
使用 Docker 的依赖于框架的生成
如果控制台应用使用的包依赖于 ASP.NET Core 共享框架,则这些应用的依赖于框架的生成可能会导致以下运行时错误:
It was not possible to find any compatible framework version
The specified framework 'Microsoft.AspNetCore.App', version '3.0.0' was not found.
- No frameworks were found.
Microsoft.AspNetCore.App
是包含 ASP.NET Core 运行时的共享框架,仅在 dotnet/core/aspnet
Docker 映像中存在。 3.0 SDK 不包括在共享框架中提供的库的重复副本,从而减小使用 ASP.NET Core 的依赖于框架的生成大小。 这可能会节省多达 18 MB,但要求存在/安装 ASP.NET Core 运行时才能运行应用。
若要确定应用是否依赖于(直接或间接)ASP.NET Core 共享框架,请检查在应用生成/发布期间生成的 runtimeconfig.json
文件。 以下 JSON 文件显示对 ASP.NET Core 共享框架的依赖关系:
{
"runtimeOptions": {
"tfm": "netcoreapp3.0",
"framework": {
"name": "Microsoft.AspNetCore.App",
"version": "3.0.0"
},
"configProperties": {
"System.GC.Server": true
}
}
}
如果应用使用 Docker,请使用包含 ASP.NET Core 3.0 的基础映像。 例如,docker pull mcr.microsoft.com/dotnet/core/aspnet:3.0
。
为删除的程序集添加包引用
ASP.NET Core 3.0 删除了一些以前作为 Microsoft.AspNetCore.App
包引用一部分的程序集。 若要直观显示已删除的程序集,请比较两个共享框架文件夹。 例如,版本 2.2.7 与 3.0.0 的比较:
若要继续使用已删除程序集提供的功能,请引用对应包的 3.0 版本:
使用“个人用户帐户”的模板生成的 Web 应用需要添加以下包:
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>netcoreapp3.0</TargetFramework> <UserSecretsId>My-secret</UserSecretsId> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="3.0.0" /> <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.0.0" /> <PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="3.0.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.0.0" /> </ItemGroup> </Project>
-
有关引用特定于数据库提供程序的包的详细信息,请参阅数据库提供程序。
Identity UI
可通过引用 Microsoft.AspNetCore.Identity.UI 包来添加对 Identity UI 的支持。
SPA 服务
身份验证:第三方身份验证流支持作为 NuGet 包提供:
- Facebook OAuth (Microsoft.AspNetCore.Authentication.Facebook)
- Google OAuth (Microsoft.AspNetCore.Authentication.Google)
- Microsoft 帐户身份验证 (Microsoft.AspNetCore.Authentication.MicrosoftAccount)
- OpenID Connect 身份验证 (Microsoft.AspNetCore.Authentication.OpenIdConnect)
- OpenID Connect 持有者令牌 (Microsoft.AspNetCore.Authentication.JwtBearer)
- Twitter OAuth (Microsoft.AspNetCore.Authentication.Twitter)
- WsFederation 身份验证 (Microsoft.AspNetCore.Authentication.WsFederation)
适用于
System.Net.HttpClient
的格式设置和内容协商支持:Microsoft.AspNet.WebApi.Client NuGet 包通过ReadAsAsync
和PostJsonAsync
等 API 向System.Net.HttpClient
提供了有用的扩展性。 但是,此包依赖的是Newtonsoft.Json
,而不是System.Text.Json
。 例如,这意味着将忽略JsonPropertyNameAttribute
(System.Text.Json
) 指定的序列化属性名称。 有一个较新的 NuGet 包,其中包含类似的扩展方法,但使用System.Text.Json
:System.Net.Http.Json.Razor 运行时编译:对 Razor 视图和页面运行时编译的支持现在是 Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation 的一部分。
MVC
Newtonsoft.Json
(Json.NET) 支持:对将 MVC 与Newtonsoft.Json
结合使用的支持现在是Microsoft.AspNetCore.Mvc.NewtonsoftJson
的一部分。
启动更改
下图显示了 ASP.NET Core 2.2 Razor Pages Web 应用中删除和更改的行:
在上图中,删除的代码显示为红色。 删除的代码未显示 cookie 选项代码,该代码在比较文件之前已删除。
下图显示了 ASP.NET Core 3.0 Razor Pages Web 应用中添加和更改的行:
在上图中,添加的代码显示为绿色。 有关以下更改的信息:
services.AddMvc
到services.AddRazorPages
,请参阅本文档中的 MVC 服务注册。CompatibilityVersion
请参阅 ASP.NET Core MVC 的兼容性版本。IHostingEnvironment
到IWebHostEnvironment
,请参阅此 GitHub 公告。app.UseAuthorization
已添加到模板,以显示必须添加订单授权中间件。 如果应用不使用授权,则可以安全地删除对app.UseAuthorization
的调用。app.UseEndpoints
,请查看本文档中的 Razor Pages 或迁移 Startup.Configure。
分析器支持
面向 Microsoft.NET.Sdk.Web
的项目会隐式引用以前作为 Microsoft.AspNetCore.Mvc.Analyzers 包的一部分提供的分析器。 无需其他引用即可启用这些内容。
如果应用使用以前通过 Microsoft.AspNetCore.Mvc.Api.Analyzers 包提供的 API 分析器,请编辑项目文件以引用作为 .NET Core Web SDK 的一部分提供的分析器:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<IncludeOpenAPIAnalyzers>true</IncludeOpenAPIAnalyzers>
</PropertyGroup>
...
</Project>
Razor 类库
为 MVC 提供 UI 组件的 Razor 类库项目必须在项目文件中设置 AddRazorSupportForMvc
属性:
<PropertyGroup>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
</PropertyGroup>
进程内托管模型
在 ASP.NET Core 3.0 或更高版本中,项目默认为进程内托管模型。 如果值为 InProcess
,可以选择在项目文件中删除 <AspNetCoreHostingModel>
属性。
Kestrel
Configuration
将 Kestrel 配置迁移到 ConfigureWebHostDefaults
(Program.cs
) 提供的 Web 主机生成器:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(serverOptions =>
{
// Set properties and call methods on options
})
.UseStartup<Startup>();
});
如果应用使用 ConfigureWebHost
而不是 ConfigureWebHostDefaults
手动创建主机,请对 Web 主机生成器调用 UseKestrel
:
public static void Main(string[] args)
{
var host = new HostBuilder()
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureWebHost(webBuilder =>
{
webBuilder.UseKestrel(serverOptions =>
{
// Set properties and call methods on options
})
.UseIISIntegration()
.UseStartup<Startup>();
})
.Build();
host.Run();
}
连接中间件替换连接适配器
连接适配器 (Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal.IConnectionAdapter
) 已从 Kestrel 中删除。 将连接适配器替换为连接中间件。 连接中间件类似于 ASP.NET Core 管道中的 HTTP 中间件,但适用于较低级别的连接。 HTTPS 和连接日志记录:
- 已从连接适配器移动到连接中间件。
- 这些扩展方法的工作方式与以前版本的 ASP.NET Core 中相同。
有关详细信息,请查看 Kestrel 文章的 ListenOptions.Protocols 部分中的 TlsFilterConnectionHandler 示例。
移动并公开的传输抽象
Kestrel 传输层已作为 Connections.Abstractions
中的公共接口公开。 作为这些更新的一部分:
Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions
和关联类型已删除。- NoDelay 已从 ListenOptions 移动到传输选项。
Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal.SchedulingMode
已从 KestrelServerOptions 中删除。
有关详细信息,请参阅以下 GitHub 资源:
- 客户端/服务器网络网络抽象 (dotnet/AspNetCore #10308)
- 实现新的 bedrock 侦听器抽象并在顶部重新放置 Kestrel (dotnet/AspNetCore #10321)
Kestrel 请求尾部标头
对于面向早期版本 ASP.NET Core 的应用:
- Kestrel 会将 HTTP/1.1 分块尾部标头添加到请求头集合中。
- 在读取请求正文直到结尾后,可使用尾部。
这会导致一些有关标头与尾部之间的多义性的问题,因此在 3.0 中,尾端已移动到新集合 (RequestTrailerExtensions
)。
HTTP/2 请求尾端:
- 在 ASP.NET Core 2.2 中不可用。
- 在 3.0 中作为
RequestTrailerExtensions
提供。
存在新的请求扩展方法以访问这些尾部。 与 HTTP/1.1 一样,在读取请求正文直到结尾后,可使用尾部。
对于 3.0 版,可使用以下 RequestTrailerExtensions
方法:
GetDeclaredTrailers
:获取列出了正文后应具有的尾部的请求Trailer
标头。SupportsTrailers
:指示请求是否支持接收尾部标头。CheckTrailersAvailable
:检查请求是否支持尾部以及是否可读取。 此检查不假定存在要读取的尾端。 即使此方法返回true
,也可能没有要读取的尾端。GetTrailer
:从响应获取请求的尾随标头。 请在调用GetTrailer
之前检查SupportsTrailers
,否则如果请求不支持尾随标头,则可能会发生 NotSupportedException。
有关详细信息,请参阅将请求尾部置于单独集合中 (dotnet/AspNetCore #10410)。
已禁用 AllowSynchronousIO
AllowSynchronousIO
可启用或禁用同步 I/O API,例如 HttpRequest.Body.Read
、HttpResponse.Body.Write
和 Stream.Flush
。 这些 API 是导致应用崩溃的线程不足的原因。 在 3.0 中,默认情况下禁用 AllowSynchronousIO
。 有关详细信息,请查看 Kestrel 文章中的“同步 I/O”部分。
如果需要同步 I/O,可以通过在所使用的服务器上配置 AllowSynchronousIO
选项(例如如果使用 Kestrel则在调用 ConfigureKestrel
时)来启用它。 请注意,Kestrel、HttpSys 和 TestServer 等服务器都有自己的 AllowSynchronousIO
选项,不会影响其他服务器。 可以使用 IHttpBodyControlFeature.AllowSynchronousIO
选项,基于请求为所有服务器启用同步 I/O:
var syncIOFeature = HttpContext.Features.Get<IHttpBodyControlFeature>();
if (syncIOFeature != null)
{
syncIOFeature.AllowSynchronousIO = true;
}
如果调用 Dispose 中同步 API 的 TextWriter 实现或其他流出现问题,请改为调用新的 DisposeAsync API。
有关详细信息,请参阅 [公告] AllowSynchronousIO 在所有服务器中已禁用 (dotnet/AspNetCore #7644)。
输出格式化程序缓冲
基于 Newtonsoft.Json、XmlSerializer 和 DataContractSerializer 输出格式化程序仅支持同步序列化。 为了使这些格式化程序可以处理服务器的 AllowSynchronousIO 限制,MVC 会在向磁盘写入之前缓冲这些格式化程序的输出。 作为缓冲的结果,当使用这些格式化程序响应时,MVC 会包含 Content-Length 标头。
System.Text.Json 支持异步序列化,因此基于 System.Text.Json
的格式化程序不会缓冲。 请考虑使用此格式化程序提高性能。
若要禁用缓冲,应用程序可以在启动中配置 SuppressOutputFormatterBuffering:
services.AddControllers(options => options.SuppressOutputFormatterBuffering = true)
请注意,如果还未配置 AllowSynchronousIO
,则这可能会导致应用程序引发运行时异常。
Microsoft.AspNetCore.Server.Kestrel.Https 程序集已删除
在 ASP.NET Core 2.1 中,Microsoft.AspNetCore.Server.Kestrel.Https.dll 的内容已移动到 Microsoft.AspNetCore.Server.Kestrel.Core.dll。 这是使用 TypeForwardedTo
属性的非中断性更新。 对于 3.0,空的 Microsoft.AspNetCore.Server.Kestrel.Https.dll 程序集和 NuGet 包已删除。
引用 Microsoft.AspNetCore.Server.Kestrel.Https 的库应将 ASP.NET Core 依赖项更新为 2.1 或更高版本。
面向 ASP.NET Core 2.1 或更高版本的应用和库应移除所有对 Microsoft.AspNetCore.Server.Kestrel.Https 包的直接引用。
Newtonsoft.Json (Json.NET) 支持
作为改进 ASP.NET Core 共享框架的工作的一部分,Newtonsoft.Json (Json.NET) 已从 ASP.NET Core 共享框架中删除。
ASP.NET Core 的默认 JSON 序列化程序现在是 System.Text.Json,它是 .NET Core 3.0 中的新增功能。 如果可能,请考虑使用 System.Text.Json
。 它是高性能的,不需要额外的库依赖项。 不过,由于 System.Text.Json
是新功能,它当前可能缺少应用所需的功能。 有关详细信息,请参阅如何从 Newtonsoft.Json 迁移到 System.Text.Json。
在 ASP.NET Core 3.0 SignalR 项目中使用 Newtonsoft.Json
安装 Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson NuGet 包。
在客户端上,将
AddNewtonsoftJsonProtocol
方法调用链接到HubConnectionBuilder
实例:new HubConnectionBuilder() .WithUrl("/chathub") .AddNewtonsoftJsonProtocol(...) .Build();
在服务器上,将
AddNewtonsoftJsonProtocol
方法调用链接到Startup.ConfigureServices
中的AddSignalR
方法调用:services.AddSignalR() .AddNewtonsoftJsonProtocol(...);
在 ASP.NET Core 3.0 MVC 项目中使用 Newtonsoft.Json
更新
Startup.ConfigureServices
以调用AddNewtonsoftJson
。services.AddMvc() .AddNewtonsoftJson();
AddNewtonsoftJson
与新的 MVC 服务注册方法兼容:AddRazorPages
AddControllersWithViews
AddControllers
services.AddControllers() .AddNewtonsoftJson();
Newtonsoft.Json
设置可以在对AddNewtonsoftJson
的调用中进行设置:services.AddMvc() .AddNewtonsoftJson(options => options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver());
注意:如果
AddNewtonsoftJson
方法不可用,请确保安装了Microsoft.AspNetCore.Mvc.NewtonsoftJson
包。 一种常见错误是安装 Newtonsoft.json 包而不是Microsoft.AspNetCore.Mvc.NewtonsoftJson
包。
有关更多信息,请参阅添加基于 Newtonsoft.Json 的 JSON 格式支持。
MVC 服务注册
ASP.NET Core 3.0 添加了用于在 Startup.ConfigureServices
中注册 MVC 方案的新选项。
提供了三种与 IServiceCollection
中的 MVC 方案相关的顶级扩展方法。 模板使用这些新方法而不是 AddMvc
。 但是,AddMvc
会继续保持以前版本中的行为方式。
下面的示例添加了对控制器和 API 相关功能的支持,但不支持视图或页面。 API 模板使用以下代码:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
}
下面的示例添加了对控制器、API 相关功能和视图的支持,但不支持页面。 Web 应用 (MVC) 模板使用以下代码:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
}
下面的示例添加了对 Razor Pages 的支持和最小控制器支持。 Web 应用模板使用以下代码:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
}
新方法还可以合并。 下面的示例等效于在 ASP.NET Core 2.2 中调用 AddMvc
:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddRazorPages();
}
路由启动代码
如果应用调用 UseMvc
或 UseSignalR
,请将应用迁移到终结点路由(如果可能)。 为了改进与以前版本的 MVC 的终结点路由兼容性,我们还原了 ASP.NET Core 2.2 引入的 URL 生成中的一些更改。 如果在 2.2 中使用终结点路由时遇到问题,请期待 ASP.NET Core 3.0 中的改进,不过有以下例外:
- 如果应用实现
IRouter
或继承自Route
,请使用 DynamicRouteValuesTransformer 作为替换。 - 如果应用在 MVC 内直接访问
RouteData.Routers
以分析 URL,则可以将此内容替换为使用 LinkParser.ParsePathByEndpointName。- 使用路由名称定义路由。
- 使用
LinkParser.ParsePathByEndpointName
并传入所需的路由名称。
终结点路由支持与 IRouter
相同的路由模式语法和路由模式创作功能。 终结点路由支持 IRouteConstraint
。 终结点路由支持 [Route]
、[HttpGet]
和其他 MVC 路由属性。
对于大多数应用程序,只有 Startup
需要更改。
迁移 Startup.Configure
一般建议:
添加
UseRouting
。如果应用调用
UseStaticFiles
,请将UseStaticFiles
置于UseRouting
前面。如果应用使用身份验证/授权功能(如
AuthorizePage
或[Authorize]
),请将对UseAuthentication
和UseAuthorization
的调用放置在UseRouting
和UseCors
后面,但是在UseEndpoints
前面:public void Configure(IApplicationBuilder app) { ... app.UseStaticFiles(); app.UseRouting(); app.UseCors(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
将
UseMvc
或UseSignalR
替换为UseEndpoints
。如果应用使用 CORS 方案(如
[EnableCors]
),请将对UseCors
的调用放置在使用 CORS 的任何其他中间件前面(例如,将UseCors
放置在UseAuthentication
、UseAuthorization
和UseEndpoints
前面)。将
IHostingEnvironment
替换为IWebHostEnvironment
,并为 Microsoft.AspNetCore.Hosting 命名空间添加using
语句。将
IApplicationLifetime
替换为 IHostApplicationLifetime(Microsoft.Extensions.Hosting 命名空间)。将
EnvironmentName
替换为 Environments(Microsoft.Extensions.Hosting 命名空间)。
下面的代码是典型 ASP.NET Core 2.2 应用中的 Startup.Configure
的示例:
public void Configure(IApplicationBuilder app)
{
...
app.UseStaticFiles();
app.UseAuthentication();
app.UseSignalR(hubs =>
{
hubs.MapHub<ChatHub>("/chat");
});
app.UseMvc(routes =>
{
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});
}
更新上面的 Startup.Configure
代码后:
public void Configure(IApplicationBuilder app)
{
...
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>("/chat");
endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
});
}
警告
对于大多数应用,对 UseAuthentication
、UseAuthorization
和 UseCors
的调用必须出现在对 UseRouting
和 UseEndpoints
的调用之间才能生效。
运行状况检查
运行状况检查将终结点路由与泛型主机一起使用。 在 Startup.Configure
内,使用终结点 URL 或相对路径在终结点生成器上调用 MapHealthChecks
:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
});
运行状况检查终结点可以:
- 指定一个或多个允许的主机/端口。
- 需要授权。
- 需要 CORS。
有关详细信息,请参阅 ASP.NET Core 中的运行状况检查。
安全性中间件指南
对授权和 CORS 的支持围绕中间件方法统一。 这样便可在这些方案中使用相同的中间件和功能。 此版本提供了更新的授权中间件,并增强了 CORS 中间件,使它可以理解 MVC 控制器使用的属性。
CORS
以前,CORS 可能难以配置。 提供中间件是为了在某些用例中使用,而 MVC 筛选器是为了在没有中间件的情况下,在其他用例中使用。 对于 ASP.NET Core 3.0,建议所有需要 CORS 的应用都将 CORS 中间件与终结点路由结合使用。 UseCors
可以通过默认策略提供,而 [EnableCors]
和 [DisableCors]
属性可用于在需要时替代默认策略。
在以下示例中:
- CORS 对于具有
default
命名策略的所有终结点都处于启用状态。 MyController
类通过[DisableCors]
属性禁用 CORS。
public void Configure(IApplicationBuilder app)
{
...
app.UseRouting();
app.UseCors("default");
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
[DisableCors]
public class MyController : ControllerBase
{
...
}
授权
在早期版本的 ASP.NET Core 中,通过 [Authorize]
属性提供授权支持。 授权中间件不可用。 在 ASP.NET Core 3.0 中,授权中间件是必需的。 建议 ASP.NET Core 授权中间件 (UseAuthorization
) 的放置位置是紧跟在 UseAuthentication
后面。 授权中间件也可以使用可替代的默认策略进行配置。
在 ASP.NET Core 3.0 或更高版本中,UseAuthorization
在 Startup.Configure
中进行调用,下面的 HomeController
需要已登录用户:
public void Configure(IApplicationBuilder app)
{
...
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
public class HomeController : Controller
{
[Authorize]
public IActionResult BuyWidgets()
{
...
}
}
使用终结点路由时,建议不要配置 AuthorizeFilter,而是依赖授权中间件。 如果应用在 MVC 中使用 AuthorizeFilter
作为全局筛选器,则建议重构代码,以便在对 AddAuthorization
的调用中提供策略。
DefaultPolicy
在开始时便配置为需要身份验证,因此无需进行其他配置。 在下面的示例中,MVC 终结点标记为 RequireAuthorization
,以便所有请求都必须基于 DefaultPolicy
进行授权。 但是由于 [AllowAnonymous]
,HomeController
允许在用户未登录应用的情况下进行访问:
public void Configure(IApplicationBuilder app)
{
...
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute().RequireAuthorization();
});
}
[AllowAnonymous]
public class HomeController : Controller
{
...
}
对特定终结点的授权
也可以为特定的终结点类配置授权。 下面的代码示例将配置可全局 AuthorizeFilter
的 MVC 应用转换具有需要授权的特定策略的应用:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
static readonly string _RequireAuthenticatedUserPolicy =
"RequireAuthenticatedUserPolicy";
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>(
options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
// Pre 3.0:
// services.AddMvc(options => options.Filters.Add(new AuthorizeFilter(...));
services.AddControllersWithViews();
services.AddRazorPages();
services.AddAuthorization(o => o.AddPolicy(_RequireAuthenticatedUserPolicy,
builder => builder.RequireAuthenticatedUser()));
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute()
.RequireAuthorization(_RequireAuthenticatedUserPolicy);
endpoints.MapRazorPages();
});
}
}
也可以自定义策略。 DefaultPolicy
配置为需要身份验证:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>(
options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddControllersWithViews();
services.AddRazorPages();
services.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute().RequireAuthorization();
endpoints.MapRazorPages();
});
}
}
[AllowAnonymous]
public class HomeController : Controller
{
或者,可以通过配置 FallbackPolicy
,将所有终结点配置为在没有 [Authorize]
或 RequireAuthorization
的情况下要求授权。 FallbackPolicy
与 DefaultPolicy
不同。 DefaultPolicy
由 [Authorize]
或 RequireAuthorization
触发,而 FallbackPolicy
在未设置其他策略时触发。 FallbackPolicy
最初配置为允许未经授权进行请求。
下面的示例与上面的 DefaultPolicy
示例相同,但使用 FallbackPolicy
以便在所有终结点上始终需要身份验证(在指定 [AllowAnonymous]
时除外):
public void ConfigureServices(IServiceCollection services)
{
...
services.AddAuthorization(options =>
{
options.FallbackPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
});
}
public void Configure(IApplicationBuilder app)
{
...
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
[AllowAnonymous]
public class HomeController : Controller
{
...
}
中间件的授权可在框架不了解授权的任何特定信息的情况下正常工作。 例如,运行状况检查不了解授权的特定信息,但运行状况检查可以具有由中间件应用的可配置授权策略。
此外,每个终结点都可以自定义其授权要求。 在下面的示例中,UseAuthorization
使用 DefaultPolicy
处理授权,但是 /healthz
运行状况检查终结点需要 admin
用户:
public void Configure(IApplicationBuilder app)
{
...
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints
.MapHealthChecks("/healthz")
.RequireAuthorization(new AuthorizeAttribute(){ Roles = "admin", });
});
}
对于某些方案实现了保护。 如果由于缺少中间件而跳过授权或 CORS 策略,则终结点中间件会引发异常。 提供有关配置错误的其他反馈的分析器支持正在准备中。
自定义授权处理程序
如果应用使用自定义授权处理程序,则终结点路由会将与 MVC 不同的资源类型传递给处理程序。 需要类型为 AuthorizationFilterContext(MVC 筛选器提供的资源类型)的授权处理程序上下文资源的处理程序需要更新,以处理类型为 RouteEndpoint(终结点路由向授权处理程序提供的资源类型)的资源。
MVC 仍使用 AuthorizationFilterContext
资源,因此,如果应用使用 MVC 授权筛选器以及终结点路由授权,则可能需要处理这两种类型的资源。
SignalR
现在,SignalR 中心的映射在 UseEndpoints
中进行。
将每个中心与 MapHub
映射。 与以前的版本一样,每个中心都会显式列出。
在下面的示例中,添加了对 ChatHub
SignalR 中心的支持:
public void Configure(IApplicationBuilder app)
{
...
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>();
});
}
有一个新选项可用于从客户端控制消息大小限制。 例如,在 Startup.ConfigureServices
中:
services.AddSignalR(hubOptions =>
{
hubOptions.MaximumReceiveMessageSize = 32768;
});
在 ASP.NET Core 2.2 中,可以设置 TransportMaxBufferSize
,这会有效控制最大消息大小。 在 ASP.NET Core 3.0 中,该选项现在仅控制观察到背压之前的最大大小。
共享框架中的 SignalR 程序集
ASP.NET Core SignalR 服务器端程序集现在随 .NET Core SDK 一起安装。 有关详细信息,请查看此文档中的移除过时的包引用。
MVC 控制器
现在,控制器的映射在 UseEndpoints
中进行。
如果应用使用属性路由,则添加 MapControllers
。 由于路由包含对 ASP.NET Core 3.0 或更高版本中许多框架的支持,因此可以选择添加属性路由控制器。
将
- 带
MapControllerRoute
的MapRoute
- 带
MapAreaControllerRoute
的MapAreaRoute
由于路由现在包含 MVC 支持以外的支持,因此术语进行了更改,使这些方法可清楚地声明其作用。 传统路由(例如 MapControllerRoute
/MapAreaControllerRoute
/MapDefaultControllerRoute
)按照其添加顺序进行应用。 首先放置更特定的路由(如某个区域的路由)。
在以下示例中:
MapControllers
添加对属性路由控制器的支持。MapAreaControllerRoute
为某个区域中的控制器添加传统路由。MapControllerRoute
为控制器添加传统路由。
public void Configure(IApplicationBuilder app)
{
...
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapAreaControllerRoute(
"admin",
"admin",
"Admin/{controller=Home}/{action=Index}/{id?}");
endpoints.MapControllerRoute(
"default", "{controller=Home}/{action=Index}/{id?}");
});
}
控制器操作名称中的 Async 后缀删除
在 ASP.NET Core 3.0 中,ASP.NET Core MVC 会从控制器操作名称中删除 Async
后缀。 此新默认设置会影响路由和链接生成。 例如:
public class ProductsController : Controller
{
public async Task<IActionResult> ListAsync()
{
var model = await _dbContext.Products.ToListAsync();
return View(model);
}
}
在 ASP.NET Core 3.0 之前:
可以在 Products/ListAsync 路由上访问以上操作。
链接生成需要指定
Async
后缀。 例如:<a asp-controller="Products" asp-action="ListAsync">List</a>
在 ASP.NET Core 3.0 中:
可以在 Products/List 路由上访问以上操作。
链接生成无需指定
Async
后缀。 例如:<a asp-controller="Products" asp-action="List">List</a>
此更改不会影响使用 [ActionName]
属性指定的名称。 可以在 Startup.ConfigureServices
中通过以下代码禁用默认行为:
services.AddMvc(options =>
options.SuppressAsyncSuffixInActionNames = false);
对链接生成的更改
链接生成中存在一些差异(例如使用 Url.Link
和相似 API)。 其中包括:
- 默认情况下,使用终结点路由时,不一定要保留生成的 URI 中路由参数的大小写。 此行为可通过
IOutboundParameterTransformer
接口进行控制。 - 为无效路由(不存在的控制器/操作或页面)生成 URI 会在终结点路由下生成空字符串,而不是生成无效 URI。
- 环境值(当前上下文中的路由参数)不会自动用于通过终结点路由进行的链接生成。 以前在生成指向其他操作(或页面)的链接时,会从当前路由环境值推断未指定的路由值。 使用终结点路由时,必须在生成链接期间显式指定所有路由参数。
Razor Pages
现在,Razor Pages 映射在 UseEndpoints
中进行。
如果应用使用 Razor Pages,则添加 MapRazorPages
。 由于终结点路由包含对许多框架的支持,因此现在可以选择添加 Razor Pages。
在下面的 Startup.Configure
方法中,MapRazorPages
添加对 Razor Pages 的支持:
public void Configure(IApplicationBuilder app)
{
...
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
在没有终结点路由的情况下使用 MVC
在 ASP.NET Core 3.0 中通过 UseMvc
或 UseMvcWithDefaultRoute
使用 MVC 需要在 Startup.ConfigureServices
中进行显式选择。 这是必需操作,因为 MVC 必须知道它是否可以在初始化期间依赖于授权和 CORS 中间件。 提供了一个分析器,以便在应用尝试使用不支持的配置时发出警告。
如果应用需要旧的 IRouter
支持,请在 Startup.ConfigureServices
中使用以下任何方法禁用 EnableEndpointRouting
:
services.AddMvc(options => options.EnableEndpointRouting = false);
services.AddControllers(options => options.EnableEndpointRouting = false);
services.AddControllersWithViews(options => options.EnableEndpointRouting = false);
services.AddRazorPages().AddMvcOptions(options => options.EnableEndpointRouting = false);
运行状况检查
运行状况检查可以在具有终结点路由的情况下用作路由器感知。
添加 MapHealthChecks
以将运行状况检查与终结点路由一起使用。 MapHealthChecks
方法接受与 UseHealthChecks
相似的参数。 使用 MapHealthChecks
相对于 UseHealthChecks
的优点是能够应用授权,并且可更精细地控制匹配策略。
在下面的示例中,会为 /healthz
处的运行状况检查终结点调用 MapHealthChecks
:
public void Configure(IApplicationBuilder app)
{
...
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/healthz", new HealthCheckOptions() { });
});
}
HostBuilder 替换 WebHostBuilder
ASP.NET Core 3.0 模板使用通用主机。 以前版本使用 Web 主机。 下面的代码演示 ASP.NET Core 3.0 模板生成的 Program
类:
// requires using Microsoft.AspNetCore.Hosting;
// requires using Microsoft.Extensions.Hosting;
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 2.2 模板生成的 Program
类:
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
IWebHostBuilder 在 3.0 中保留,是上面代码示例中所示的 webBuilder
的类型。 WebHostBuilder 将在未来版本中弃用,并替换为 HostBuilder
。
从 WebHostBuilder
到 HostBuilder
的最显著更改在依赖项注入 (DI) 中。 使用 HostBuilder
时,只能将以下内容注入 Startup
的构造函数中:
HostBuilder
DI 约束:
- 使 DI 容器可以仅生成一次。
- 避免导致对象生存期问题,例如解析单一实例的多个实例。
有关详细信息,请参阅在 ASP.NET Core 3 中避免启动服务注入。
AddAuthorization 已移到其他程序集
Microsoft.AspNetCore.Authorization.dll 中的 ASP.NET Core 2.2 及更低版本 AddAuthorization
方法:
- 已重命名为
AddAuthorizationCore
。 - 已移动到 Microsoft.AspNetCore.Authorization.Policy.dll。
同时使用 Microsoft.AspNetCore.Authorization.dll 和 Microsoft.AspNetCore.Authorization.Policy.dll 的应用不受影响。
未使用 Microsoft.AspNetCore.Authorization.Policy.dll 的应用应执行以下操作之一:
- 添加对 Microsoft.AspNetCore.Authorization.Policy.dll 的引用。 此方法适用于大多数应用,并且是唯一的必需操作。
- 切换到使用
AddAuthorizationCore
有关详细信息,请参阅 AddAuthorization(o =>
) 重载中的中断性变更处于其他程序集 #386。
Identity UI
针对 ASP.NET Core 3.0 的 Identity UI 更新:
- 将包引用添加到 Microsoft.AspNetCore.Identity.UI。
- 不使用 Razor Pages 的应用必须调用
MapRazorPages
。 请查看本文档中的 Razor Pages。 - Bootstrap 4 是默认 UI 框架。 设置
IdentityUIFrameworkVersion
项目属性以更改默认值。 有关详细信息,请参阅此 GitHub 公告。
SignalR
SignalR JavaScript 客户端从 @aspnet/signalr
更改为 @microsoft/signalr
。 若要对此更改做出反应,请更改 package.json
文件、require
语句和 ECMAScript import
语句中的引用。
System.Text.Json 是默认协议
System.Text.Json
现在是客户端和服务器使用的默认中心协议。
在 Startup.ConfigureServices
中,调用 AddJsonProtocol
以设置序列化程序选项。
服务器:
services.AddSignalR(...)
.AddJsonProtocol(options =>
{
options.PayloadSerializerOptions.WriteIndented = false;
})
客户端:
new HubConnectionBuilder()
.WithUrl("/chathub")
.AddJsonProtocol(options =>
{
options.PayloadSerializerOptions.WriteIndented = false;
})
.Build();
切换到 Newtonsoft.Json
如果使用 中不支持的 Newtonsoft.Json 功能,则可以切换回 Newtonsoft.Json
。 请参阅本文前面的在 ASP.NET Core 3.0 SignalR 项目中使用 Newtonsoft.Json。
Redis 分布式缓存
包不适用于 ASP.NET Core 3.0 或更高版本应用。 将包引用替换为 Microsoft.Extensions.Caching.StackExchangeRedis。 有关详细信息,请参阅 ASP.NET Core 中的分布式缓存。
选择进行运行时编译
在 ASP.NET Core 3.0 之前,视图的运行时编译是框架的隐式功能。 运行时编译可对视图的生成时编译进行补充。 它使框架可在修改文件时编译 Razor 视图和页面(.cshtml
文件),而无需重新生成整个应用。 此功能支持在 IDE 中进行快速编辑并刷新浏览器以查看更改的方案。
在 ASP.NET Core 3.0 中,运行时编译是一种选择加入方案。 生成时编译是适用于视图编译的默认启用的的唯一机制。 运行时在检测到 .cshtml
文件的更改时,依靠 Visual Studio 或 Visual Studio Code 中的 dotnet-watch 重新生成项目。 在 Visual Studio 中,在运行 (Ctrl+F5) 但不调试 (F5) 的项目中更改 .cs
、.cshtml
或 .razor
文件会触发项目的重新编译。
若要在 ASP.NET Core 3.0 项目中启用运行时编译,请执行以下操作:
安装 Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation NuGet 包。
更新
Startup.ConfigureServices
以调用AddRazorRuntimeCompilation
:对于 ASP.NET Core MVC,请使用以下代码:
services.AddControllersWithViews() .AddRazorRuntimeCompilation(...);
对于 ASP.NET Core Razor Pages,请使用以下代码:
services.AddRazorPages() .AddRazorRuntimeCompilation(...);
https://github.com/aspnet/samples/tree/main/samples/aspnetcore/mvc/runtimecompilation 上的示例演示了在开发环境中有条件地启用运行时编译的示例。
有关 Razor 编译的详细信息,请参阅 ASP.NET Core 中的 Razor 文件编译。
通过多目标迁移库
库通常需要支持多个版本的 ASP.NET Core。 针对以前版本的 ASP.NET Core 编译的大多数库应该可以继续正常工作,不会出现问题。 以下状况要求对应用进行交叉编译:
- 库依赖于具有二进制文件中断性变更的功能。
- 库希望利用 ASP.NET Core 3.0 中的新功能。
例如:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp3.0;netstandard2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="Microsoft.AspNetCore" Version="2.1.0" />
</ItemGroup>
</Project>
使用 #ifdefs
启用特定于 ASP.NET Core 3.0 的 API:
var webRootFileProvider =
#if NETCOREAPP3_0
GetRequiredService<IWebHostEnvironment>().WebRootFileProvider;
#elif NETSTANDARD2_0
GetRequiredService<IHostingEnvironment>().WebRootFileProvider;
#else
#error unknown target framework
#endif
有关在类库中使用 ASP.NET Core API 的详细信息,请参阅在类库中使用 ASP.NET Core API。
其他更改
.NET Core 3.0 和更高版本中的验证系统将不可为 null 的参数或绑定属性视为具有 [Required]
特性。 有关详细信息,请参阅 [Required] 属性。
发布
在项目目录中删除 bin 和 obj 文件夹。
TestServer
对于不直接通过通用主机使用 TestServer 的应用,请在 ConfigureWebHost 中对 IWebHostBuilder 创建 TestServer
:
[Fact]
public async Task GenericCreateAndStartHost_GetTestServer()
{
using var host = await new HostBuilder()
.ConfigureWebHost(webBuilder =>
{
webBuilder
.UseTestServer()
.Configure(app => { });
})
.StartAsync();
var response = await host.GetTestServer().CreateClient().GetAsync("/");
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
中断性 API 变更
查看中断性变更:
- ASP.NET Core 3.0 版本中的中断性变更的完整列表
- 防伪、CORS、诊断、MVC 和路由中的中断性 API 变更。 此列表包含兼容性开关的重大变更。
- 有关 .NET Core、ASP.NET Core 和 Entity Framework Core 中的 2.2 到 3.0 中断性变更的摘要,请参阅从版本 2.2 到 3.0 的迁移的中断性变更。
使用 catch-all 参数的终结点路由
警告
由于路由中的 bugcatch-all 参数可能无法正确匹配相应路由。 受此 Bug 影响的应用具有以下特征:
- “全部捕获”路由,例如
{**slug}"
- “全部捕获”路由未能匹配应与之匹配的请求。
- 删除其他路由可使“全部捕获”路由开始运行。
请参阅 GitHub bug 18677 和 16579,了解遇到此 bug 的示例。
.NET Core 3.1.301 SDK 及更高版本中包含此 bug 的修补程序(可选用)。 以下代码设置了一个可修复此 bug 的内部开关:
public static void Main(string[] args)
{
AppContext.SetSwitch("Microsoft.AspNetCore.Routing.UseCorrectCatchAllBehavior",
true);
CreateHostBuilder(args).Build().Run();
}
// Remaining code removed for brevity.
Azure 应用服务中的 .NET Core 3.0
.NET Core 到 Azure 应用服务的推出已完成。 所有 Azure 应用服务数据中心中都提供了 .NET Core 3.0。
ASP.NET Core 模块 (ANCM)
如果在安装 Visual Studio 时未选择 ASP.NET Core 模块 (ANCM) 组件,或者系统上安装了 ANCM 的早期版本,请下载最新的 .NET Core 托管捆绑包安装程序(直接下载)并运行该安装程序。 有关详细信息,请参阅托管捆绑包。