从 ASP.NET Core 2.2 迁移到3。0Migrate from ASP.NET Core 2.2 to 3.0

作者: Scott AddieRick AndersonBy Scott Addie and Rick Anderson

本文介绍如何将现有 ASP.NET Core 2.2 项目更新为 ASP.NET Core 3.0。This article explains how to update an existing ASP.NET Core 2.2 project to ASP.NET Core 3.0. 创建新的 ASP.NET Core 3.0 项目来执行以下操作可能会有所帮助:It might be helpful to create a new ASP.NET Core 3.0 project to:

  • 与 ASP.NET Core 2.2 代码进行比较。Compare with the ASP.NET Core 2.2 code.
  • 将相关更改复制到 ASP.NET Core 3.0 项目。Copy the relevant changes to your ASP.NET Core 3.0 project.

先决条件Prerequisites

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

如果解决方案依赖于针对特定 .NET Core SDK 版本的文件global.js ,请 version 将其属性更新为计算机上安装的3.0 版本:If your solution relies upon a global.json file to target a specific .NET Core SDK version, update its version property to the 3.0 version installed on your machine:

{
  "sdk": {
    "version": "3.0.100"
  }
}

更新项目文件Update the project file

更新目标框架Update the Target Framework

ASP.NET Core 3.0 及更高版本仅在 .NET Core 上运行。ASP.NET Core 3.0 and later only run on .NET Core. 目标框架名字对象(TFM)设置为 netcoreapp3.0Set the Target Framework Moniker (TFM) to netcoreapp3.0:

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

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

</Project>

删除过时的包引用Remove obsolete package references

ASP.NET Core 3.0 不会生成大量 NuGet 包。A large number of NuGet packages aren't produced for ASP.NET Core 3.0. 此类包引用应从项目文件中删除。Such package references should be removed from your project file. 对于 ASP.NET Core 2.2 web 应用,请考虑以下项目文件:Consider the following project file for an ASP.NET Core 2.2 web app:

<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 的更新项目文件:The updated project file for ASP.NET Core 3.0:

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

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

</Project>

更新的 ASP.NET Core 3.0 项目文件:The updated ASP.NET Core 3.0 project file:

  • <PropertyGroup> 中:In the <PropertyGroup>:

    • 将 TFM 更新为netcoreapp3.0Updates the TFM to netcoreapp3.0
    • 删除 <AspNetCoreHostingModel> 元素。Removes the <AspNetCoreHostingModel> element. 有关详细信息,请参阅本文档中的进程内承载模型For more information, see In-process hosting model in this document.
  • <ItemGroup> 中:In the <ItemGroup>:

    • Microsoft.AspNetCore.App已删除。Microsoft.AspNetCore.App is removed. 有关详细信息,请参阅本文档中的框架参考For more information, see Framework reference in this document.
    • Microsoft.AspNetCore.Razor.Design将删除,并且不再生成以下包列表。Microsoft.AspNetCore.Razor.Design is removed and in the following list of packages no longer being produced.

若要查看不再生成的包的完整列表,请选择以下展开列表:To see the full list of packages that are no longer produced, select the following expand list:

单击以展开不再生成的包列表Click to expand the list of packages no longer being produced
  • Microsoft.AspNetCoreMicrosoft.AspNetCore
  • Microsoft.AspNetCore.AllMicrosoft.AspNetCore.All
  • Microsoft.AspNetCore.AppMicrosoft.AspNetCore.App
  • Microsoft.AspNetCore.AntiforgeryMicrosoft.AspNetCore.Antiforgery
  • Microsoft.AspNetCore.AuthenticationMicrosoft.AspNetCore.Authentication
  • Microsoft.AspNetCore.Authentication.AbstractionsMicrosoft.AspNetCore.Authentication.Abstractions
  • Microsoft.AspNetCore.Authentication.CookiesMicrosoft.AspNetCore.Authentication.Cookies
  • Microsoft.AspNetCore.Authentication.CoreMicrosoft.AspNetCore.Authentication.Core
  • Microsoft.AspNetCore.Authentication.OAuthMicrosoft.AspNetCore.Authentication.OAuth
  • Microsoft.AspNetCore.Authorization.PolicyMicrosoft.AspNetCore.Authorization.Policy
  • Microsoft.AspNetCore.CookiePolicyMicrosoft.AspNetCore.CookiePolicy
  • Microsoft.AspNetCore.CorsMicrosoft.AspNetCore.Cors
  • Microsoft.AspNetCore.DiagnosticsMicrosoft.AspNetCore.Diagnostics
  • Microsoft.AspNetCore.Diagnostics.HealthChecksMicrosoft.AspNetCore.Diagnostics.HealthChecks
  • Microsoft.AspNetCore.HostFilteringMicrosoft.AspNetCore.HostFiltering
  • Microsoft.AspNetCore.HostingMicrosoft.AspNetCore.Hosting
  • Microsoft.AspNetCore.Hosting.AbstractionsMicrosoft.AspNetCore.Hosting.Abstractions
  • Microsoft.AspNetCore.Hosting.Server.AbstractionsMicrosoft.AspNetCore.Hosting.Server.Abstractions
  • Microsoft.AspNetCore.HttpMicrosoft.AspNetCore.Http
  • Microsoft.AspNetCore.Http.AbstractionsMicrosoft.AspNetCore.Http.Abstractions
  • Microsoft.AspNetCore.Http.ConnectionsMicrosoft.AspNetCore.Http.Connections
  • Microsoft.AspNetCore.Http.ExtensionsMicrosoft.AspNetCore.Http.Extensions
  • Microsoft.AspNetCore.HttpOverridesMicrosoft.AspNetCore.HttpOverrides
  • Microsoft.AspNetCore.HttpsPolicyMicrosoft.AspNetCore.HttpsPolicy
  • AspNetCore。IdentityMicrosoft.AspNetCore.Identity
  • Microsoft.AspNetCore.LocalizationMicrosoft.AspNetCore.Localization
  • Microsoft.AspNetCore.Localization.RoutingMicrosoft.AspNetCore.Localization.Routing
  • Microsoft.AspNetCore.MvcMicrosoft.AspNetCore.Mvc
  • Microsoft.AspNetCore.Mvc.AbstractionsMicrosoft.AspNetCore.Mvc.Abstractions
  • Microsoft.AspNetCore.Mvc.AnalyzersMicrosoft.AspNetCore.Mvc.Analyzers
  • Microsoft.AspNetCore.Mvc.ApiExplorerMicrosoft.AspNetCore.Mvc.ApiExplorer
  • Microsoft.AspNetCore.Mvc.Api.AnalyzersMicrosoft.AspNetCore.Mvc.Api.Analyzers
  • Microsoft.AspNetCore.Mvc.CoreMicrosoft.AspNetCore.Mvc.Core
  • Microsoft.AspNetCore.Mvc.CorsMicrosoft.AspNetCore.Mvc.Cors
  • Microsoft.AspNetCore.Mvc.DataAnnotationsMicrosoft.AspNetCore.Mvc.DataAnnotations
  • Microsoft.AspNetCore.Mvc.Formatters.JsonMicrosoft.AspNetCore.Mvc.Formatters.Json
  • Microsoft.AspNetCore.Mvc.Formatters.XmlMicrosoft.AspNetCore.Mvc.Formatters.Xml
  • Microsoft.AspNetCore.Mvc.LocalizationMicrosoft.AspNetCore.Mvc.Localization
  • AspNetCore。RazorMicrosoft.AspNetCore.Mvc.Razor
  • AspNetCore Razor 。Microsoft.aspnetcore.mvc.razor.viewcompilationMicrosoft.AspNetCore.Mvc.Razor.ViewCompilation
  • Microsoft.AspNetCore.Mvc.RazorPagesMicrosoft.AspNetCore.Mvc.RazorPages
  • Microsoft.AspNetCore.Mvc.TagHelpersMicrosoft.AspNetCore.Mvc.TagHelpers
  • Microsoft.AspNetCore.Mvc.ViewFeaturesMicrosoft.AspNetCore.Mvc.ViewFeatures
  • AspNetCore。RazorMicrosoft.AspNetCore.Razor
  • AspNetCore Razor 。时会Microsoft.AspNetCore.Razor.Runtime
  • AspNetCore Razor 。设计图Microsoft.AspNetCore.Razor.Design
  • Microsoft.AspNetCore.ResponseCachingMicrosoft.AspNetCore.ResponseCaching
  • Microsoft.AspNetCore.ResponseCaching.AbstractionsMicrosoft.AspNetCore.ResponseCaching.Abstractions
  • Microsoft.AspNetCore.ResponseCompressionMicrosoft.AspNetCore.ResponseCompression
  • Microsoft.AspNetCore.RewriteMicrosoft.AspNetCore.Rewrite
  • Microsoft.AspNetCore.RoutingMicrosoft.AspNetCore.Routing
  • Microsoft.AspNetCore.Routing.AbstractionsMicrosoft.AspNetCore.Routing.Abstractions
  • Microsoft.AspNetCore.Server.HttpSysMicrosoft.AspNetCore.Server.HttpSys
  • Microsoft.AspNetCore.Server.IISMicrosoft.AspNetCore.Server.IIS
  • Microsoft.AspNetCore.Server.IISIntegrationMicrosoft.AspNetCore.Server.IISIntegration
  • Microsoft.AspNetCore.Server.KestrelMicrosoft.AspNetCore.Server.Kestrel
  • Microsoft.AspNetCore.Server.Kestrel.CoreMicrosoft.AspNetCore.Server.Kestrel.Core
  • Microsoft.AspNetCore.Server.Kestrel.HttpsMicrosoft.AspNetCore.Server.Kestrel.Https
  • Microsoft.AspNetCore.Server.Kestrel.Transport.AbstractionsMicrosoft.AspNetCore.Server.Kestrel.Transport.Abstractions
  • Microsoft.AspNetCore.Server.Kestrel.Transport.SocketsMicrosoft.AspNetCore.Server.Kestrel.Transport.Sockets
  • Microsoft.AspNetCore.SessionMicrosoft.AspNetCore.Session
  • AspNetCore。SignalRMicrosoft.AspNetCore.SignalR
  • AspNetCore SignalR 。转储Microsoft.AspNetCore.SignalR.Core
  • Microsoft.AspNetCore.StaticFilesMicrosoft.AspNetCore.StaticFiles
  • Microsoft.AspNetCore.WebSocketsMicrosoft.AspNetCore.WebSockets
  • Microsoft.AspNetCore.WebUtilitiesMicrosoft.AspNetCore.WebUtilities
  • Microsoft.Net.Http.Headers Microsoft.Net.Http.Headers

