从 ASP.NET Core 2.2 迁移到 3.0

笔:Scott AddieRick Anderson

本文介绍如何将现有 ASP.NET Core 2.2 项目更新为 ASP.NET Core 3.0。 创建新的 Core 3.0 ASP.NET 有助于:

  • 与 ASP.NET Core 2.2 代码进行比较。
  • 将相关更改复制到 ASP.NET Core 3.0 项目。

先决条件

在 global.json 中更新 .NET Core SDK 版本

如果解决方案依赖于global.js文件以特定版本为目标.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>

删除过时的包引用

没有为 Core 3.0 生成大量 nuGet ASP.NET 包。 应从项目文件中删除此类包引用。 请考虑以下适用于 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>

更新后的 Core 3.0 ASP.NET 文件:

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

  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
  </PropertyGroup>

</Project>

更新后的 ASP.NET Core 3.0 项目文件:

  • <PropertyGroup> 中:

    • 将 TFM 更新为 netcoreapp3.0
    • 删除 <AspNetCoreHostingModel> 元素。 有关详细信息,请参阅本文档 中的进程内 托管模型。
  • <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。 Cookie政策
  • 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。 RazorViewCompilation
  • Microsoft.AspNetCore.Mvc。 Razor页面
  • Microsoft.AspNetCore.Mvc.TagHelpers
  • Microsoft.AspNetCore.Mvc.ViewFeatures
  • Microsoft.AspNetCore。Razor
  • Microsoft.AspNetCore。 Razor运行
  • Microsoft.AspNetCore。 Razor设计
  • 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核心
  • Microsoft.AspNetCore.Server。 KestrelHttps
  • Microsoft.AspNetCore.Server。 KestrelTransport.Abstractions
  • Microsoft.AspNetCore.Server。 KestrelTransport.Sockets
  • Microsoft.AspNetCore.Session
  • Microsoft.AspNetCore。SignalR
  • Microsoft.AspNetCore。 SignalR核心
  • 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 为或 SDK 的项目 Microsoft.NET.Sdk.Razor 应将显式添加 FrameworkReferenceMicrosoft.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.js 。 以下 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>
    
  • Microsoft.EntityFrameworkCore

    有关引用数据库提供程序特定包的详细信息,请参阅 数据库提供程序

  • Identity UI

    可以通过引用 AspNetCore 来添加对 Identity UI Identity 支持。UI包。

  • SPA 服务

  • 身份验证:对第三方身份验证流的支持作为 NuGet 包提供:

  • 的格式设置和内容协商支持 System.Net.HttpClientWebApi NuGet 包提供对和等 api 的有用扩展性 System.Net.HttpClient ReadAsAsync PostJsonAsync

  • Razor 运行时编译:视图和页面的运行时编译支持 Razor 现在是 AspNetCore 的一部分。 RazorRuntimeCompilation

  • MVC Newtonsoft.Json (Json.NET) 支持:对使用 MVC 的支持 Newtonsoft.Json 现在属于 Microsoft.AspNetCore.Mvc.NewtonsoftJson

启动更改

下图显示了 ASP.NET Core 2.2 页面 Web 应用中的已删除和已更改的行 Razor :

ASP.NET Core 2.2::: no loc (Razor) ::: Web 应用中的已删除和已更改的行

在上图中,删除的代码显示为红色。 删除的代码不会显示 cookie 在比较文件之前已删除的选项代码。

下图显示了 ASP.NET Core 3.0 页面 Web 应用中的已添加和已更改的行 Razor :

ASP.NET Core 3.0::: no loc (Razor) ::: Web 应用中添加和更改的行

在上图中,添加的代码显示为绿色。 有关以下更改的信息:

分析器支持

Microsoft.NET.Sdk.Web之前作为AspNetCore包的一部分提供的隐式引用分析器的项目。 不需要其他引用即可启用这些。

如果你的应用使用以前使用AspNetCore包交付的API 分析器,则编辑项目文件以引用作为 .net Core Web SDK 的一部分提供的分析器:

<Project Sdk="Microsoft.NET.Sdk.Web">
    <PropertyGroup>
        <TargetFramework>netcoreapp3.0</TargetFramework>
        <IncludeOpenAPIAnalyzers>true</IncludeOpenAPIAnalyzers>
    </PropertyGroup>

    ...
