Новые возможности в ASP.NET Core 3.0
В этой статье описываются наиболее важные изменения в ASP.NET Core 3.0 со ссылками на соответствующую документацию.
Blazor
Blazor — это новая платформа в ASP.NET Core, предназначенная для создания интерактивного веб-интерфейса на стороне клиента с использованием .NET. Она воплощает следующие возможности:
- Создание расширенных интерактивных интерфейсов пользовательского интерфейса с помощью C#.
- совместное использование серверной и клиентской логик приложений, написанных с помощью .NET;
- отображение пользовательского интерфейса в виде HTML-страницы с CSS для широкой поддержки браузеров, в том числе для мобильных устройств.
Поддерживаемые сценарии платформы Blazor:
- повторно используемые компоненты пользовательского интерфейса (компоненты Razor);
- маршрутизация на стороне клиента;
- макеты компонентов;
- поддержка внедрения зависимостей;
- Формы и проверка
- Предоставление компонентов Razor в библиотеках классов Razor
- Взаимодействие с JavaScript
Дополнительные сведения см. в статье об ASP.NET Blazor.
Blazor Server
Blazor отделяет логику отображения компонентов от того, как применяются обновления пользовательского интерфейса. Blazor Server поддерживает размещение компонентов Razor на сервере в приложении ASP.NET Core. Обновления пользовательского интерфейса передаются через подключение SignalR. Blazor Server поддерживается только в ASP.NET Core 3.0.
Blazor WebAssembly (предварительная версия)
Приложения Blazor можно также запускать напрямую в браузере с использованием среды выполнения .NET на основе WebAssembly. Платформа Blazor WebAssembly доступна в режиме предварительной версии и не поддерживается в ASP.NET Core 3.0. Blazor WebAssembly будет поддерживаться в будущем выпуске ASP.NET Core.
составные части компонента Razor.
Приложения Blazor создаются на основе компонентов. Компоненты — это автономные блоки пользовательского интерфейса, такие как страница, диалоговое окно или форма. Это обычные классы .NET, определяющие логику отрисовки пользовательского интерфейса и обработчики событий на стороне клиента. Многофункциональные интерактивные веб-приложения можно создавать без JavaScript.
Компоненты в Blazor обычно создаются с использованием синтаксиса Razor, естественного сочетания HTML и C#. Компоненты Razor похожи на Razor Pages и представления MVC тем, что они используют Razor. В отличие от страниц и представлений, которые созданы на базе модели "запрос и ответ", компоненты используются исключительно для обработки компоновки пользовательского интерфейса.
gRPC;
gRPC:
это популярная высокопроизводительная платформа RPC (удаленный вызов процедур).
Для разработки API используется подход, при котором сначала создается контракт.
Использует современные технологии, такие как:
- HTTP/2 для транспортировки;
- буферы протоколов в качестве языка описания интерфейса;
- формат двоичной сериализации.
Предоставляет следующие возможности:
- Проверка подлинности
- двунаправленная потоковая передача и управление потоком;
- отмена и время ожидания.
К функциям gRPC в ASP.NET Core 3.0 относятся:
- Grpc.AspNetCore: платформа ASP.NET Core для размещения служб gRPC. gRPC в ASP.NET Core поддерживает интеграцию со стандартными возможностями ASP.NET Core, такими как ведение журнала, внедрение зависимостей, проверка подлинности и авторизация.
- Grpc.Net.Client — клиент gRPC для .NET Core, созданный на основе знакомого компонента
HttpClient
. - Grpc.Net.ClientFactory. Интеграция клиента gRPC с
HttpClientFactory
.
Дополнительные сведения см. в статье Общие сведения о gRPC на .NET.
SignalR
Инструкции по миграции см. в разделе об обновлении кода SignalR. Для сериализации и десериализации сообщений JSON SignalR теперь использует System.Text.Json
. Инструкции по восстановлению сериализатора на основе Newtonsoft.Json
см. в разделе Switch to Newtonsoft.Json (Переключение на Newtonsoft.JSON).
В клиентах JavaScript и .NET для SignalR добавлена поддержка автоматического повторного подключения. По умолчанию клиент пытается немедленно заново подключиться и повторить попытку через 2, 10 и 30 секунд при необходимости. Если клиент успешно повторно подключается, он получает новый идентификатор подключения. Автоматическое повторное подключение необходимо явно выбирать:
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withAutomaticReconnect()
.build();
Интервалы повторного подключения можно указать, передав массив длительности в миллисекундах:
.withAutomaticReconnect([0, 3000, 5000, 10000, 15000, 30000])
//.withAutomaticReconnect([0, 2000, 10000, 30000]) The default intervals.
Пользовательскую реализацию можно передать для полного управления интервалами повторного подключения.
Если повторное подключение не удается выполнить после последнего интервала повторного подключения:
- клиент считает, что подключение находится в автономном режиме;
- клиент прекращает попытки повторного подключения.
Во время повторных попыток подключения обновите пользовательский интерфейс приложения, чтобы уведомить пользователя о попытке повторного подключения.
Чтобы обеспечить возможность отправлять отзывы о пользовательском интерфейсе при прерывании подключения, в API клиента SignalR добавлены следующие обработчики событий:
onreconnecting
: дает разработчикам возможность отключить пользовательский интерфейс или сообщить пользователям о том, что приложение находится в автономном режиме.onreconnected
: предоставляет разработчикам возможность обновить пользовательский интерфейс после восстановления подключения.
Следующий код использует onreconnecting
для обновления пользовательского интерфейса при попытке подключения:
connection.onreconnecting((error) => {
const status = `Connection lost due to error "${error}". Reconnecting.`;
document.getElementById("messageInput").disabled = true;
document.getElementById("sendButton").disabled = true;
document.getElementById("connectionStatus").innerText = status;
});
Следующий код использует onreconnected
для обновления пользовательского интерфейса при подключении:
connection.onreconnected((connectionId) => {
const status = `Connection reestablished. Connected.`;
document.getElementById("messageInput").disabled = false;
document.getElementById("sendButton").disabled = false;
document.getElementById("connectionStatus").innerText = status;
});
SignalR 3.0 и более поздних версий предоставляется пользовательский ресурс для обработчиков авторизации, когда методу концентратора требуется авторизация. Ресурс является экземпляром HubInvocationContext
. HubInvocationContext
включает:
HubCallerContext
- Имя вызываемого метода концентратора.
- Аргументы для метода концентратора.
Рассмотрим следующий пример приложения чата, разрешающего вход нескольких организаций с помощью Azure Active Directory. Любой пользователь с учетной записью Майкрософт может войти в чат, но запрещать пользователям принимать участие в обсуждениях или просматривать журналы чата пользователей могут только члены владеющей организации. Приложение может ограничивать определенные функции для определенных пользователей.
public class DomainRestrictedRequirement :
AuthorizationHandler<DomainRestrictedRequirement, HubInvocationContext>,
IAuthorizationRequirement
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
DomainRestrictedRequirement requirement,
HubInvocationContext resource)
{
if (context.User?.Identity?.Name == null)
{
return Task.CompletedTask;
}
if (IsUserAllowedToDoThis(resource.HubMethodName, context.User.Identity.Name))
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
private bool IsUserAllowedToDoThis(string hubMethodName, string currentUsername)
{
if (hubMethodName.Equals("banUser", StringComparison.OrdinalIgnoreCase))
{
return currentUsername.Equals("bob42@jabbr.net", StringComparison.OrdinalIgnoreCase);
}
return currentUsername.EndsWith("@jabbr.net", StringComparison.OrdinalIgnoreCase));
}
}
В приведенном выше коде DomainRestrictedRequirement
служит пользовательским IAuthorizationRequirement
. Так как параметр ресурса HubInvocationContext
передается, внутренняя логика может выполнять следующее:
- проверять контекст, в котором вызывается концентратор;
- принимать решения о разрешении пользователю выполнять отдельные методы концентратора.
Отдельные методы концентратора можно пометить именем политики, которую проверяет код во время выполнения. Когда клиенты пытаются вызвать отдельные методы концентратора, обработчик DomainRestrictedRequirement
запускается и управляет доступом к методам. В зависимости от того, как DomainRestrictedRequirement
управляет доступом:
- все вошедшие в систему пользователи могут вызывать метод
SendMessage
; - просматривать журналы пользователей могут только пользователи, выполнившие вход с помощью адреса электронной почты
@jabbr.net
; - запретить пользователям участвовать в обсуждениях могут только члены
bob42@jabbr.net
.
[Authorize]
public class ChatHub : Hub
{
public void SendMessage(string message)
{
}
[Authorize("DomainRestricted")]
public void BanUser(string username)
{
}
[Authorize("DomainRestricted")]
public void ViewUserHistory(string username)
{
}
}
Для создания политики DomainRestricted
может потребоваться сделать следующее:
- Добавьте
Startup.cs
новую политику. - предоставить настраиваемое требование
DomainRestrictedRequirement
в качестве параметра; - зарегистрировать
DomainRestricted
с помощью ПО промежуточного слоя авторизации.
services
.AddAuthorization(options =>
{
options.AddPolicy("DomainRestricted", policy =>
{
policy.Requirements.Add(new DomainRestrictedRequirement());
});
});
Концентраторы SignalR используют маршрутизацию конечных точек. Подключение концентратора SignalR было ранее выполнено явным образом:
app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("hubs/chat");
});
В предыдущей версии разработчикам требовалось подключать контроллеры, страницы Razor и концентраторы в различных местах. В результате явного подключения возникает последовательность практически идентичных сегментов маршрутизации:
app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("hubs/chat");
});
app.UseRouting(routes =>
{
routes.MapRazorPages();
});
Концентраторы SignalR 3.0 можно маршрутизировать через конечные точки. При такой маршрутизации, как правило, можно настроить всю маршрутизацию в UseRouting
.
app.UseRouting(routes =>
{
routes.MapRazorPages();
routes.MapHub<ChatHub>("hubs/chat");
});
С SignalR ASP.NET Core 3.0 добавлены новые возможности.
потоковая передача между клиентом и сервером. При потоковой передаче между клиентом и сервером методы на стороне сервера могут принимать экземпляры IAsyncEnumerable<T>
или ChannelReader<T>
. В следующем примере C# метод UploadStream
в концентраторе получит поток строк от клиента:
public async Task UploadStream(IAsyncEnumerable<string> stream)
{
await foreach (var item in stream)
{
// process content
}
}
Клиентские приложения .NET могут передавать экземпляр IAsyncEnumerable<T>
или ChannelReader<T>
в качестве аргумента stream
для метода концентратора UploadStream
, приведенного выше.
После завершения цикла for
и завершения работы локальной функции отправляется завершение потока:
async IAsyncEnumerable<string> clientStreamData()
{
for (var i = 0; i < 5; i++)
{
var data = await FetchSomeData();
yield return data;
}
}
await connection.SendAsync("UploadStream", clientStreamData());
Клиентские приложения JavaScript используют Subject
SignalR (или субъект RxJS) для аргумента stream
метода концентратора UploadStream
, приведенного выше.
let subject = new signalR.Subject();
await connection.send("StartStream", "MyAsciiArtStream", subject);
Код JavaScript может использовать метод subject.next
для обработки строк по мере их записи и готовности к отправке на сервер.
subject.next("example");
subject.complete();
С помощью кода, подобного двум предыдущим фрагментам, можно создать потоковую передачу в реальном времени.
Новая сериализация JSON
ASP.NET Core 3.0 теперь по умолчанию использует System.Text.Json для сериализации JSON:
- асинхронно считывает и записывает JSON;
- оптимизирован для текста UTF-8;
- предоставляет более высокую производительность, чем
Newtonsoft.Json
.
Сведения о добавлении Json.NET в ASP.NET Core 3.0 см. в разделе Добавление поддержки формата JSON на основе Newtonsoft.Json.
Новые директивы Razor
Следующий список содержит новые директивы Razor.
@attribute
@attribute
: директива применяет заданный атрибут к классу созданной страницы или представления. Например,@attribute [Authorize]
.@implements
: директива@implements
реализует интерфейс для созданного класса. Например,@implements IDisposable
.
IdentityServer4 поддерживает проверку подлинности и авторизацию для веб-API и одностраничных приложений
ASP.NET Core 3.0 обеспечивает проверку подлинности в одностраничных приложениях с помощью поддержки авторизации веб-API. ASP.NET Core Identity для проверки подлинности и хранения пользователей объединяется с IdentityServer4 для реализации OpenID Connect.
IdentityServer4 — это платформа OpenID Connect и OAuth 2.0 для ASP.NET Core 3.0. Она обеспечивает следующие функции безопасности:
- Проверка подлинности как услуга (AaaS)
- Единый вход (SSO) для нескольких типов приложений
- Контроль доступа для API
- Шлюз федерации
Дополнительные сведения см. в документации по IdentityServer4 или статье Проверка подлинности и авторизация для одностраничных приложений.
Проверка подлинности Kerberos и проверка подлинности с помощью сертификата
Для проверки подлинности с помощью сертификата требуется:
- настройка сервера для принятия сертификатов;
- добавление ПО промежуточного слоя для проверки подлинности в
Startup.Configure
; - добавление службы проверки подлинности с помощью сертификатов в
Startup.ConfigureServices
.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(
CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate();
// Other service configuration removed.
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
// Other app configuration removed.
}
Параметры проверки подлинности с помощью сертификата включают следующие возможности:
- принятие самозаверяющих сертификатов;
- проверка отзыва сертификатов;
- проверка наличия в предложенном сертификате правильных флагов использования.
Субъект-пользователь по умолчанию создается на основе свойств сертификата. Субъект-пользователь содержит событие, которое позволяет дополнить или заменить субъект. Дополнительные сведения см. в статье Настройка проверки подлинности по сертификату в ASP.NET Core.
Проверка подлинности Windows теперь предусмотрена для Linux и macOS. В предыдущих версиях аутентификация Windows была доступна только для IIS и HTTP.sys. В ASP.NET Core 3.0 Kestrel может использовать Negotiate, Kerberos и NTLM в Windows, Linux и macOS для узлов, присоединенных к домену Windows. Поддержка в Kestrel этих схем проверки подлинности реализована в пакете Microsoft.AspNetCore.Authentication.Negotiate NuGet. Как и в других службах проверки подлинности, настройте приложение проверки подлинности во всей организации, а затем настройте службу:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate();
// Other service configuration removed.
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
// Other app configuration removed.
}
Требования к узлу:
- На узлах Windows имена субъектов-служб должны быть добавлены в учетную запись пользователя, где размещается приложение.
- Компьютеры Linux и macOS должны быть присоединены к домену.
- Имена субъектов-служб необходимо создать для веб-процесса.
- Файлы Keytab необходимо создать и настроить на компьютере узла.
Дополнительные сведения см. в статье Настройка проверки подлинности Windows в ASP.NET Core.
Изменения шаблонов
В шаблонах веб-интерфейса (Razor Pages, MVC с контроллером и представлениями) удалены следующие элементы.
- Пользовательского интерфейса согласия на файлы cookie больше нет. Сведения о том, как включить функцию согласия для файлов cookie в приложении, созданном на основе шаблона ASP.NET Core 3.0, см. в статье Поддержка Общего регламента по защите данных (GDPR) в ASP.NET Core.
- Для ссылки на скрипты и связанные статические ресурсы теперь используются локальные файлы, а не CDN. Дополнительные сведения см. в статье В версии 3.0 для ссылки на скрипты и связанные статические ресурсы теперь используются локальные файлы, а не CDN в зависимости от текущей среды (dotnet/AspNetCore.Docs № 14350).
Шаблон Angular обновлен для использования Angular 8.
По умолчанию для шаблона библиотеки классов Razor (RCL) используется разработка компонентов Razor. Новый параметр шаблона в Visual Studio обеспечивает поддержку шаблонов для страниц и представлений. При создании RCL на основе шаблона в командной оболочке передайте параметр --support-pages-and-views
(dotnet new razorclasslib --support-pages-and-views
).
Универсальный узел
Шаблоны ASP.NET Core 3.0 используют универсальный узел .NET в ASP.NET Core. В предыдущих версиях использовался WebHostBuilder. Использование универсального узла .NET Core (HostBuilder) обеспечивает лучшую интеграцию приложений ASP.NET Core с другими серверными сценариями, не зависящими от Интернета. Дополнительные сведения см. в разделе HostBuilder replaces WebHostBuilder (HostBuilder заменяет WebHostBuilder).
Конфигурация узла
До выхода ASP.NET Core 3.0 переменные среды с префиксом ASPNETCORE_
были загружены для конфигурации веб-узла. В 3.0 AddEnvironmentVariables
используется для загрузки переменных среды с префиксом DOTNET_
для конфигурации узла с помощью CreateDefaultBuilder
.
Изменения во внедрении через конструктор Startup
Универсальный узел поддерживает только следующие типы для внедрения через конструктор Startup
:
- IHostEnvironment
IWebHostEnvironment
- IConfiguration
Все службы по-прежнему можно непосредственно внедрять в метод Startup.Configure
в качестве аргументов. Дополнительные сведения см. в статье Generic Host restricts Startup constructor injection (Универсальный узел ограничивает внедрение через конструктор Startup) (№ 353).
Kestrel
- В конфигурацию Kestrel добавлена возможность миграции на универсальный узел. В версии 3.0
ConfigureWebHostDefaults
настраивается в построителе веб-узлов, предоставляемом Kestrel. - Адаптеры подключений удалены из Kestrel и заменены ПО промежуточного слоя подключения, которое похоже на ПО промежуточного слоя HTTP в конвейере ASP.NET Core, но для подключений более низкого уровня.
- Транспортный уровень Kestrel предоставляется как открытый интерфейс в
Connections.Abstractions
. - Неоднозначность заголовков и конечных строк устранена путем перемещения конечных заголовков в новую коллекцию.
- Из-за таких интерфейсов API с синхронными операциями ввода-вывода, как
HttpRequest.Body.Read
, часто возникает нехватка потоков, что приводит к сбоям приложений. В 3.0AllowSynchronousIO
отключен по умолчанию.
Дополнительные сведения см. в статье Миграция с ASP.NET Core 2.2 на 3.0.
HTTP/2 включено по умолчанию.
В Kestrel для конечных точек HTTPS по умолчанию включен протокол HTTP/2. Поддержка HTTP/2 для IIS или HTTP.sys включена, если поддерживается операционной системой.
EventCounters по запросу
EventSource размещения, Microsoft.AspNetCore.Hosting
, выдает следующие новые типы EventCounter, связанные с входящими запросами:
requests-per-second
total-requests
current-requests
failed-requests
Маршрутизация конечных точек
Маршрутизация конечных точек, позволяющая платформам (например, MVC) хорошо работать с ПО промежуточного слоя, усовершенствована:
- порядок ПО промежуточного слоя и конечных точек можно настроить в конвейере обработки запросов
Startup.Configure
; - конечные точки и ПО промежуточного слоя хорошо используются с другими технологиями на основе ASP.NET Core, такими как проверки работоспособности;
- конечные точки могут реализовывать политику, например CORS или авторизацию, в ПО промежуточного слоя и MVC;
- фильтры и атрибуты можно разместить в методах контроллеров.
Подробные сведения см. в статье Маршрутизация в ASP.NET Core.
Проверки работоспособности
Для проверок работоспособности используется маршрутизация конечных точек с универсальным узлом. В Startup.Configure
вызовите MapHealthChecks
для построителя конечной точки с URL-адресом конечной точки или относительным путем:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
});
Конечные точки проверки работоспособности могут:
- указать один или несколько разрешенных узлов или портов;
- требовать авторизацию;
- требовать CORS.
Дополнительные сведения см. в следующих статьях:
Каналы в HttpContext
Теперь можно читать текст запроса и писать текст ответа с помощью API System.IO.Pipelines. Свойство HttpRequest.BodyReader
предоставляет объект PipeReader , который можно использовать для чтения текста запроса. Свойство HttpResponse.BodyWriter
предоставляет объект PipeWriter , который можно использовать для записи текста ответа. HttpRequest.BodyReader
— это аналог потока HttpRequest.Body
. HttpResponse.BodyWriter
— это аналог потока HttpResponse.Body
.
Улучшены сообщения об ошибках в IIS
Теперь при ошибках запуска во время размещения приложений ASP.NET Core в IIS предоставляются более полные диагностические данные. Сведения об этих ошибках передаются в журнал событий Windows с трассировками стека везде, где это применимо. Кроме того, все предупреждения, ошибки и необработанные исключения записываются в журнал событий Windows.
Служба рабочих ролей и пакет SDK для рабочей роли
В .NET Core 3.0 появился новый шаблон приложения службы рабочих ролей. Этот шаблон может служить отправной точкой для написания длительных приложений служб в .NET Core.
Дополнительные сведения см. в разделе:
- .NET Core Workers as Windows Services (Рабочие роли .NET Core в качестве служб Windows)
- Фоновые задачи с размещенными службами в ASP.NET Core
- Узел ASP.NET Core в службе Windows
Улучшения ПО промежуточного слоя перенаправления заголовков
В предыдущих версиях ASP.NET Core вызвать UseHsts и UseHttpsRedirection было проблематично при развертывании в Azure Linux или за любым обратным прокси-сервером, отличным от IIS. Исправление для предыдущих версий описано в разделе Переадресация схемы для Linux и обратных прокси-серверов не IIS.
Этот сценарий исправлен в ASP.NET Core 3.0. Узел включает ПО промежуточного слоя перенаправления заголовков, если переменной среды ASPNETCORE_FORWARDEDHEADERS_ENABLED
присвоено значение true
. В образах контейнера для ASPNETCORE_FORWARDEDHEADERS_ENABLED
задано значение true
.
Улучшения производительности
В ASP.NET Core 3.0 реализованы многочисленные улучшения, сокращающие использование памяти и повышающие пропускную способность:
- сокращение использования памяти при использовании встроенного контейнера внедрения зависимостей для служб с заданной областью;
- сокращение количества распределений на платформе, включая сценарии ПО промежуточного слоя и маршрутизацию;
- сокращение использования памяти для подключений WebSocket;
- сокращение использования памяти и улучшение пропускной способности для подключений по протоколу HTTPS;
- новый оптимизированный и полностью асинхронный сериализатор JSON;
- сокращение использования памяти и улучшения пропускной способности при анализе формы.
ASP.NET Core 3.0 работает только в .NET Core 3.0
Начиная с ASP.NET Core 3.0, .NET Framework больше не является поддерживаемой целевой платформой. Проекты, предназначенные для .NET Framework, можно полноценно использовать с помощью выпуска LTS .NET Core 2.1. Большинство пакетов, связанных с ASP.NET Core 2.1.x, будут поддерживаться неограниченно после истечения трехлетнего периода LTS для .NET Core 2.1.
Сведения о миграции см. в статье Перенос кода в .NET Core из .NET Framework.
Использование общей платформы .NET Core
Для общей платформы ASP.NET Core 3.0, содержащейся в метапакете Microsoft.AspNetCore.app, больше не требуется явный элемент <PackageReference />
в файле проекта. При использовании пакета SDK Microsoft.NET.Sdk.Web
в файле проекта автоматически создается ссылка на общую платформу:
<Project Sdk="Microsoft.NET.Sdk.Web">
Сборки, удаленные из общей платформы ASP.NET Core
Наиболее важные сборки, удаленные из общей платформы ASP.NET Core 3.0:
- Newtonsoft.Json (Json.NET). Сведения о добавлении Json.NET в ASP.NET Core 3.0 см. в разделе Добавление поддержки формата JSON на основе Newtonsoft.Json. В ASP.NET Core 3.0 внедрен
System.Text.Json
для чтения файла JSON и записи в него. Дополнительные сведения см. в разделе Новая сериализация JSON в этом документе. - Entity Framework Core
Полный список сборок, удаленных из общей платформы, см. в разделе Assemblies being removed from Microsoft.AspNetCore.App 3.0 (Сборки, удаленные из Microsoft.AspNetCore.App 3.0). Дополнительные сведения о мотивации для этого изменения см. в статье Breaking changes to Microsoft.AspNetCore.App in 3.0 (Критические изменения в Microsoft.AspNetCore.App 3.0) и записи блога A first look at changes coming in ASP.NET Core 3.0 (Первое знакомство с изменениями в ASP.NET Core 3.0).
ASP.NET Core