查看重大更改Review breaking changes

查看重大更改Review breaking changes

框架引用Framework reference

通过上述某个包提供的 ASP.NET Core 功能可作为共享框架的一部分提供 Microsoft.AspNetCore.AppFeatures of ASP.NET Core that were available through one of the packages listed above are available as part of the Microsoft.AspNetCore.App shared framework. 共享框架** 是安装在计算机上并包括运行时组件和目标包的一组程序集(.dll 文件)。The shared framework is the set of assemblies (.dll files) that are installed on the machine and includes a runtime component and a targeting pack. 有关详细信息,请参阅共享框架For more information, see The shared framework.

  • 面向 Microsoft.NET.Sdk.Web SDK 的项目隐式引用 Microsoft.AspNetCore.App 框架。Projects that target the Microsoft.NET.Sdk.Web SDK implicitly reference the Microsoft.AspNetCore.App framework.

    对于这些项目,不需要其他引用:No additional references are required for these projects:

    <Project Sdk="Microsoft.NET.Sdk.Web">
      <PropertyGroup>
        <TargetFramework>netcoreapp3.0</TargetFramework>
      </PropertyGroup>
        ...
    </Project>
    
  • 目标 Microsoft.NET.Sdk 为或 SDK 的项目 Microsoft.NET.Sdk.Razor 应将显式添加 FrameworkReferenceMicrosoft.AspNetCore.AppProjects that target Microsoft.NET.Sdk or Microsoft.NET.Sdk.Razor SDK, should add an explicit FrameworkReference to Microsoft.AspNetCore.App:

    <Project Sdk="Microsoft.NET.Sdk.Razor">
      <PropertyGroup>
        <TargetFramework>netcoreapp3.0</TargetFramework>
      </PropertyGroup>
    
      <ItemGroup>
        <FrameworkReference Include="Microsoft.AspNetCore.App" />
      </ItemGroup>
        ...
    </Project>
    

使用 Docker 的依赖框架的生成Framework-dependent builds using Docker

使用依赖于 ASP.NET Core共享框架的包的、依赖于框架的控制台应用程序可能会给出以下运行时错误:Framework-dependent builds of console apps that use a package that depends on the ASP.NET Core shared framework may give the following runtime error:

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 映像中。Microsoft.AspNetCore.App is the shared framework containing the ASP.NET Core runtime and is only present on the dotnet/core/aspnet Docker image. 3.0 SDK 使用 ASP.NET Core 来减小依赖于框架的生成的大小,但不包括共享框架中可用的库的重复副本。The 3.0 SDK reduces the size of framework-dependent builds using ASP.NET Core by not including duplicate copies of libraries that are available in the shared framework. 这可能会节省高达 18 MB,但需要提供 ASP.NET Core 运行时才能运行应用。This is a potential savings of up to 18 MB, but it requires that the ASP.NET Core runtime be present / installed to run the app.

若要确定应用程序在 ASP.NET Core 共享框架上是否具有依赖关系(直接或间接),请检查应用程序生成/发布期间生成的文件runtimeconfig.jsTo determine if the app has a dependency (either direct or indirect) on the ASP.NET Core shared framework, examine the runtimeconfig.json file generated during a build/publish of your app. 以下 JSON 文件显示了对 ASP.NET Core 共享框架的依赖项:The following JSON file shows a dependency on the ASP.NET Core shared framework:

{
  "runtimeOptions": {
    "tfm": "netcoreapp3.0",
    "framework": {
      "name": "Microsoft.AspNetCore.App",
      "version": "3.0.0"
    },
    "configProperties": {
      "System.GC.Server": true
    }
  }
}

如果你的应用使用的是 Docker,请使用包含 ASP.NET Core 3.0 的基本映像。If your app is using Docker, use a base image that includes ASP.NET Core 3.0. 例如 docker pull mcr.microsoft.com/dotnet/core/aspnet:3.0For example, docker pull mcr.microsoft.com/dotnet/core/aspnet:3.0.

添加已删除程序集的包引用Add package references for removed assemblies

ASP.NET Core 3.0 删除了之前属于包引用的某些程序集 Microsoft.AspNetCore.AppASP.NET Core 3.0 removes some assemblies that were previously part of the Microsoft.AspNetCore.App package reference. 若要可视化删除了哪些程序集,请比较两个共享框架文件夹。To visualize which assemblies were removed, compare the two shared framework folders. 例如,2.2.7 和3.0.0 版本的比较:For example, a comparison of versions 2.2.7 and 3.0.0:

共享框架程序集比较

若要继续使用已删除程序集提供的功能,请参考相应包的3.0 版本:To continue using features provided by the removed assemblies, reference the 3.0 versions of the corresponding packages:

启动更改Startup changes

下图显示了 ASP.NET Core 2.2 页面 Web 应用中的已删除和已更改的行 Razor :The following image shows the deleted and changed lines in an ASP.NET Core 2.2 Razor Pages Web app:

ASP.NET Core 2.2 Web 应用中的已删除和已更改的行 Razorthe deleted and changed lines in an ASP.NET Core 2.2 Razor Web app

在上图中,删除的代码显示为红色。In the preceding image, deleted code is shown in red. 删除的代码不显示 cookie 选项代码,该代码在比较文件之前已被删除。The deleted code doesn't show cookie options code, which was deleted prior to comparing the files.

下图显示了 ASP.NET Core 3.0 页面 Web 应用中的已添加和已更改的行 Razor :The following image shows the added and changed lines in an ASP.NET Core 3.0 Razor Pages Web app:

ASP.NET Core 3.0 Web 应用中添加和更改的行 Razorthe added and changed lines in an ASP.NET Core 3.0 Razor Web app

在上图中,添加的代码显示为绿色。In the preceding image, added code is shown in green. 有关以下更改的信息:For information on the following changes:

分析器支持Analyzer support