</Project>

Razor 类库

Razor 为 MVC 提供 UI 组件的类库项目必须 AddRazorSupportForMvc 在项目文件中设置属性:

<PropertyGroup>
  <AddRazorSupportForMvc>true</AddRazorSupportForMvc>
</PropertyGroup>

进程内托管模型

项目默认为 ASP.NET Core 3.0 或更高版本中的 进程内承载模型 。 如果项目文件的值为,则可以选择删除该 <AspNetCoreHostingModel> 属性 InProcess

Kestrel

Configuration

Kestrel将配置迁移到 (Program) 提供的web 主机生成器 ConfigureWebHostDefaults

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 ,请 UseKestrel 在 web 主机生成器上调用:

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 部分中的 TlsFilterConnectionHandler 示例

已移动并公开传输抽象

Kestrel 传输层已作为 Connections.Abstractions 中的公共接口公开。 作为这些更新的一部分:

  • Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions 和关联的类型已被删除。
  • NoDelay 已从移 ListenOptions 到传输选项。
  • Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal.SchedulingMode 已从中移除 KestrelServerOptions

有关详细信息,请参阅以下 GitHub 资源:

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:从响应中获取请求的尾随标头。 SupportsTrailers请在调用前检查 GetTrailerNotSupportedException 如果请求不支持尾部标头,则可能会发生这种情况。

有关详细信息,请参阅 将请求尾端置于单独的集合中 (dotnet/AspNetCore #10410)

已禁用 AllowSynchronousIO

AllowSynchronousIO 启用或禁用同步 i/o Api,例如 HttpRequest.Body.ReadHttpResponse.Body.WriteStream.Flush 。 这些 Api 是线程不足的源,导致应用崩溃。 在 3.0 中,默认情况下禁用 AllowSynchronousIO。 有关详细信息,请参阅 Kestrel 文章中的同步 i/o 部分

如果需要同步 i/o,可以通过在 AllowSynchronousIO 调用时 (正在使用的服务器上配置选项来启用该选项, ConfigureKestrel 例如,如果使用 Kestrel) 。 请注意,服务器 (Kestrel 、HttpSys、TestServer 等 ) 都具有自己 AllowSynchronousIO 的选项,而不会影响其他服务器。 可以使用以下选项,针对每个请求为所有服务器启用同步 i/o IHttpBodyControlFeature.AllowSynchronousIO

var syncIOFeature = HttpContext.Features.Get<IHttpBodyControlFeature>();

if (syncIOFeature != null)
{
    syncIOFeature.AllowSynchronousIO = true;
}

如果对 TextWriterDispose中调用同步 api 的实现或其他流有问题,请改为调用新 DisposeAsync api。

有关详细信息,请参阅 [公告] AllowSynchronousIO 在所有服务器 (dotnet/AspNetCore #7644) 中禁用

输出格式化程序缓冲

XmlSerializer 基于、和的输出格式化程序Newtonsoft.JsDataContractSerializer 仅支持同步序列化。 为了使这些格式化程序能够使用服务器的 AllowSynchronousIO 限制,MVC 在写入磁盘之前缓冲这些格式化程序的输出。 作为缓冲的结果,当使用这些格式化程序响应时,MVC 将包含内容长度标头。

System.Text.Json 支持异步序列化,因此 System.Text.Json 基于的格式化程序不会缓冲。 请考虑使用此格式化程序以提高性能。

若要禁用缓冲,可以在启动时配置应用程序 SuppressOutputFormatterBuffering

services.AddControllers(options => options.SuppressOutputFormatterBuffering = true)

请注意,如果还未配置,这可能会导致应用程序引发运行时异常 AllowSynchronousIO

AspNetCore Kestrel 。已删除 Https 程序集

在 ASP.NET Core 2.1 中, Kestrel.Https.dllAspNetCore 的内容已移至 AspNetCore。 Kestrel.Core.dll"。 这是一个使用特性的非重大更新 TypeForwardedTo 。 对于3.0,已删除空的 Kestrel.Https.dllAspNetCore 程序集和 NuGet 包。

引用 AspNetCore 的库 。 KestrelHttps 应将 ASP.NET Core 依赖项更新为2.1 或更高版本。

目标为 ASP.NET Core 2.1 或更高版本的应用程序和库应删除对 AspNetCore. 的所有直接引用。 KestrelHttps 包。

(Json.NET 上的 Newtonsoft.Js) 支持

作为 改善 ASP.NET Core 共享框架的工作的一部分,已从 ASP.NET Core 共享框架中删除 (Json.NET) 的Newtonsoft.Js

ASP.NET Core 的默认 JSON 序列化程序现在是 System.Text.Json .Net Core 3.0 中的新增项。 请考虑 System.Text.Json 尽可能使用。 它是高性能的,不需要额外的库依赖项。 不过,由于 System.Text.Json 是全新的,它当前可能缺少你的应用程序所需的功能。 有关详细信息,请参阅 " 如何从 Newtonsoft.Js迁移到 System.Text.Js"

在 ASP.NET Core 3.0 项目中使用 Newtonsoft.JsSignalR

  • 安装 AspNetCore。 SignalRNewtonsoftJson NuGet 包。

  • 在客户端上,将 AddNewtonsoftJsonProtocol 方法调用链接到 HubConnectionBuilder 实例:

    new HubConnectionBuilder()
        .WithUrl("/chathub")
        .AddNewtonsoftJsonProtocol(...)
        .Build();
    
  • 在服务器上, AddNewtonsoftJsonProtocol 将方法调用链接到 AddSignalR 中的方法调用 Startup.ConfigureServices

    services.AddSignalR()
        .AddNewtonsoftJsonProtocol(...);
    

在 ASP.NET Core 3.0 MVC 项目中使用 Newtonsoft.Js

  • 安装 Microsoft.AspNetCore.Mvc.NewtonsoftJson 包。

  • 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.JsMicrosoft.AspNetCore.Mvc.NewtonsoftJson

有关详细信息,请参阅 添加基于 Newtonsoft.Js的 JSON 格式支持

MVC 服务注册

ASP.NET Core 3.0 添加了用于在中注册 MVC 方案的新选项 Startup.ConfigureServices

提供了三种与中的 MVC 方案相关的高级扩展方法 IServiceCollection 。 模板使用这些新方法,而不是 AddMvc 。 但是, AddMvc 会继续按照以前版本中的方式进行。

下面的示例添加了对控制器和 API 相关功能的支持,但不支持视图或页面。 API 模板使用以下代码:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
}

下面的示例添加了对控制器、API 相关功能和视图(而不是页)的支持。 (MVC) 模板中的 Web 应用程序使用以下代码:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
}

