Миграция с ASP.NET Core 2.2.x на 3.0

Скотт Адди и Рик Андерсон

В этой статье объясняется, как обновить существующий проект ASP.NET Core 2.2 до ASP.NET Core 3.0. Возможно, полезно создать новый проект ASP.NET Core 3.0 для:

  • Сравните с кодом ASP.NET Core 2.2.
  • Скопируйте соответствующие изменения в проект ASP.NET Core 3.0.

Необходимые компоненты

Обновление версии пакета SDK для .NET Core в global.json

Если решение использует global.json файл для целевой версии пакета SDK для .NET Core, обновите его version свойство до версии 3.0, установленной на компьютере:

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

Обновление файла проекта

Обновление целевой платформы

ASP.NET Core 3.0 и более поздних версий запускаются только в .NET Core. Задайте для Moniker целевой платформы (TFM) значение netcoreapp3.0:

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

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

</Project>

Удаление устаревших ссылок на пакеты

Большое количество пакетов NuGet не создается для ASP.NET Core 3.0. Такие ссылки на пакеты должны быть удалены из файла проекта. Рассмотрим следующий файл проекта для веб-приложения ASP.NET Core 2.2:

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

  <PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>
    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App"/>
    <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
  </ItemGroup>

</Project>

Обновленный файл проекта для ASP.NET Core 3.0:

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

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

</Project>

Обновленный файл проекта ASP.NET Core 3.0:

  • В <PropertyGroup>:

    • Обновления TFM вnetcoreapp3.0
    • Удаляет <AspNetCoreHostingModel> элемент. Дополнительные сведения см . в модели размещения в процессе в этом документе.
  • В <ItemGroup>:

    • Microsoft.AspNetCore.App удален. Дополнительные сведения см . в справочнике по Framework в этом документе.
    • 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.Razor. ViewCompilation
  • 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.Kestrel. Https
  • Microsoft.AspNetCore.Server.Kestrel. Transport.Abstractions
  • Microsoft.AspNetCore.Server.Kestrel. Transport.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-файлы), которые установлены на компьютере, содержащий компонент среды выполнения и целевой пакет. Дополнительную информацию см. в этой публикации об общей платформе.

  • Проекты, предназначенные для пакета SDK Microsoft.NET.Sdk.Web, неявно ссылаются на платформу Microsoft.AspNetCore.App.

    Для этих проектов не требуются дополнительные ссылки:

    <Project Sdk="Microsoft.NET.Sdk.Web">
      <PropertyGroup>
        <TargetFramework>netcoreapp3.0</TargetFramework>
      </PropertyGroup>
        ...
    </Project>
    
  • Проекты, предназначенные для проектов Microsoft.NET.Sdk или Microsoft.NET.Sdk.Razor пакета SDK, должны добавлять явные FrameworkReference элементы в Microsoft.AspNetCore.App:

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

Сборки, зависящие от платформы, с помощью Docker

Сборки, зависящие от платформы консольных приложений, использующих пакет, зависящий от общей платформы ASP.NET Core, могут привести к следующей ошибке среды выполнения:

It was not possible to find any compatible framework version
The specified framework 'Microsoft.AspNetCore.App', version '3.0.0' was not found.
  - No frameworks were found.

Microsoft.AspNetCore.App является общей платформой, содержащей среду выполнения ASP.NET Core и присутствует только на образе dotnet/core/aspnet Docker. Пакет SDK 3.0 уменьшает размер зависимых от платформ сборок с помощью ASP.NET Core, не включая дубликаты библиотек, доступных в общей платформе. Это потенциальная экономия до 18 МБ, но требуется, чтобы среда выполнения ASP.NET Core присутствовала / установлена для запуска приложения.

Чтобы определить, имеет ли приложение зависимость (прямое или косвенное) в общей платформе ASP.NET Core, изучите runtimeconfig.json файл, созданный во время сборки или публикации приложения. JSСледующий ON-файл показывает зависимость от общей платформы 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:

shared framework assemblies comparison

Чтобы продолжить использование функций, предоставляемых удаленными сборками, ознакомьтесь с версиями 3.0 соответствующих пакетов:

Изменения при запуске

На следующем рисунке показаны удаленные и измененные строки в веб-приложении ASP.NET Core 2.2 Razor Pages:

the deleted and changed lines in an ASP.NET Core 2.2 Razor Web app

На предыдущем рисунке удаленный код отображается красным цветом. Удаленный код не отображает cookie код параметров, который был удален до сравнения файлов.

На следующем рисунке показаны добавленные и измененные строки в веб-приложении ASP.NET Core 3.0 Razor Pages:

the added and changed lines in an ASP.NET Core 3.0 Razor Web app

На предыдущем изображении добавленный код отображается зеленым цветом. Дополнительные сведения о следующих изменениях:

  • services.AddMvc To services.AddRazorPages, см . регистрацию службы MVC в этом документе.
  • CompatibilityVersion, см . версию совместимости для ASP.NET Core MVC.
  • IHostingEnvironment значение IWebHostEnvironment/> см . в этом объявлении GitHub.
  • app.UseAuthorization добавлен в шаблоны для отображения по промежуточного слоя авторизации заказа необходимо добавить. Если приложение не использует авторизацию, вы можете безопасно удалить вызов app.UseAuthorization.
  • app.UseEndpoints, см. статью Razor Pages или Migrate Startup.Configure в этом документе.

Поддержка анализатора

Проекты, предназначенные для Microsoft.NET.Sdk.Web неявно ссылающихся на анализаторы, ранее отправленные в составе пакета Microsoft.AspNetCore.Mvc.Analyzers . Для включения этих дополнительных ссылок не требуется.

Если приложение использует анализаторы API, ранее отправленные с помощью пакета Microsoft.AspNetCore.Mvc.Api.Analyzers, измените файл проекта, чтобы ссылаться на анализаторы, отправленные в составе веб-пакета SDK для .NET Core:

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

    ...
</Project>

Razor Библиотека классов

Razor Проекты библиотеки классов, предоставляющие компоненты пользовательского интерфейса для MVC, должны задать AddRazorSupportForMvc свойство в файле проекта:

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

Модель внутрипроцессного размещения

Проекты по умолчанию предназначены для модели размещения в процессе в ASP.NET Core 3.0 или более поздней версии. При необходимости можно удалить <AspNetCoreHostingModel> свойство в файле проекта, если его значение равно InProcess.

Kestrel

Настройка

Миграция Kestrel конфигурации в построитель веб-узлов, 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>();
        });

Если приложение создает узел вручную вместо ConfigureWebHostConfigureWebHostDefaultsэтого, вызовите UseKestrel построитель веб-узлов:

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

    host.Run();
}

ПО промежуточного слоя Подключение ion заменяет адаптеры Подключение ion

Подключение адаптеры (Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal.IConnectionAdapter) были удалены.Kestrel Замените адаптеры Подключение ion на ПО промежуточного слоя Подключение ion. по промежуточному слоям Подключение ion аналогичен ПО промежуточного слоя HTTP в конвейере ASP.NET Core, но для подключений более низкого уровня. Ведение журнала HTTPS и подключения:

  • Были перемещены из адаптеров Подключение ion в по промежуточное по промежуточное поверх Подключение ion.
  • Эти методы расширения работают как в предыдущих версиях ASP.NET Core.

Дополнительные сведения см. в примере TlsFilter Подключение ionHandler в разделе ListenOptions.Protocols статьиKestrel.

Абстракции транспорта перемещаются и делаются общедоступными

Транспортный уровень 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 в коллекцию заголовков запросов.
  • Трейлеры доступны после того, как текст запроса считывается до конца.

Это вызывает некоторые опасения по поводу неоднозначности между заголовками и трейлерами, поэтому трейлеры были перемещены в новую коллекцию (RequestTrailerExtensions) в 3.0.

Трейлеры запросов HTTP/2:

  • Недоступно в ASP.NET Core 2.2.
  • Доступно в версии 3.0 как RequestTrailerExtensions.

Новые методы расширения запроса присутствуют для доступа к этим трейлерам. Как и в случае с HTTP/1.1, трейлеры доступны после того, как текст запроса считывается до конца.