Microsoft.NET.Sdk.Web之前作为AspNetCore包的一部分提供的隐式引用分析器的项目。Projects that target Microsoft.NET.Sdk.Web implicitly reference analyzers previously shipped as part of the Microsoft.AspNetCore.Mvc.Analyzers package. 不需要其他引用即可启用这些。No additional references are required to enable these.

如果你的应用使用以前使用AspNetCore包交付的API 分析器,则编辑项目文件以引用作为 .net Core Web SDK 的一部分提供的分析器:If your app uses API analyzers previously shipped using the Microsoft.AspNetCore.Mvc.Api.Analyzers package, edit your project file to reference the analyzers shipped as part of the .NET Core Web SDK:

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

    ...
</Project>

Razor类库 Class Library

Razor为 MVC 提供 UI 组件的类库项目必须 AddRazorSupportForMvc 在项目文件中设置属性: Class Library projects that provide UI components for MVC must set the AddRazorSupportForMvc property in the project file:

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

进程内托管模型In-process hosting model

项目默认为 ASP.NET Core 3.0 或更高版本中的进程内承载模型Projects default to the in-process hosting model in ASP.NET Core 3.0 or later. 如果项目文件的值为,则可以选择删除该 <AspNetCoreHostingModel> 属性 InProcessYou may optionally remove the <AspNetCoreHostingModel> property in the project file if its value is InProcess.

KestrelKestrel

配置Configuration

将 Kestrel 配置迁移到由(Program.cs)提供的web 主机生成器 ConfigureWebHostDefaults Program.csMigrate Kestrel configuration to the web host builder provided by ConfigureWebHostDefaults (Program.cs):

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.ConfigureKestrel(serverOptions =>
            {
                // Set properties and call methods on options
            })
            .UseStartup<Startup>();
        });

如果应用通过手动创建主机,则 HostBuilder UseKestrel 在中的 web 主机生成器上调用 ConfigureWebHostDefaultsIf the app creates the host manually with HostBuilder, call UseKestrel on the web host builder in ConfigureWebHostDefaults:

public static void Main(string[] args)
{
    var host = new HostBuilder()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseKestrel(serverOptions =>
            {
                // Set properties and call methods on options
            })
            .UseIISIntegration()
            .UseStartup<Startup>();
        })
        .Build();

    host.Run();
}

连接中间件替代连接适配器Connection Middleware replaces Connection Adapters

Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal.IConnectionAdapter 从 Kestrel 中删除连接适配器()。Connection Adapters (Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal.IConnectionAdapter) have been removed from Kestrel. 将连接适配器替换为连接中间件。Replace Connection Adapters with Connection Middleware. 连接中间件与 ASP.NET Core 管道中的 HTTP 中间件类似,但对于较低级别的连接。Connection Middleware is similar to HTTP Middleware in the ASP.NET Core pipeline but for lower-level connections. HTTPS 和连接日志记录:HTTPS and connection logging:

  • 已从连接适配器移到连接中间件。Have been moved from Connection Adapters to Connection Middleware.
  • 这些扩展方法的工作方式与 ASP.NET Core 以前版本相同。These extension methods work as in previous versions of ASP.NET Core.

有关详细信息,请参阅Kestrel 文章的 ListenOptions 部分中的 TlsFilterConnectionHandler 示例For more information, see the TlsFilterConnectionHandler example in the ListenOptions.Protocols section of the Kestrel article.

已移动并公开传输抽象Transport abstractions moved and made public

Kestrel 传输层已作为 Connections.Abstractions 中的公共接口公开。The Kestrel transport layer has been exposed as a public interface in Connections.Abstractions. 作为这些更新的一部分:As part of these updates:

  • Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions和关联的类型已被删除。Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions and associated types have been removed.
  • NoDelay已从移 ListenOptions 到传输选项。NoDelay was moved from ListenOptions to the transport options.
  • Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal.SchedulingMode已从中移除 KestrelServerOptionsMicrosoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal.SchedulingMode was removed from KestrelServerOptions.

有关详细信息,请参阅以下 GitHub 资源:For more information, see the following GitHub resources:

Kestrel 请求尾端标头Kestrel Request trailer headers

对于面向 ASP.NET Core 早期版本的应用:For apps that target earlier versions of ASP.NET Core:

  • Kestrel 将 HTTP/1.1 分块尾端标头添加到请求标头集合。Kestrel adds HTTP/1.1 chunked trailer headers into the request headers collection.
  • 在将请求正文读取到末尾后,尾端可用。Trailers are available after the request body is read to the end.

这会导致一些有关标头和尾部的歧义的问题,因此,尾端已移到3.0 中的新集合( RequestTrailerExtensions )。This causes some concerns about ambiguity between headers and trailers, so the trailers have been moved to a new collection (RequestTrailerExtensions) in 3.0.

HTTP/2 请求尾端包括:HTTP/2 request trailers are:

  • ASP.NET Core 2.2 中不可用。Not available in ASP.NET Core 2.2.
  • 可在3.0 中提供 RequestTrailerExtensionsAvailable in 3.0 as RequestTrailerExtensions.

提供了新的请求扩展方法来访问这些尾端。New request extension methods are present to access these trailers. 与 HTTP/1.1 一样,在请求正文读取到末尾后,尾端可用。As with HTTP/1.1, trailers are available after the request body is read to the end.

对于3.0 版, RequestTrailerExtensions 可以使用以下方法:For the 3.0 release, the following RequestTrailerExtensions methods are available:

  • GetDeclaredTrailers:获取一个请求 Trailer 标头,该标头列出了主体后预期的尾部。GetDeclaredTrailers: Gets the request Trailer header that lists which trailers to expect after the body.
  • SupportsTrailers:指示请求是否支持接收尾端标头。SupportsTrailers: Indicates if the request supports receiving trailer headers.
  • CheckTrailersAvailable:检查请求是否支持尾端以及是否可供读取。CheckTrailersAvailable: Checks if the request supports trailers and if they're available to be read. 此检查未假定有要读取的尾端。This check doesn't assume that there are trailers to read. 即使 true 此方法返回了,也没有要读取的尾端。There might be no trailers to read even if true is returned by this method.
  • GetTrailer:从响应中获取请求的尾随标头。GetTrailer: Gets the requested trailing header from the response. SupportsTrailers请在调用前检查 GetTrailerNotSupportedException 如果请求不支持尾部标头,则可能会发生这种情况。Check SupportsTrailers before calling GetTrailer, or a NotSupportedException may occur if the request doesn't support trailing headers.