以下示例添加了对 Razor 页面和最小控制器支持的支持。 Web 应用程序模板使用以下代码:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
}

新方法也可以组合在一起。 下面的示例等效于 AddMvc 在 ASP.NET Core 2.2 中调用:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddRazorPages();
}

路由启动代码

如果应用调用 UseMvcUseSignalR ,则将应用迁移到 终结点路由 (如果可能)。 若要改善与以前版本的 MVC 的终结点路由兼容性,我们已还原 ASP.NET Core 2.2 中引入的 URL 生成的某些更改。 如果在2.2 中使用终结点路由时遇到问题,则需要 ASP.NET Core 3.0 中的改进,但有以下例外:

  • 如果应用实现 IRouter 或继承 Route ,请使用 DynamicRouteValuesTransformer 作为替换。
  • 如果应用在 RouteData.Routers MVC 内直接访问以分析 url,则可以将其替换为使用 LinkParser. ParsePathByEndpointName
    • 使用路由名称定义路由。
    • 使用 LinkParser.ParsePathByEndpointName 并传入所需的路由名称。

终结点路由支持与相同的路由模式语法和路由模式创作功能 IRouter 。 终结点路由支持 IRouteConstraint 。 终结点路由支持 [Route][HttpGet] 和其他 MVC 路由特性。

对于大多数应用程序,只 Startup 需要更改。

迁移 Startup.Configu)