Для выпуска 3.0 доступны следующие RequestTrailerExtensions методы:

  • GetDeclaredTrailers: получает заголовок запроса Trailer , в котором перечислены трейлеры, которые следует ожидать после текста.
  • SupportsTrailers: указывает, поддерживает ли запрос получение заголовков трейлера.
  • CheckTrailersAvailable: проверяет, поддерживает ли запрос трейлеры и доступен ли он для чтения. Это проверка не предполагает, что есть трейлеры для чтения. Не может быть трейлеров для чтения, даже если true возвращается этим методом.
  • GetTrailer: получает запрошенный заголовок конечного пути из ответа. Проверьте SupportsTrailers перед вызовом GetTrailerNotSupportedException или может возникнуть, если запрос не поддерживает конечные заголовки.

Дополнительные сведения см. в статье Put request trailers in a separate collection (dotnet/AspNetCore #10410).

AllowSynchronousIO отключен

AllowSynchronousIO включает или отключает синхронные API ввода-вывода, например HttpRequest.Body.Read, HttpResponse.Body.Writeи Stream.Flush. Эти API являются источником нехватки потоков, что приводит к сбою приложения. В 3.0 AllowSynchronousIO отключен по умолчанию. Дополнительные сведения см. в разделе "Синхронный ввод-вывод" статьиKestrel.

Если требуется синхронный ввод-вывод, его можно включить, настроив AllowSynchronousIO параметр на используемом сервере (например, при вызовеConfigureKestrelKestrel). Обратите внимание, что все серверы (KestrelhttpSys, TestServer и т. д.) имеют собственный AllowSynchronousIO вариант, который не влияет на другие серверы. Синхронный ввод-вывод можно включить для всех серверов на основе каждого запроса с помощью IHttpBodyControlFeature.AllowSynchronousIO параметра:

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

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

Если у вас возникли проблемы с TextWriter реализацией или другими потоками, которые вызывают синхронные API в Dispose, вызовите новый DisposeAsync API.

Дополнительные сведения см. в разделе [Объявление] AllowSynchronousIO отключен на всех серверах (dotnet/AspNetCore #7644).

Буферизация выходного форматирования

Newtonsoft.JsonXmlSerializer и DataContractSerializer выходные форматировщики на основе поддерживают только синхронную сериализацию. Чтобы разрешить этим модулям форматирования работать с ограничениями AllowSynchronousIO сервера, MVC буферизирует выходные данные этих средств форматирования перед записью на диск. В результате буферизации MVC будет включать заголовок Content-Length при реагировании на эти средства форматирования.

System.Text.Json поддерживает асинхронную сериализацию и, следовательно, System.Text.Json модуль форматирования на основе не буферизирует. Рассмотрите возможность использования этого средства форматирования для повышения производительности.

Чтобы отключить буферизацию, приложения могут настроить SuppressOutputFormatterBuffering в запуске:

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

Обратите внимание, что это может привести к тому, что приложение создает исключение среды выполнения, если AllowSynchronousIO не настроено.

Microsoft.AspNetCore.Server.Kestrel. Удалена сборка https

В ASP.NET Core 2.1 содержимое Microsoft.AspNetCore.Server.Kestrel. Https.dll были перемещены в Microsoft.AspNetCore.Server.Kestrel. Core.dll. Это было неразрывное обновление с помощью TypeForwardedTo атрибутов. Для версии 3.0 пустой Microsoft.AspNetCore.Server.Kestrel. Сборка Https.dll и пакет NuGet удалены.

Библиотеки, ссылающиеся на Microsoft.AspNetCore.Server.Kestrel. Https должен обновлять зависимости ядра ASP.NET до версии 2.1 или более поздней версии.

Приложения и библиотеки, предназначенные для ASP.NET Core 2.1 или более поздней версии, должны удалять любые прямые ссылки на Microsoft.AspNetCore.Server.Server.Kestrel Пакет https .

Поддержка Newtonsoft.Json (Json.NET)

В рамках работы по улучшению общей платформы ASP.NET Core newtonsoft.Json (Json.NET) было удалено из общей платформы ASP.NET Core.

Сериализатор ON по умолчанию JSдля ASP.NET Core теперь является System.Text.Jsonновым в .NET Core 3.0. Рекомендуется использовать System.Text.Json , когда это возможно. Это высокая производительность и не требует дополнительной зависимости библиотеки. Тем не менее, так как System.Text.Json это новое, в настоящее время может быть отсутствуют функции, необходимые вашему приложению. Дополнительные сведения см. в разделе "Миграция из Newtonsoft.Json в System.Text.Json".

Использование Newtonsoft.Json в проекте ASP.NET Core 3.0 SignalR

  • Установите Microsoft.AspNetCore.SignalR. Пакет NuGet Protocols.NewtonsoftJson.

  • В клиенте выполните цепочку AddNewtonsoftJsonProtocol вызова метода к экземпляру HubConnectionBuilder :

    new HubConnectionBuilder()
        .WithUrl("/chathub")
        .AddNewtonsoftJsonProtocol(...)
        .Build();
    
  • На сервере прицедим AddNewtonsoftJsonProtocol вызов метода к вызову AddSignalR метода в Startup.ConfigureServices:

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

Использование Newtonsoft.Json в проекте MVC ASP.NET Core 3.0

  • Установите пакет 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.Json вместо Microsoft.AspNetCore.Mvc.NewtonsoftJson пакета.

Дополнительные сведения см. в разделе "Добавление поддержки формата ON на основе JSNewtonsoft.Json".

Регистрация службы MVC

ASP.NET Core 3.0 добавляет новые параметры для регистрации сценариев MVC внутри Startup.ConfigureServices.

Доступны три новых метода расширения верхнего уровня, связанных с сценариями IServiceCollection MVC. Шаблоны используют эти новые методы вместо AddMvc. Однако продолжает вести себя так же, AddMvc как и в предыдущих выпусках.

В следующем примере добавлена поддержка контроллеров и функций, связанных с API, но не представлений или страниц. Шаблон API использует этот код:

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

В следующем примере добавлена поддержка контроллеров, функций, связанных с API, и представлений, но не страниц. Шаблон веб-приложения (MVC) использует следующий код:

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

В следующем примере добавлена поддержка Razor Pages и минимальная поддержка контроллера. Шаблон веб-приложения использует этот код:

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

Новые методы также можно объединить. Следующий пример эквивалентен вызову AddMvc в ASP.NET Core 2.2:

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

Код запуска маршрутизации

Если приложение вызывает UseMvc или UseSignalRпереносите приложение в маршрутизацию конечных точек, если это возможно. Чтобы улучшить совместимость маршрутизации конечных точек с предыдущими версиями MVC, мы отменить изменения некоторые изменения в создании URL-адресов, представленных в ASP.NET Core 2.2. Если вы столкнулись с проблемами с маршрутизацией конечных точек в версии 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.Configure

Общие советы:

Следующий код является примером 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?}");
    });
}