有关详细信息,请参阅将请求尾端置于单独的集合中(dotnet/AspNetCore #10410)For more information, see Put request trailers in a separate collection (dotnet/AspNetCore #10410).

已禁用 AllowSynchronousIOAllowSynchronousIO disabled

AllowSynchronousIO启用或禁用同步 i/o Api,例如 HttpRequest.Body.ReadHttpResponse.Body.WriteStream.FlushAllowSynchronousIO enables or disables synchronous I/O APIs, such as HttpRequest.Body.Read, HttpResponse.Body.Write, and Stream.Flush. 这些 Api 是线程不足的源,导致应用崩溃。These APIs are a source of thread starvation leading to app crashes. 在 3.0 中,默认情况下禁用 AllowSynchronousIOIn 3.0, AllowSynchronousIO is disabled by default. 有关详细信息,请参阅Kestrel 文章中的同步 i/o 部分For more information, see the Synchronous I/O section in the Kestrel article.

如果需要同步 i/o,可以通过在 AllowSynchronousIO 所使用的服务器上配置选项来启用该选项(例如,在调用时, ConfigureKestrel 例如,如果使用 Kestrel)。If synchronous I/O is needed, it can be enabled by configuring the AllowSynchronousIO option on the server being used (when calling ConfigureKestrel, for example, if using Kestrel). 请注意,服务器(Kestrel、HttpSys、TestServer 等)都有自己 AllowSynchronousIO 的选项,此选项不会影响其他服务器。Note that servers (Kestrel, HttpSys, TestServer, etc.) all have their own AllowSynchronousIO option that won't affect other servers. 可以使用以下选项,针对每个请求为所有服务器启用同步 i/o IHttpBodyControlFeature.AllowSynchronousIOSynchronous I/O can be enabled for all servers on a per-request basis using the IHttpBodyControlFeature.AllowSynchronousIO option:

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

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

如果对 TextWriterDispose中调用同步 api 的实现或其他流有问题,请改为调用新 DisposeAsync api。If you have trouble with TextWriter implementations or other streams that call synchronous APIs in Dispose, call the new DisposeAsync API instead.

有关详细信息,请参阅[公告] AllowSynchronousIO 在所有服务器中禁用(dotnet/AspNetCore #7644)For more information, see [Announcement] AllowSynchronousIO disabled in all servers (dotnet/AspNetCore #7644).

输出格式化程序缓冲Output formatter buffering

Newtonsoft.Json XmlSerializer 基于、和的输出格式化程序Newtonsoft.JsDataContractSerializer 仅支持同步序列化。Newtonsoft.Json, XmlSerializer, and DataContractSerializer based output formatters only support synchronous serialization. 为了使这些格式化程序能够使用服务器的AllowSynchronousIO限制,MVC 在写入磁盘之前缓冲这些格式化程序的输出。To allow these formatters to work with the AllowSynchronousIO restrictions of the server, MVC buffers the output of these formatters before writing to disk. 作为缓冲的结果,当使用这些格式化程序响应时,MVC 将包含内容长度标头。As a result of buffering, MVC will include the Content-Length header when responding using these formatters.

System.Text.Json支持异步序列化,因此 System.Text.Json 基于的格式化程序不会缓冲。System.Text.Json supports asynchronous serialization and consequently the System.Text.Json based formatter does not buffer. 请考虑使用此格式化程序以提高性能。Consider using this formatter for improved performance.

若要禁用缓冲,可以在启动时配置应用程序 SuppressOutputFormatterBufferingTo disable buffering, applications can configure SuppressOutputFormatterBuffering in their startup:

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

请注意,如果还未配置,这可能会导致应用程序引发运行时异常 AllowSynchronousIONote that this may result in the application throwing a runtime exception if AllowSynchronousIO isn't also configured.

AspNetCore. Kestrel 程序集Microsoft.AspNetCore.Server.Kestrel.Https assembly removed

在 ASP.NET Core 2.1 中, Microsoft.AspNetCore.Server.Kestrel.Https.dll的内容已移到Microsoft.AspNetCore.Server.Kestrel.Core.dll中。In ASP.NET Core 2.1, the contents of Microsoft.AspNetCore.Server.Kestrel.Https.dll were moved to Microsoft.AspNetCore.Server.Kestrel.Core.dll. 这是一个使用特性的非重大更新 TypeForwardedToThis was a non-breaking update using TypeForwardedTo attributes. 对于3.0,已删除空的Microsoft.AspNetCore.Server.Kestrel.Https.dll程序集和 NuGet 包。For 3.0, the empty Microsoft.AspNetCore.Server.Kestrel.Https.dll assembly and the NuGet package have been removed.

引用AspNetCore的库应将 ASP.NET Core 依赖项更新为2.1 或更高版本。Libraries referencing Microsoft.AspNetCore.Server.Kestrel.Https should update ASP.NET Core dependencies to 2.1 or later.

目标为 ASP.NET Core 2.1 或更高版本的应用程序和库应删除对Kestrel包的任何直接引用。Apps and libraries targeting ASP.NET Core 2.1 or later should remove any direct references to the Microsoft.AspNetCore.Server.Kestrel.Https package.

Newtonsoft.Js(Json.NET)支持Newtonsoft.Json (Json.NET) support

作为改善 ASP.NET Core 共享框架的工作的一部分,已从 ASP.NET Core 共享框架中删除Newtonsoft.Json (Json.NET)As part of the work to improve the ASP.NET Core shared framework, Newtonsoft.Json (Json.NET) has been removed from the ASP.NET Core shared framework.

ASP.NET Core 的默认 JSON 序列化程序现在是 System.Text.Json .Net Core 3.0 中的新增项。The default JSON serializer for ASP.NET Core is now System.Text.Json, which is new in .NET Core 3.0. 请考虑 System.Text.Json 尽可能使用。Consider using System.Text.Json when possible. 它是高性能的,不需要额外的库依赖项。It's high-performance and doesn't require an additional library dependency. 不过,由于 System.Text.Json 是全新的,它当前可能缺少你的应用程序所需的功能。However, since System.Text.Json is new, it might currently be missing features that your app needs. 有关详细信息,请参阅 "如何从 Newtonsoft.Js迁移到 System.Text.Js"For more information, see How to migrate from Newtonsoft.Json to System.Text.Json.

在 ASP.NET Core 3.0 项目中使用 Newtonsoft.JsSignalRUse Newtonsoft.Json in an ASP.NET Core 3.0 SignalR project

  • 安装AspNetCore。 SignalRNewtonsoftJson NuGet 包。Install the Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson NuGet package.

  • 在客户端上,将 AddNewtonsoftJsonProtocol 方法调用链接到 HubConnectionBuilder 实例:On the client, chain an AddNewtonsoftJsonProtocol method call to the HubConnectionBuilder instance:

    new HubConnectionBuilder()
        .WithUrl("/chathub")
        .AddNewtonsoftJsonProtocol(...)
        .Build();
    
  • 在服务器上, AddNewtonsoftJsonProtocol 将方法调用链接到 AddSignalR 中的方法调用 Startup.ConfigureServicesOn the server, chain an AddNewtonsoftJsonProtocol method call to the AddSignalR method call in Startup.ConfigureServices:

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

在 ASP.NET Core 3.0 MVC 项目中使用 Newtonsoft.JsUse Newtonsoft.Json in an ASP.NET Core 3.0 MVC project

  • 安装 Microsoft.AspNetCore.Mvc.NewtonsoftJson 包。Install the Microsoft.AspNetCore.Mvc.NewtonsoftJson package.

  • Startup.ConfigureServices要调用 AddNewtonsoftJson 的更新。Update Startup.ConfigureServices to call AddNewtonsoftJson.

    services.AddMvc()
        .AddNewtonsoftJson();
    

    AddNewtonsoftJson与新 MVC 服务注册方法兼容:AddNewtonsoftJson is compatible with the new MVC service registration methods:

    • AddRazorPages
    • AddControllersWithViews
    • AddControllers
    services.AddControllers()
        .AddNewtonsoftJson();
    

    Newtonsoft.Json可以在对的调用中设置设置 AddNewtonsoftJsonNewtonsoft.Json settings can be set in the call to AddNewtonsoftJson:

    services.AddMvc()
        .AddNewtonsoftJson(options =>
               options.SerializerSettings.ContractResolver =
                  new CamelCasePropertyNamesContractResolver());
    

注意: 如果此 AddNewtonsoftJson 方法不可用,请确保已安装 Microsoft.AspNetCore.Mvc.NewtonsoftJson 包。Note: If the AddNewtonsoftJson method isn't available, make sure that you installed the Microsoft.AspNetCore.Mvc.NewtonsoftJson package. 常见的错误是在包而不是包安装Newtonsoft.JsMicrosoft.AspNetCore.Mvc.NewtonsoftJsonA common error is to install the Newtonsoft.Json package instead of the Microsoft.AspNetCore.Mvc.NewtonsoftJson package.

MVC 服务注册MVC service registration

ASP.NET Core 3.0 添加了用于在中注册 MVC 方案的新选项 Startup.ConfigureServicesASP.NET Core 3.0 adds new options for registering MVC scenarios inside Startup.ConfigureServices.

提供了三种与中的 MVC 方案相关的高级扩展方法 IServiceCollectionThree new top-level extension methods related to MVC scenarios on IServiceCollection are available. 模板使用这些新方法,而不是 AddMvcTemplates use these new methods instead of AddMvc. 但是, AddMvc 会继续按照以前版本中的方式进行。However, AddMvc continues to behave as it has in previous releases.

下面的示例添加了对控制器和 API 相关功能的支持,但不支持视图或页面。The following example adds support for controllers and API-related features, but not views or pages. API 模板使用以下代码:The API template uses this code:

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

下面的示例添加了对控制器、API 相关功能和视图(而不是页)的支持。The following example adds support for controllers, API-related features, and views, but not pages. Web 应用程序(MVC)模板使用以下代码:The Web Application (MVC) template uses this code:

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

以下示例添加了对 Razor 页面和最小控制器支持的支持。The following example adds support for Razor Pages and minimal controller support. Web 应用程序模板使用以下代码:The Web Application template uses this code:

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

新方法也可以组合在一起。The new methods can also be combined. 下面的示例等效于 AddMvc 在 ASP.NET Core 2.2 中调用:The following example is equivalent to calling AddMvc in ASP.NET Core 2.2:

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

路由启动代码Routing startup code

如果应用调用 UseMvcUseSignalR ,则将应用迁移到终结点路由(如果可能)。If an app calls UseMvc or UseSignalR, migrate the app to Endpoint Routing if possible. 若要改善与以前版本的 MVC 的终结点路由兼容性,我们已还原 ASP.NET Core 2.2 中引入的 URL 生成的某些更改。To improve Endpoint Routing compatibility with previous versions of MVC, we've reverted some of the changes in URL generation introduced in ASP.NET Core 2.2. 如果在2.2 中使用终结点路由时遇到问题,则需要 ASP.NET Core 3.0 中的改进,但有以下例外:If you experienced problems using Endpoint Routing in 2.2, expect improvements in ASP.NET Core 3.0 with the following exceptions:

  • 如果应用实现 IRouter 或继承 Route ,请使用DynamicRouteValuesTransformer作为替换。If the app implements IRouter or inherits from Route, use DynamicRouteValuesTransformer as the replacement.
  • 如果应用在 RouteData.Routers MVC 内直接访问以分析 url,则可以将其替换为使用LinkParser. ParsePathByEndpointNameIf the app directly accesses RouteData.Routers inside MVC to parse URLs, you can replace this with use of LinkParser.ParsePathByEndpointName.
    • 使用路由名称定义路由。Define the route with a route name.
    • 使用 LinkParser.ParsePathByEndpointName 并传入所需的路由名称。Use LinkParser.ParsePathByEndpointName and pass in the desired route name.

终结点路由支持与相同的路由模式语法和路由模式创作功能 IRouterEndpoint Routing supports the same route pattern syntax and route pattern authoring features as IRouter. 终结点路由支持 IRouteConstraintEndpoint Routing supports IRouteConstraint. 终结点路由支持 [Route][HttpGet] 和其他 MVC 路由特性。Endpoint routing supports [Route], [HttpGet], and the other MVC routing attributes.

对于大多数应用程序,只 Startup 需要更改。For most applications, only Startup requires changes.

迁移 Startup.Configu)Migrate Startup.Configure

一般建议:General advice:

  • 添加 UseRoutingAdd UseRouting.

  • 如果应用调用 UseStaticFiles ,则放置 UseStaticFiles 在之前 UseRoutingIf the app calls UseStaticFiles, place UseStaticFiles before UseRouting.

  • 如果应用使用身份验证/授权功能(如 AuthorizePage[Authorize] ),请将对和的调用放在 UseAuthenticationUseAuthorization 之后UseRouting UseCors UseEndpointsIf the app uses authentication/authorization features such as AuthorizePage or [Authorize], place the call to UseAuthentication and UseAuthorization: after, UseRouting and UseCors, but before UseEndpoints:

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

  • 如果应用使用cors方案(如 [EnableCors] ),则在 UseCors 使用 cors 的任何其他中间件之前(例如, UseCors 在、和之前放置 UseAuthentication UseAuthorization UseEndpoints )。If the app uses CORS scenarios, such as [EnableCors], place the call to UseCors before any other middleware that use CORS (for example, place UseCors before UseAuthentication, UseAuthorization, and UseEndpoints).

  • 将替换为 IHostingEnvironment IWebHostEnvironment ,并 usingMicrosoft.Extensions.Hosting 命名空间添加语句。Replace IHostingEnvironment with IWebHostEnvironment and add a using statement for the Microsoft.Extensions.Hosting namespace.

  • 替换 IApplicationLifetimeIHostApplicationLifetimeMicrosoft.Extensions.Hosting 命名空间)。Replace IApplicationLifetime with IHostApplicationLifetime (Microsoft.Extensions.Hosting namespace).

  • 替换 EnvironmentNameEnvironmentsMicrosoft.Extensions.Hosting 命名空间)。Replace EnvironmentName with Environments (Microsoft.Extensions.Hosting namespace).