一般建议:

  • 添加 UseRouting

  • 如果应用调用 UseStaticFiles ,则放置 UseStaticFiles 在之前 UseRouting

  • 如果应用使用身份验证/授权功能(如 AuthorizePage[Authorize] ),请将对和的调用放在 UseAuthenticationUseAuthorization 之后UseRouting UseCors UseEndpoints

    public void Configure(IApplicationBuilder app)
    {
      ...
    
      app.UseStaticFiles();
    
      app.UseRouting();
      app.UseCors();
    
      app.UseAuthentication();
      app.UseAuthorization();
    
      app.UseEndpoints(endpoints => {
         endpoints.MapControllers();
      });
    
  • UseMvc 或替换 UseSignalRUseEndpoints

  • 如果应用使用 cors 方案(如),则在 [EnableCors] UseCors 使用 cors 的任何其他中间件之前,将调用放在其他中间件之前 (例如, UseCorsUseAuthenticationUseAuthorization 和) 之前放置 UseEndpoints

  • 将替换为 IHostingEnvironment IWebHostEnvironment ,并 usingMicrosoft.Extensions.Hosting 命名空间添加语句。

  • 替换 IApplicationLifetimeIHostApplicationLifetime (Microsoft.Extensions.Hosting 命名空间) 。

  • 替换 EnvironmentNameEnvironments (Microsoft.Extensions.Hosting 命名空间) 。

下面的代码是 Startup.Configure 典型 ASP.NET Core 2.2 应用中的的一个示例:

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?}");
    });
}

警告

对于大多数应用,对 UseAuthenticationUseAuthorization 和的调用 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类通过属性禁用 CORS [DisableCors]
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 ,而是依赖授权中间件。 如果应用在 AuthorizeFilter MVC 中使用作为全局筛选器,我们建议重构代码,以便在对的调用中提供策略 AddAuthorization

DefaultPolicy最初配置为要求身份验证,因此无需进行其他配置。 在下面的示例中,MVC 终结点标记为, RequireAuthorization 以便所有请求都必须基于进行授权 DefaultPolicy 。 但是, HomeController 由于以下原因,不允许用户登录到应用程序 [AllowAnonymous]

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute().RequireAuthorization();
    });
}

[AllowAnonymous]
public class HomeController : Controller
{
    ...
}

针对特定终结点的授权