Предупреждение

Для большинства приложений вызовы UseAuthenticationUseAuthorizationUseCors и должны отображаться между вызовами UseRouting и UseEndpoints быть эффективными.

Проверки работоспособности

Для проверок работоспособности используется маршрутизация конечных точек с универсальным узлом. В Startup.Configure вызовите MapHealthChecks для построителя конечной точки с URL-адресом конечной точки или относительным путем:

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 Authorization (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. Как и в предыдущих версиях, каждый концентратор явно указан.

В следующем примере добавлена поддержка концентратора ChatHubSignalR :

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

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

Существует новый вариант управления ограничениями размера сообщений от клиентов. Например, для Startup.ConfigureServices:

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

В ASP.NET Core 2.2 можно задать TransportMaxBufferSize и эффективно контролировать максимальный размер сообщения. В ASP.NET Core 3.0 этот параметр теперь определяет только максимальный размер, прежде чем наблюдается обратная прессура.

SignalR сборки в общей платформе

ASP.NET сборки на SignalR стороне сервера теперь устанавливаются с помощью пакета SDK для .NET Core. Дополнительные сведения см. в разделе "Удаление устаревших ссылок на пакеты" в этом документе.

Контроллеры MVC

Сопоставление контроллеров теперь происходит внутри UseEndpoints.

Добавьте, MapControllers использует ли приложение маршрутизацию атрибутов. Так как маршрутизация включает поддержку многих платформ в ASP.NET Core 3.0 или более поздней версии, добавление контроллеров с перенаправлением атрибутов является согласием.

Вместо

  • MapRoute с MapControllerRoute
  • MapAreaRoute с MapAreaControllerRoute

Так как маршрутизация теперь включает поддержку более чем просто MVC, терминология изменилась, чтобы сделать эти методы четко о том, что они делают. Обычные маршруты, такие как MapControllerRoute//MapAreaControllerRouteMapDefaultControllerRoute применены в порядке их добавления. Сначала поместите более конкретные маршруты (например, маршруты для области).

В следующем примере :

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

Удаление асинхронного суффикса из имен действий контроллера

В ASP.NET Core 3.0 ASP.NET Core MVC удаляет Async суффикс из имен действий контроллера. Создание маршрутизации и канала влияет на это новое значение по умолчанию. Например:

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

До ASP.NET Core 3.0:

  • К предыдущему действию можно получить доступ по маршруту Products/ListAsync .

  • Необходимое создание ссылок, указывающее Async суффикс. Например:

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

В ASP.NET Core 3.0:

  • К предыдущему действию можно получить доступ по маршруту Products/List .

  • Для создания ссылок не требуется указывать Async суффикс. Например:

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

Это изменение не влияет на имена, указанные с атрибутом [ActionName]. Поведение по умолчанию можно отключить с помощью следующего кода:Startup.ConfigureServices

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

Существуют некоторые различия в создании ссылок (например, с помощью Url.Link и аналогичных API). Например:

  • По умолчанию при использовании маршрутизации конечных точек регистр параметров маршрута в созданных URI не обязательно сохраняется. Это поведение можно контролировать с помощью IOutboundParameterTransformer интерфейса.
  • Создание URI для недопустимого маршрута (контроллер или действие или страница, которая не существует) создаст пустую строку в маршрутизации конечных точек вместо создания недопустимого URI.
  • Внешние значения (параметры маршрута из текущего контекста) не используются автоматически в создании ссылок с маршрутизацией конечных точек. Ранее при создании ссылки на другое действие (или страница) неопределенные значения маршрутов будут выводиться из текущих значений окружения маршрутов. При использовании маршрутизации конечных точек все параметры маршрута должны быть явно указаны во время создания канала.

Razor Pages

Теперь страницы сопоставления Razor происходят внутри UseEndpoints.

Добавьте, MapRazorPages использует Razor ли приложение Pages. Так как маршрутизация конечных точек включает поддержку для многих платформ, добавление Razor Pages теперь входит в систему.

В следующем Startup.Configure методе MapRazorPages добавляется поддержка Razor Pages:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

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

Использование MVC без маршрутизации конечных точек

Использование MVC через UseMvcUseMvcWithDefaultRoute или в ASP.NET Core 3.0 требует явного согласия внутри 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. Преимущество использования 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 используют универсальный узел. Предыдущие версии использовали веб-узел. В следующем коде показан созданный Program класс шаблона ASP.NET Core 3.0:

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

В следующем коде показан класс, созданный Program шаблоном ASP.NET Core 2.2:

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.

Наиболее значительным изменением является WebHostBuilderHostBuilderвнедрение зависимостей (DI). При использовании HostBuilderможно внедрить только следующий код в Startupконструктор:

Ограничения HostBuilder DI:

  • Включите создание контейнера DI только один раз.
  • Избегает возникающих проблем со временем существования объекта, таких как разрешение нескольких экземпляров одноэлементных объектов.

Дополнительные сведения см. в разделе "Избегание внедрения службы запуска" в ASP.NET Core 3.

ДобавлениеAuthorization перемещено в другую сборку

Методы 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 Пользовательского интерфейса

Identity Обновления пользовательского интерфейса для ASP.NET Core 3.0:

SignalR

SignalR Клиент JavaScript изменился на @aspnet/signalr@microsoft/signalr. Чтобы реагировать на это изменение, измените ссылки в package.json файлах, require инструкциях и инструкциях ECMAScript import .

System.Text.Json — это протокол по умолчанию

System.Text.Json Теперь используется протокол концентратора по умолчанию, используемый как клиентом, так и сервером.

В Startup.ConfigureServicesвызове AddJsonProtocol для задания параметров сериализатора.

Сервер:

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

Клиент —

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

Переключение на Newtonsoft.Json

Если вы используете функции Newtonsoft.Json, которые не поддерживаются в System.Text.Json, вы можете вернуться в Newtonsoft.Json. См. статью "Использование Newtonsoft.Json" в проекте ASP.NET Core 3.0 SignalR ранее в этой статье.

Распределенные кэши Redis

Пакет Microsoft.Extensions.Caching.Redis недоступен для приложений ASP.NET Core 3.0 или более поздних версий. Замените ссылку на пакет microsoft.Extensions.Caching.StackExchangeRedis. Дополнительные сведения см. в статье Распределенное кэширование в ASP.NET Core.

Согласие на компиляцию во время выполнения

До ASP.NET Core 3.0 компиляция представлений во время выполнения была неявной функцией платформы. Компиляция среды выполнения дополняет компиляцию представлений во время сборки. Она позволяет платформе компилировать Razor представления и страницы (.cshtml файлы) при изменении файлов, не перестроив все приложение. Эта функция поддерживает сценарий быстрого редактирования в интегрированной среде разработки и обновления браузера для просмотра изменений.

В ASP.NET Core 3.0 компиляция среды выполнения — это сценарий согласия. Компиляция во время сборки — единственный механизм для компиляции представлений, включенной по умолчанию. Среда выполнения использует Visual Studio или dotnet-watch в Visual Studio Code для перестроения проекта при обнаружении изменений в .cshtml файлах. В Visual Studio изменения .cs.cshtml.razor или файлы в выполняемом проекте (CTRL+F5), но не отлаживаются (F5), активируют перекомпиляцию проекта.

Чтобы включить компиляцию среды выполнения в проекте ASP.NET Core 3.0:

  1. Установите Microsoft.AspNetCore.Mvc.Razor. Пакет NuGet runtimeCompilation.

  2. Обновление Startup.ConfigureServices для вызова AddRazorRuntimeCompilation:

    Для ASP.NET Core MVC используйте следующий код:

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

    Для ASP.NET Core Razor Pages используйте следующий код:

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

В примере https://github.com/aspnet/samples/tree/main/samples/aspnetcore/mvc/runtimecompilation показан пример включения компиляции среды выполнения условно в средах разработки.

Дополнительные сведения о Razor компиляции файлов см. в статье 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 для включения API-интерфейсов ASP.NET Core 3.0:

var webRootFileProvider =
#if NETCOREAPP3_0
    GetRequiredService<IWebHostEnvironment>().WebRootFileProvider;
#elif NETSTANDARD2_0
    GetRequiredService<IHostingEnvironment>().WebRootFileProvider;
#else
#error unknown target framework
#endif

Дополнительные сведения об использовании api ASP.NET Core в библиотеке классов см. в разделе "Использование api ASP.NET Core" в библиотеке классов.

Прочие изменения

Система проверки в .NET Core 3.0 и более поздних версий рассматривает не допускающие значение NULL параметры или свойства привязки так, как если бы они имели атрибут [Required]. Дополнительные сведения см. в разделе [Обязательный] атрибут.

Публикация

Удалите папки bin и obj в каталоге проекта.

TestServer

Для приложений, которые используются TestServer непосредственно с универсальным узлом, создайте его TestServer в IWebHostBuilderConfigureWebHost:

[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

Предупреждение

Соответствие параметра catch-all маршрутам может быть неправильным из-за ошибки в маршрутизации. Приложения, на работу которых влияет эта ошибка, обладают следующими характеристиками:

  • Маршрут catch-all, например {**slug}".
  • Маршрут catch-all не соответствует необходимым запросам.
  • После удаления других маршрутов маршрут catch-all начинает функционировать должным образом.

Ознакомьтесь с примерами 18677 и 16579, в которых встречается эта ошибка, на сайте GitHub.

Опциональное исправление для этой ошибки содержится в пакете SDK для .NET Core начиная с версии 3.1.301. Следующий код задает внутренний переключатель, исправляющий эту ошибку:

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 в службе приложение Azure

Развертывание .NET Core для приложение Azure service завершено. .NET Core 3.0 доступен во всех центрах обработки данных приложение Azure служб.

модуль ASP.NET Core (ANCM)

Если модуль ASP.NET Core (ANCM) не был выбранным компонентом при установке Visual Studio или если в системе установлена предварительная версия ANCM, скачайте последнюю версию установщика пакета размещения .NET Core (прямая загрузка) и запустите установщик. Дополнительные сведения см. в разделе "Пакет размещения".