下面的代码是 Startup.Configure 典型 ASP.NET Core 2.2 应用中的的一个示例:The following code is an example of Startup.Configure in a typical ASP.NET Core 2.2 app:

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 代码后:After updating the previous Startup.Configure code:

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 生效。For most apps, calls to UseAuthentication, UseAuthorization, and UseCors must appear between the calls to UseRouting and UseEndpoints to be effective.

运行状况检查Health Checks

运行状况检查将终结点路由与泛型主机一起使用。Health Checks use endpoint routing with the Generic Host. Startup.Configure 内,使用终结点 URL 或相对路径在终结点生成器上调用 MapHealthChecksIn Startup.Configure, call MapHealthChecks on the endpoint builder with the endpoint URL or relative path:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health");
});

运行状况检查终结点可以:Health Checks endpoints can:

  • 指定一个或多个允许的主机/端口。Specify one or more permitted hosts/ports.
  • 需要授权。Require authorization.
  • 需要 CORS。Require CORS.

有关详细信息,请参阅 ASP.NET Core 中的运行状况检查For more information, see ASP.NET Core 中的运行状况检查.

安全中间件指南Security middleware guidance

对授权和 CORS 的支持是围绕中间件方法统一的。Support for authorization and CORS is unified around the middleware approach. 这允许在这些情况下使用相同的中间件和功能。This allows use of the same middleware and functionality across these scenarios. 此版本提供了更新的授权中间件,并增强了 CORS 中间件,使其能够理解 MVC 控制器使用的属性。An updated authorization middleware is provided in this release, and CORS Middleware is enhanced so that it can understand the attributes used by MVC controllers.

CORSCORS

以前,CORS 可能比较困难。Previously, CORS could be difficult to configure. 在某些用例中提供了中间件,但在其他用例中使用中间件即可使用 MVC 筛选器。Middleware was provided for use in some use cases, but MVC filters were intended to be used without the middleware in other use cases. 使用 ASP.NET Core 3.0,建议所有需要 CORS 的应用都将 CORS 中间件与端点路由一起使用。With ASP.NET Core 3.0, we recommend that all apps that require CORS use the CORS Middleware in tandem with Endpoint Routing. UseCors可以使用默认策略提供,并且 [EnableCors][DisableCors] 属性可用于在需要时覆盖默认策略。UseCors can be provided with a default policy, and [EnableCors] and [DisableCors] attributes can be used to override the default policy where required.

如下示例中:In the following example:

  • 已为具有命名策略的所有终结点启用 CORS defaultCORS is enabled for all endpoints with the default named policy.
  • MyController类通过属性禁用 CORS [DisableCors]The MyController class disables CORS with the [DisableCors] attribute.
public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseCors("default");

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

[DisableCors]
public class MyController : ControllerBase
{
    ...
}

授权Authorization

在早期版本的 ASP.NET Core 中,通过属性提供授权支持 [Authorize]In earlier versions of ASP.NET Core, authorization support was provided via the [Authorize] attribute. 授权中间件不可用。Authorization middleware wasn't available. 在 ASP.NET Core 3.0 中,授权中间件是必需的。In ASP.NET Core 3.0, authorization middleware is required. 建议在之后立即放置 ASP.NET Core 授权中间件( UseAuthorizationUseAuthenticationWe recommend placing the ASP.NET Core Authorization Middleware (UseAuthorization) immediately after UseAuthentication. 授权中间件还可以使用默认策略进行配置,该策略可以重写。The Authorization Middleware can also be configured with a default policy, which can be overridden.

在 ASP.NET Core 3.0 或更高版本中, UseAuthorization 在中调用 Startup.Configure ,并且以下 HomeController 要求登录用户:In ASP.NET Core 3.0 or later, UseAuthorization is called in Startup.Configure, and the following HomeController requires a signed in user:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

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

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

public class HomeController : Controller
{
    [Authorize]
    public IActionResult BuyWidgets()
    {
        ...
    }
}

使用终结点路由时,建议不要配置 <xref:Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter> ,而是依赖授权中间件。When using endpoint routing, we recommend against configuring <xref:Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter> and instead relying on the Authorization middleware. 如果应用在 AuthorizeFilter MVC 中使用作为全局筛选器,我们建议重构代码,以便在对的调用中提供策略 AddAuthorizationIf the app uses an AuthorizeFilter as a global filter in MVC, we recommend refactoring the code to provide a policy in the call to AddAuthorization.