还可以为特定的终结点类配置授权。 下面的代码示例将配置为全局应用程序的 MVC 应用程序转换 AuthorizeFilter 为具有要求授权的特定策略:

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
{

或者,可以将所有终结点配置为要求在没有 [Authorize]RequireAuthorization 配置的情况下进行身份验证 FallbackPolicy 。 与 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 中,该选项现在仅控制观察反压之前的最大大小。

MVC 控制器

控制器的映射现在发生在中 UseEndpoints

MapControllers如果应用使用属性路由,则添加。 由于路由包括对 ASP.NET Core 3.0 或更高版本中的多个框架的支持,因此添加属性路由控制器是可选的。

  • MapControllerRouteMapRoute
  • MapAreaControllerRouteMapAreaRoute

由于路由现在不仅包括对 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/batchmanagementclient.account.listasync 路由中访问上述操作。

  • 需要指定后缀的链接生成 Async 。 例如:

    <a asp-controller="Products" asp-action="ListAsync">List</a>
    

在 ASP.NET Core 3.0:

  • 可以在 产品/列表 路由上访问上述操作。

  • 链接生成不需要指定 Async 后缀。 例如:

    <a asp-controller="Products" asp-action="List">List</a>
    

此更改不会影响使用属性指定 [ActionName] 的名称。 可以通过以下代码禁用默认行为 Startup.ConfigureServices

services.AddMvc(options =>
    options.SuppressAsyncSuffixInActionNames = false);

如文档中所述,与 早期版本的路由有关的不同之处在于,使用和类似的 api 进行链接生成 (Url.Link ,例如) 。 其中包括:

  • 默认情况下,使用终结点路由时,不一定要保留生成的 Uri 中路由参数的大小写。 此行为可通过接口进行控制 IOutboundParameterTransformer
  • 在不存在的控制器/操作或页) 为无效 (路由生成 URI 时,将在端点路由下生成空字符串,而不是生成无效的 URI。
  • 从当前上下文) (路由参数的环境值不会自动用于通过终结点路由进行的链接生成。 以前,如果生成指向其他操作 (或页面) 的链接,则将从 当前 路由的环境值推断出未指定的路由值。 使用终结点路由时,必须在生成链接期间显式指定所有路由参数。

Razor Pages

Razor现在,映射页发生在中 UseEndpoints

MapRazorPages如果应用使用页面,则添加 Razor 。 由于终结点路由包含对多个框架的支持,因此 Razor 现在将选择添加页。

在下面的 Startup.Configure 方法中, MapRazorPages 添加了对页的支持 Razor :

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

使用不带终结点路由的 MVC

UseMvc UseMvcWithDefaultRoute 在 ASP.NET Core 3.0 中通过或使用 MVC 需要显式选择加入 Startup.ConfigureServices 。 这是必需的,因为 MVC 必须知道它是否可以在初始化期间依赖于授权和 CORS 中间件。 如果应用程序尝试使用不受支持的配置,则会发出警告。

如果应用需要旧 IRouter 支持,请 EnableEndpointRouting 使用中的以下任何方法禁用 Startup.ConfigureServices

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 。 使用 over MapHealthChecksUseHealthChecks 优点是能够应用授权,并可以更精细地控制匹配策略。

在下面的示例中, MapHealthChecks 为 中的运行状况检查终结点调用 /healthz

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 到 的构造函数中:

HostBuilderDI 约束:

  • 使 DI 容器仅生成一次。
  • 避免导致的对象生存期问题,例如解决多个单一实例。

有关详细信息,请参阅避免在 ASP.NET Core 3 中注入启动服务

AddAuthorization 已移到其他程序集

中 ASP.NET Core 2.2 和 AddAuthorization 更低 Microsoft.AspNetCore.Authorization.dll:

  • 已重命名 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

Identity ASP.NET Core 3.0 的 UI 更新:

SignalR

SignalRJavaScript 客户端从 更改为 @aspnet/signalr @microsoft/signalr 。 若要对此更改做出反应,请更改 package.js、 语句和 require ECMAScript 语句中的 import 引用。

System.Text.Js是默认协议

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.Js打开

如果使用的是 Newtonsoft.Json 中不支持的 System.Text.Js功能,可以切换回 Newtonsoft.Json 。 请参阅 本文Newtonsoft.Js在 ASP.NET Core 3.0 SignalR 项目中使用 on。

Redis 分布式缓存

Microsoft.Extensions.Caching.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 文件的更改会触发项目的重新编译。

若要在 Core 3.0 项目中 ASP.NET 运行时编译,请执行:

  1. 安装 Microsoft.AspNetCore.Mvc。 RazorRuntimeCompilation NuGet 包。

  2. 更新 Startup.ConfigureServices 以调用 AddRazorRuntimeCompilation

    对于 ASP.NET Core MVC,请使用以下代码:

    services.AddControllersWithViews()
        .AddRazorRuntimeCompilation(...);
    

    对于 ASP.NET Razor Core Pages,请使用以下代码:

    services.AddRazorPages()
        .AddRazorRuntimeCompilation(...);
    

上的示例 https://github.com/aspnet/samples/tree/main/samples/aspnetcore/mvc/runtimecompilation 演示了在开发环境中有条件地启用运行时编译的示例。

有关文件编译 Razor 详细信息,请参阅 Razor ASP.NET Core 中的文件编译

通过多目标迁移库

库通常需要支持多个版本的 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] 特性。 有关详细信息,请参阅 [必需] 属性

发布

删除 项目 目录中的 bin 和 obj 文件夹。

TestServer

对于直接使用 TestServer 泛型主机 的应用,TestServer 中的 IWebHostBuilder 上创建 ConfigureWebHost

[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 更改

查看中断性变更:

使用 catch-all 参数的终结点路由

警告

由于路由中的 bugcatch-all 参数可能无法正确匹配相应路由。 受此 Bug 影响的应用具有以下特征:

  • “全部捕获”路由,例如 {**slug}"
  • “全部捕获”路由未能匹配应与之匹配的请求。
  • 删除其他路由可使“全部捕获”路由开始运行。

请参阅 GitHub bug 1867716579,了解遇到此 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.

.NET Core 3.0 on Azure 应用服务

.NET Core 的推出Azure 应用服务完成。 .NET Core 3.0 在所有数据中心Azure 应用服务可用。