DefaultPolicy最初配置为要求身份验证,因此无需进行其他配置。The DefaultPolicy is initially configured to require authentication, so no additional configuration is required. 在下面的示例中,MVC 终结点标记为, RequireAuthorization 以便所有请求都必须基于进行授权 DefaultPolicyIn the following example, MVC endpoints are marked as RequireAuthorization so that all requests must be authorized based on the DefaultPolicy. 但是, HomeController 由于以下原因,不允许用户登录到应用程序 [AllowAnonymous]However, the HomeController allows access without the user signing into the app due to [AllowAnonymous]:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

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

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

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

针对特定终结点的授权Authorization for specific endpoints

还可以为特定的终结点类配置授权。Authorization can also be configured for specific classes of endpoints. 下面的代码示例将配置为全局应用程序的 MVC 应用程序转换 AuthorizeFilter 为具有要求授权的特定策略:The following code is an example of converting an MVC app that configured a global AuthorizeFilter to an app with a specific policy requiring authorization:

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();
        });
    }
}

还可以自定义策略。Policies can also be customized. DefaultPolicy配置为要求身份验证:The DefaultPolicy is configured to require authentication:

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 配置的情况下进行身份验证 FallbackPolicyAlternatively, all endpoints can be configured to require authorization without [Authorize] or RequireAuthorization by configuring a FallbackPolicy. FallbackPolicy 不同 DefaultPolicyThe FallbackPolicy is different from the DefaultPolicy. DefaultPolicy [Authorize] 或触发 RequireAuthorization ,而在 FallbackPolicy 未设置其他策略时触发。The DefaultPolicy is triggered by [Authorize] or RequireAuthorization, while the FallbackPolicy is triggered when no other policy is set. FallbackPolicy最初配置为允许未经授权的请求。FallbackPolicy is initially configured to allow requests without authorization.

下面的示例与前面的示例相同, DefaultPolicy 但使用在 FallbackPolicy 所有终结点上始终要求身份验证,但 [AllowAnonymous] 指定时除外:The following example is the same as the preceding DefaultPolicy example but uses the FallbackPolicy to always require authentication on all endpoints except when [AllowAnonymous] is specified:

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
{
    ...
}

中间件的授权工作正常,无需使用任何特定的授权知识。Authorization by middleware works without the framework having any specific knowledge of authorization. 例如,运行状况检查没有特定的授权知识,但运行状况检查可以具有由中间件应用的可配置授权策略。For instance, health checks has no specific knowledge of authorization, but health checks can have a configurable authorization policy applied by the middleware.

此外,每个终结点都可以自定义其授权要求。Additionally, each endpoint can customize its authorization requirements. 在下面的示例中, UseAuthorization 使用处理授权 DefaultPolicy ,但是 /healthz 运行状况检查终结点需要 admin 用户:In the following example, UseAuthorization processes authorization with the DefaultPolicy, but the /healthz health check endpoint requires an admin user:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

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

    app.UseEndpoints(endpoints =>
    {
        endpoints
            .MapHealthChecks("/healthz")
            .RequireAuthorization(new AuthorizeAttribute(){ Roles = "admin", });
    });
}

在某些情况下,实现保护。Protection is implemented for some scenarios. 如果由于缺少中间件而跳过授权或 CORS 策略,则终结点中间件会引发异常。Endpoints Middleware throws an exception if an authorization or CORS policy is skipped due to missing middleware. 提供有关配置错误的其他反馈的分析器支持。Analyzer support to provide additional feedback about misconfiguration is in progress.

自定义授权处理程序Custom authorization handlers

如果应用使用自定义授权处理程序,则终结点路由将不同于 MVC 的资源类型传递给处理程序。If the app uses custom authorization handlers, endpoint routing passes a different resource type to handlers than MVC. 需要更新授权处理程序上下文资源为类型 AuthorizationFilterContextMVC 筛选器提供的资源类型)的处理程序,以处理类型为的资源 RouteEndpoint (由端点路由提供给授权处理程序的资源类型)。Handlers that expect the authorization handler context resource to be of type AuthorizationFilterContext (the resource type provided by MVC filters) will need to be updated to handle resources of type RouteEndpoint (the resource type given to authorization handlers by endpoint routing).

MVC 仍使用 AuthorizationFilterContext 资源,因此,如果应用使用 MVC 授权筛选器以及终结点路由授权,则可能有必要处理这两种类型的资源。MVC still uses AuthorizationFilterContext resources, so if the app uses MVC authorization filters along with endpoint routing authorization, it may be necessary to handle both types of resources.

SignalR

集线器的映射 SignalR 现在发生在中 UseEndpointsMapping of SignalR hubs now takes place inside UseEndpoints.

将每个中心映射到 MapHubMap each hub with MapHub. 与早期版本一样,每个中心都显式列出。As in previous versions, each hub is explicitly listed.

在以下示例中,添加了对中心的支持 ChatHub SignalR :In the following example, support for the ChatHub SignalR hub is added:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapHub<ChatHub>();
    });
}

有一个新的选项可用于控制来自客户端的消息大小限制。There is a new option for controlling message size limits from clients. 例如,在 Startup.ConfigureServices 中:For example, in Startup.ConfigureServices:

services.AddSignalR(hubOptions =>
{
    hubOptions.MaximumReceiveMessageSize = 32768;
});

在 ASP.NET Core 2.2 中,可以设置 TransportMaxBufferSize 和,以便有效地控制最大消息大小。In ASP.NET Core 2.2, you could set the TransportMaxBufferSize and that would effectively control the maximum message size. 在 ASP.NET Core 3.0 中,该选项现在仅控制观察反压之前的最大大小。In ASP.NET Core 3.0, that option now only controls the maximum size before backpressure is observed.

MVC 控制器MVC controllers

控制器的映射现在发生在中 UseEndpointsMapping of controllers now takes place inside UseEndpoints.

MapControllers如果应用使用属性路由,则添加。Add MapControllers if the app uses attribute routing. 由于路由包括对 ASP.NET Core 3.0 或更高版本中的多个框架的支持,因此添加属性路由控制器是可选的。Since routing includes support for many frameworks in ASP.NET Core 3.0 or later, adding attribute-routed controllers is opt-in.

Replace the following:

  • MapControllerRouteMapRouteMapRoute with MapControllerRoute
  • MapAreaControllerRouteMapAreaRouteMapAreaRoute with MapAreaControllerRoute

由于路由现在不仅包括对 MVC 的支持,术语已更改,使这些方法清楚地说明它们的作用。Since routing now includes support for more than just MVC, the terminology has changed to make these methods clearly state what they do. 传统路由(例如)按照 MapControllerRoute / MapAreaControllerRoute / MapDefaultControllerRoute 它们的添加顺序进行应用。Conventional routes such as MapControllerRoute/MapAreaControllerRoute/MapDefaultControllerRoute are applied in the order that they're added. 首先放置更具体的路由(如区域的路由)。Place more specific routes (such as routes for an area) first.

如下示例中:In the following example:

  • MapControllers添加对属性路由控制器的支持。MapControllers adds support for attribute-routed controllers.
  • MapAreaControllerRoute为某个区域中的控制器添加传统路由。MapAreaControllerRoute adds a conventional route for controllers in an area.
  • MapControllerRoute为控制器添加传统路由。MapControllerRoute adds a conventional route for controllers.
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 后缀Async suffix removal from controller action names

在 ASP.NET Core 3.0 中,ASP.NET Core MVC Async 从控制器操作名称中删除后缀。In ASP.NET Core 3.0, ASP.NET Core MVC removes the Async suffix from controller action names. 此新默认设置会影响路由和链接的生成。Both routing and link generation are impacted by this new default. 例如:For example:

public class ProductsController : Controller
{
    public async Task<IActionResult> ListAsync()
    {
        var model = await _dbContext.Products.ToListAsync();
        return View(model);
    }
}

在 ASP.NET Core 3.0 之前:Prior to ASP.NET Core 3.0:

  • 可以在Products/batchmanagementclient.account.listasync路由中访问上述操作。The preceding action could be accessed at the Products/ListAsync route.

  • 需要指定后缀的链接生成 AsyncLink generation required specifying the Async suffix. 例如:For example:

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

在 ASP.NET Core 3.0:In ASP.NET Core 3.0:

  • 可以在产品/列表路由上访问上述操作。The preceding action can be accessed at the Products/List route.

  • 链接生成不需要指定 Async 后缀。Link generation doesn't require specifying the Async suffix. 例如:For example:

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

此更改不会影响使用属性指定 [ActionName] 的名称。This change doesn't affect names specified using the [ActionName] attribute. 可以通过以下代码禁用默认行为 Startup.ConfigureServicesThe default behavior can be disabled with the following code in Startup.ConfigureServices:

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

如文档中所述,与早期版本的路由的不同之处在于,链接生成存在一些差异(例如,使用 Url.Link 类似的 api)。As explained in documentation on differences from earlier versions of routing, there are some differences in link generation (using Url.Link and similar APIs, for example). 其中包括:These include:

  • 默认情况下,使用终结点路由时,不一定要保留生成的 Uri 中路由参数的大小写。By default, when using endpoint routing, casing of route parameters in generated URIs is not necessarily preserved. 此行为可通过接口进行控制 IOutboundParameterTransformerThis behavior can be controlled with the IOutboundParameterTransformer interface.
  • 为无效路由(不存在的控制器/操作或页)生成 URI 将在终结点路由下生成空字符串,而不是生成无效的 URI。Generating a URI for an invalid route (a controller/action or page that doesn't exist) will produce an empty string under endpoint routing instead of producing an invalid URI.
  • 环境值(来自当前上下文的路由参数)不会自动用于通过终结点路由生成的链接。Ambient values (route parameters from the current context) are not automatically used in link generation with endpoint routing. 以前,当生成指向另一操作(或页)的链接时,将从当前路由的环境值推断出未指定的路由值。Previously, when generating a link to another action (or page), unspecified route values would be inferred from the current routes ambient values. 使用终结点路由时,必须在生成链接期间显式指定所有路由参数。When using endpoint routing, all route parameters must be specified explicitly during link generation.

Razor Pages Pages

Razor现在,映射页发生在中 UseEndpointsMapping Razor Pages now takes place inside UseEndpoints.

MapRazorPages如果应用使用页面,则添加 Razor 。Add MapRazorPages if the app uses Razor Pages. 由于终结点路由包含对多个框架的支持,因此 Razor 现在将选择添加页。Since Endpoint Routing includes support for many frameworks, adding Razor Pages is now opt-in.

在下面的 Startup.Configure 方法中, MapRazorPages 添加了对页的支持 Razor :In the following Startup.Configure method, MapRazorPages adds support for Razor Pages:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

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

使用不带终结点路由的 MVCUse MVC without Endpoint Routing

UseMvc UseMvcWithDefaultRoute 在 ASP.NET Core 3.0 中通过或使用 MVC 需要显式选择加入 Startup.ConfigureServicesUsing MVC via UseMvc or UseMvcWithDefaultRoute in ASP.NET Core 3.0 requires an explicit opt-in inside Startup.ConfigureServices. 这是必需的,因为 MVC 必须知道它是否可以在初始化期间依赖于授权和 CORS 中间件。This is required because MVC must know whether it can rely on the authorization and CORS Middleware during initialization. 如果应用程序尝试使用不受支持的配置,则会发出警告。An analyzer is provided that warns if the app attempts to use an unsupported configuration.

如果应用需要旧 IRouter 支持,请 EnableEndpointRouting 使用中的以下任何方法禁用 Startup.ConfigureServicesIf the app requires legacy IRouter support, disable EnableEndpointRouting using any of the following approaches in 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);

运行状况检查Health checks

运行状况检查可用作使用终结点路由的路由器软件。Health checks can be used as a router-ware with Endpoint Routing.

添加 MapHealthChecks 以将运行状况检查与终结点路由配合使用。Add MapHealthChecks to use health checks with Endpoint Routing. MapHealthChecks方法接受与类似的参数 UseHealthChecksThe MapHealthChecks method accepts arguments similar to UseHealthChecks. 使用 over 的优点 MapHealthChecks UseHealthChecks 是能够应用授权,并对匹配策略进行更精细的控制。The advantage of using MapHealthChecks over UseHealthChecks is the ability to apply authorization and to have greater fine-grained control over the matching policy.

在下面的示例中, MapHealthChecks 针对运行状况检查终结点调用 /healthzIn the following example, MapHealthChecks is called for a health check endpoint at /healthz:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapHealthChecks("/healthz", new HealthCheckOptions() { });
    });
}

HostBuilder 替换 WebHostBuilderHostBuilder replaces WebHostBuilder

ASP.NET Core 3.0 模板使用泛型主机The ASP.NET Core 3.0 templates use Generic Host. 以前的版本使用Web 主机Previous versions used Web Host. 下面的代码演示 ASP.NET Core 3.0 模板生成的 Program 类:The following code shows the ASP.NET Core 3.0 template generated Program class:

// 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 类:The following code shows the ASP.NET Core 2.2 template-generated Program class:

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 代码示例中所示的类型。IWebHostBuilder remains in 3.0 and is the type of the webBuilder seen in the preceding code sample. WebHostBuilder未来版本中将弃用,并将其替换为 HostBuilderWebHostBuilder will be deprecated in a future release and replaced by HostBuilder.

从到的最重要的更改 WebHostBuilder HostBuilder依赖关系注入(DI)The most significant change from WebHostBuilder to HostBuilder is in dependency injection (DI). 使用时 HostBuilder ,只能将以下 Startup 内容注入构造函数:When using HostBuilder, you can only inject the following into Startup's constructor:

HostBuilderDI 约束:The HostBuilder DI constraints:

  • 启用仅生成一次 DI 容器。Enable the DI container to be built only one time.
  • 避免产生的对象生存期问题,如解析多个单一实例实例。Avoids the resulting object lifetime issues like resolving multiple instances of singletons.

有关详细信息,请参阅避免启动服务注入 ASP.NET Core 3For more information, see Avoiding Startup service injection in ASP.NET Core 3.

AddAuthorization 已移动到不同的程序集AddAuthorization moved to a different assembly

Microsoft.AspNetCore.Authorization.dll中的 ASP.NET Core 2.2 和更低 AddAuthorization 方法: * *The ASP.NET Core 2.2 and lower AddAuthorization methods in Microsoft.AspNetCore.Authorization.dll:

  • 已重命名 AddAuthorizationCoreHave been renamed AddAuthorizationCore.
  • 已移动到Microsoft.AspNetCore.Authorization.Policy.dllHave been moved to Microsoft.AspNetCore.Authorization.Policy.dll.

同时使用Microsoft.AspNetCore.Authorization.dllMicrosoft.AspNetCore.Authorization.Policy.dll的应用不会受到影响。Apps that are using both Microsoft.AspNetCore.Authorization.dll and Microsoft.AspNetCore.Authorization.Policy.dll aren't impacted.

不使用Microsoft.AspNetCore.Authorization.Policy.dll的应用程序应执行以下操作之一:Apps that are not using Microsoft.AspNetCore.Authorization.Policy.dll should do one of the following:

  • 添加对Microsoft.AspNetCore.Authorization.Policy.dll的引用。Add a reference to Microsoft.AspNetCore.Authorization.Policy.dll. 这种方法适用于大多数应用,只是必需的。This approach works for most apps and is all that is required.
  • 切换到使用AddAuthorizationCoreSwitch to using AddAuthorizationCore

有关详细信息,请参阅中的重大更改 AddAuthorization(o => )重载在不同的程序集中 #386For more information, see Breaking change in AddAuthorization(o =>) overload lives in a different assembly #386.

Identity UI UI

IdentityASP.NET Core 3.0 的 UI 更新: UI updates for ASP.NET Core 3.0:

  • 向 AspNetCore 添加包引用 Identity 。UIAdd a package reference to Microsoft.AspNetCore.Identity.UI.
  • 不使用页面的应用 Razor 必须调用 MapRazorPagesApps that don't use Razor Pages must call MapRazorPages. 请参阅本文档中的 Razor 页面See Razor Pages in this document.
  • 启动4是默认的 UI 框架。Bootstrap 4 is the default UI framework. 设置 IdentityUIFrameworkVersion 项目属性以更改默认值。Set an IdentityUIFrameworkVersion project property to change the default. 有关详细信息,请参阅此 GitHub 公告For more information, see this GitHub announcement.

SignalR

SignalRJavaScript 客户端已从更改 @aspnet/signalr@microsoft/signalrThe SignalR JavaScript client has changed from @aspnet/signalr to @microsoft/signalr. 若要对此更改做出反应,请更改package.json文件、 require 语句和 ECMAScript 语句package.js中的引用 importTo react to this change, change the references in package.json files, require statements, and ECMAScript import statements.

System.Text.Js为默认协议System.Text.Json is the default protocol

System.Text.Json现在是客户端和服务器使用的默认集线器协议。System.Text.Json is now the default Hub protocol used by both the client and server.

在中 Startup.ConfigureServices ,调用 AddJsonProtocol 设置序列化程序选项。In Startup.ConfigureServices, call AddJsonProtocol to set serializer options.

服务Server:

services.AddSignalR(...)
        .AddJsonProtocol(options =>
        {
            options.PayloadSerializerOptions.WriteIndented = false;
        })

Client:

new HubConnectionBuilder()
    .WithUrl("/chathub")
    .AddJsonProtocol(options =>
    {
        options.PayloadSerializerOptions.WriteIndented = false;
    })
    .Build();

切换到 Newtonsoft.JsSwitch to Newtonsoft.Json

如果你使用System.Text.Js上不支持的 Newtonsoft.Js功能,则可以切换回 Newtonsoft.JsonIf you're using features of Newtonsoft.Json that aren't supported in System.Text.Json, you can switch back to Newtonsoft.Json. 请参阅本文前面的在ASP.NET Core 3.0 SignalR 项目中使用 Newtonsoft.JsSee Use Newtonsoft.Json in an ASP.NET Core 3.0 SignalR project earlier in this article.

Redis 分布式缓存Redis distributed caches

Redis包不适用于 ASP.NET Core 3.0 或更高版本的应用。The Microsoft.Extensions.Caching.Redis package isn't available for ASP.NET Core 3.0 or later apps. 将包引用替换为StackExchangeRedisReplace the package reference with Microsoft.Extensions.Caching.StackExchangeRedis. 有关详细信息,请参阅 ASP.NET Core 中的分布式缓存For more information, see ASP.NET Core 中的分布式缓存.

选择启用运行时编译Opt in to runtime compilation

在 ASP.NET Core 3.0 之前,视图的运行时编译是框架的隐式功能。Prior to ASP.NET Core 3.0, runtime compilation of views was an implicit feature of the framework. 运行时编译对视图的生成时编译进行了补充。Runtime compilation supplements build-time compilation of views. 它允许框架 Razor 在修改文件时编译视图和页面(cshtml文件),而无需重新生成整个应用。It allows the framework to compile Razor views and pages (.cshtml files) when the files are modified, without having to rebuild the entire app. 此功能支持在 IDE 中进行快速编辑并刷新浏览器以查看更改的方案。This feature supports the scenario of making a quick edit in the IDE and refreshing the browser to view the changes.

在 ASP.NET Core 3.0 中,运行时编译是一个可选方案。In ASP.NET Core 3.0, runtime compilation is an opt-in scenario. 生成时编译是默认情况下启用的视图编译机制。Build-time compilation is the only mechanism for view compilation that's enabled by default. 当检测到dotnet文件的更改时,运行时依赖于 Visual Studio 或 Visual Studio Code 以重新生成项目。The runtime relies on Visual Studio or dotnet-watch in Visual Studio Code to rebuild the project when it detects changes to .cshtml files. 在 Visual Studio 中,将运行的项目(Ctrl + F5)更改为 .cs、.csrazor 文件,但不进行调试(F5),这会触发项目的重新编译。In Visual Studio, changes to .cs, .cshtml, or .razor files in the project being run (Ctrl+F5), but not debugged (F5), trigger recompilation of the project.

在 ASP.NET Core 3.0 项目中启用运行时编译:To enable runtime compilation in your ASP.NET Core 3.0 project:

  1. 安装AspNetCore Razor .。RuntimeCompilation NuGet 包。Install the Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation NuGet package.

  2. Startup.ConfigureServices要调用的更新 AddRazorRuntimeCompilationUpdate Startup.ConfigureServices to call AddRazorRuntimeCompilation:

    对于 ASP.NET Core MVC,请使用以下代码:For ASP.NET Core MVC, use the following code:

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

    对于 ASP.NET Core Razor 页面,请使用以下代码:For ASP.NET Core Razor Pages, use the following code:

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

中的示例 https://github.com/aspnet/samples/tree/master/samples/aspnetcore/mvc/runtimecompilation 显示了在开发环境中有条件地启用运行时编译的示例。The sample at https://github.com/aspnet/samples/tree/master/samples/aspnetcore/mvc/runtimecompilation shows an example of enabling runtime compilation conditionally in Development environments.

有关文件编译的详细信息 Razor ,请参阅 RazorASP.NET Core 中的文件编译For more information on Razor file compilation, see RazorASP.NET Core 中的文件编译.

通过多目标迁移库Migrate libraries via multi-targeting

库通常需要支持 ASP.NET Core 的多个版本。Libraries often need to support multiple versions of ASP.NET Core. 针对以前版本的 ASP.NET Core 编译的大多数库应继续正常运行。Most libraries that were compiled against previous versions of ASP.NET Core should continue working without issues. 以下条件要求对应用进行交叉编译:The following conditions require the app to be cross-compiled:

  • 库依赖于具有二进制重大更改的功能。The library relies on a feature that has a binary breaking change.
  • 库需要利用 ASP.NET Core 3.0 中的新增功能。The library wants to take advantage of new features in ASP.NET Core 3.0.

例如:For example:

<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:Use #ifdefs to enable ASP.NET Core 3.0-specific APIs:

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 APIFor more information on using ASP.NET Core APIs in a class library, see 使用类库中的 ASP.NET Core API.

其他更改Miscellaneous changes

.NET Core 3.0 和更高版本中的验证系统将不可为 null 的参数或绑定属性视为具有 [Required] 特性。The validation system in .NET Core 3.0 and later treats non-nullable parameters or bound properties as if they had a [Required] attribute. 有关详细信息,请参阅[必需] 特性For more information, see [Required] attribute.

发布Publish

删除项目目录中的binobj文件夹。Delete the bin and obj folders in the project directory.

TestServerTestServer

对于 TestServer 直接使用泛型主机的应用,请 TestServer 在上的中创建 IWebHostBuilder ConfigureWebHostFor apps that use TestServer directly with the Generic Host, create the TestServer on an IWebHostBuilder in 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 更改Breaking API changes

查看重大更改:Review breaking changes:

带 catch 参数的终结点路由Endpoint routing with catch-all parameter

警告

由于路由中的 bugcatch-all 参数可能无法正确匹配相应路由。A catch-all parameter may match routes incorrectly due to a bug in routing. 受此 Bug 影响的应用具有以下特征:Apps impacted by this bug have the following characteristics:

  • “全部捕获”路由,例如 {**slug}"A catch-all route, for example, {**slug}"
  • “全部捕获”路由未能匹配应与之匹配的请求。The catch-all route fails to match requests it should match.
  • 删除其他路由可使“全部捕获”路由开始运行。Removing other routes makes catch-all route start working.

请参阅 GitHub bug 1867716579,了解遇到此 bug 的示例。See GitHub bugs 18677 and 16579 for example cases that hit this bug.

此 bug 的选择加入修复包含在.Net Core 3.1.301 SDK 和更高版本中。An opt-in fix for this bug is contained in .NET Core 3.1.301 SDK and later. 下面的代码设置修复此 bug 的内部开关:The following code sets an internal switch that fixes this bug:

public static void Main(string[] args)
{
   AppContext.SetSwitch("Microsoft.AspNetCore.Routing.UseCorrectCatchAllBehavior", 
                         true);
   CreateHostBuilder(args).Build().Run();
}
// Remaining code removed for brevity.

Azure App Service 上的 .NET Core 3。0.NET Core 3.0 on Azure App Service

完成 .NET Core 到 Azure App Service 的推出。The rollout of .NET Core to Azure App Service is finished. .NET Core 3.0 在所有 Azure App Service 数据中心提供。.NET Core 3.0 is available in all Azure App Service datacenters.