Прочитать на английском

Поделиться через


Новые возможности ASP.NET Core 10.0

В этой статье рассматриваются наиболее значительные изменения в ASP.NET Core 10.0 со ссылками на соответствующую документацию.

Эта статья будет обновлена по мере доступности новых предварительных выпусков. Пока эта страница не обновлена, см. страницу анонса Asp.Net Core.

Blazor

В этом разделе описываются новые функции для Blazor.

параметр QuickGridRowClass

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

<QuickGrid ... RowClass="GetRowCssClass">
    ...
</QuickGrid>

@code {
    private string GetRowCssClass(MyGridItem item) =>
        item.IsArchived ? "row-archived" : null;
}

Дополнительные сведения см. в ASP.NET Core Blazor "QuickGrid" компоненте.

скрипт Blazor как статический веб-ресурс

В предыдущих выпусках .NET скрипт Blazor обслуживается из внедренного ресурса в общей платформе ASP.NET Core. В .NET версии 10 или более поздней скрипт Blazor предоставляется как статический веб-ресурс с автоматическим сжатием и уникальными идентификаторами.

Дополнительные сведения см. в следующих ресурсах:

Основные сведения о шаблоне маршрута

Атрибут [Route] теперь поддерживает выделение синтаксиса маршрутов для визуализации структуры шаблона маршрута:

шаблон маршрута атрибута для значения счетчика показывает подсветку синтаксиса

Ранее NavigationManager.NavigateTo прокручивался в начало страницы при навигации на той же странице. Это поведение было изменено в .NET 10, чтобы браузер больше не прокручивал в верх страницы при переходе на ту же самую страницу. Это означает, что окно просмотра больше не сбрасывается при изменении адреса текущей страницы, например, при изменении строки запроса или фрагмента.

Компонент пользовательского интерфейса повторного подключения, добавленный в шаблон проекта Blazor Web App

Теперь шаблон проекта Blazor Web App включает компонент ReconnectModal, включая составную таблицу стилей и файлы JavaScript, для улучшения контроля разработчика над пользовательским интерфейсом повторного подключения, когда клиент теряет подключение WebSocket к серверу. Компонент не вставляет стили программным образом, обеспечивая соответствие более строгим параметрам политики безопасности содержимого (CSP) для политики style-src. В предыдущих выпусках пользовательский интерфейс повторного подключения по умолчанию был создан платформой таким образом, что может привести к нарушениям CSP. Обратите внимание, что пользовательский интерфейс повторного подключения по умолчанию по-прежнему используется в качестве резервного элемента, если приложение не определяет пользовательский интерфейс повторного подключения, например с помощью компонента ReconnectModal шаблона проекта или аналогичного пользовательского компонента.

Новые возможности пользовательского интерфейса повторного подключения:

  • Помимо указания состояния повторного подключения, задав определенный класс CSS в элементе пользовательского интерфейса повторного подключения, новое событие components-reconnect-state-changed отправляется для изменения состояния повторного подключения.
  • Код может лучше различать этапы процесса повторного подключения с новым состоянием повторного подключения "retrying", указанным как классом CSS, так и новым событием.

Дополнительные сведения см. в статье Руководство по ASP.NET Core BlazorSignalR.

Игнорировать строку запроса и фрагмент при использовании NavLinkMatch.All

Компонент NavLink теперь игнорирует строку запроса и фрагмент при использовании значения NavLinkMatch.All для параметра Match. Это означает, что ссылка сохраняет класс active, если путь URL совпадает, но строка запроса или фрагмент изменяется. Чтобы вернуться к исходному поведению, используйте переключатель Microsoft.AspNetCore.Components.Routing.NavLink.EnableMatchAllForQueryStringAndFragmentAppContext, установленный на true.

Можно также переопределить метод ShouldMatch на NavLink, чтобы настроить поведение сопоставления:

public class CustomNavLink : NavLink
{
    protected override bool ShouldMatch(string currentUriAbsolute)
    {
        // Custom matching logic
    }
}

Дополнительные сведения см. в статье Маршрутизация ASP.NET Core Blazor и навигация.

Закрыть параметры столбца QuickGrid

Теперь можно закрыть пользовательский интерфейс параметров столбца QuickGrid с помощью нового метода CloseColumnOptionsAsync.

В следующем примере метод CloseColumnOptionsAsync используется для закрытия пользовательского интерфейса параметров столбца сразу после применения фильтра заголовков:

<QuickGrid @ref="movieGrid" Items="movies">
    <PropertyColumn Property="@(m => m.Title)" Title="Title">
        <ColumnOptions>
            <input type="search" @bind="titleFilter" placeholder="Filter by title" 
                @bind:after="@(() => movieGrid.CloseColumnOptionsAsync())" />
        </ColumnOptions>
    </PropertyColumn>
    <PropertyColumn Property="@(m => m.Genre)" Title="Genre" />
    <PropertyColumn Property="@(m => m.ReleaseYear)" Title="Release Year" />
</QuickGrid>

@code {
    private QuickGrid<Movie>? movieGrid;
    private string titleFilter = string.Empty;
    private IQueryable<Movie> movies = new List<Movie> { ... }.AsQueryable();
    private IQueryable<Movie> filteredMovies => 
        movies.Where(m => m.Title!.Contains(titleFilter));
}

Настройка потоковой передачи ответов является добровольной и как отказаться от нее.

В предыдущих Blazor выпусках потоковая передача ответов для HttpClient запросов была опциональной. Теперь потоковая передача ответов включена по умолчанию.

Это является серьезным изменением, так как вызов HttpContent.ReadAsStreamAsync для HttpResponseMessage.Content (response.Content.ReadAsStreamAsync()) возвращает BrowserHttpReadStream и больше не возвращает MemoryStream. BrowserHttpReadStream не поддерживает синхронные операции, например Stream.Read(Span<Byte>). Если код использует синхронные операции, вы можете отказаться от потоковой передачи ответов или скопировать Stream в MemoryStream самостоятельно.

Чтобы отказаться от потоковой передачи ответов глобально, задайте для переменной среды DOTNET_WASM_ENABLE_STREAMING_RESPONSE значение false или 0.

Чтобы отказаться от потоковой передачи ответов для отдельного запроса, задайте для SetBrowserResponseStreamingEnabled значение false на HttpRequestMessage (requestMessage в следующем примере):

requestMessage.SetBrowserResponseStreamingEnabled(false);

Дополнительные сведения см. в разделах HttpClient и HttpRequestMessage, где рассматриваются параметры запросов Fetch API (статья Вызов веб-API).

Фингерпринтинг на стороне клиента

В прошлом году выпуск .NET 9 представил серверное отпечатковывание статических ресурсов в s с введением соглашений о маршрутизации статических активов используя Map Static Assets (Blazor Web App), компонента MapStaticAssets и свойства (ImportMap) для разрешения серверных отпечатков модулей JavaScript. Для .NET 10 вы можете включить функцию клиентского отпечатка модулей JavaScript для автономных Blazor WebAssembly приложений.

В автономных Blazor WebAssembly приложениях во время сборки и публикации платформа заменяет заполнители в index.html значениями, вычисленными во время сборки, чтобы создать уникальные идентификаторы для статических ресурсов. Отпечаток пальца вставляется в имя файла скрипта blazor.webassembly.js.

Чтобы применить функцию отпечатков пальцев, необходимо ввести wwwwoot/index.html в файл следующие изменения. Blazor WebAssembly Автономный шаблон проекта будет обновлен, чтобы включить эти изменения в предстоящий предварительный выпуск:

<head>
    ...
+   <script type="importmap"></script>
</head>

<body>
    ...
-   <script src="_framework/blazor.webassembly.js"></script>
+   <script src="_framework/blazor.webassembly#[.{fingerprint}].js"></script>
</body>

</html>

В файл проекта (.csproj) добавьте свойство <WriteImportMapToHtml>, установленное на значение true.

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

  <PropertyGroup>
    <TargetFramework>net10.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
+   <WriteImportMapToHtml>true</WriteImportMapToHtml>
  </PropertyGroup>
</Project>

Чтобы идентифицировать дополнительные JS модули в самостоятельных Blazor WebAssembly приложениях, используйте свойство <StaticWebAssetFingerprintPattern> в файле проекта (.csproj).

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

<StaticWebAssetFingerprintPattern Include="JSModule" Pattern="*.mjs" 
  Expression="#[.{fingerprint}]!" />

Файлы автоматически помещаются в карту импорта:

  • Автоматически для Blazor Web App CSR.
  • При подключении функции идентификации модуля в самостоятельных Blazor WebAssembly приложениях в соответствии с приведенными выше инструкциями.

При разрешении импорта для взаимодействия с JavaScript карта импорта используется браузером для разрешения файлов с отпечатками.

Настройка среды в автономных Blazor WebAssembly приложениях

Файл Properties/launchSettings.json больше не используется для управления средой в автономных Blazor WebAssembly приложениях.

Начиная с .NET 10 задайте среду со <WasmApplicationEnvironmentName> свойством в файле проекта приложения (.csproj).

В следующем примере среда приложения устанавливается: Staging.

<WasmApplicationEnvironmentName>Staging</WasmApplicationEnvironmentName>

Среды по умолчанию:

  • Development для сборки.
  • Production для публикации.

Изменение имени файла конфигурации загрузки

Файл конфигурации загрузки изменяет имя с blazor.boot.json на dotnet.boot.js. Это изменение имени влияет только на разработчиков, которые взаимодействуют непосредственно с файлом, например, когда разработчики:

Декларативная модель для консервирования состояния компонентов и сервисов

Теперь можно декларативно указать состояние для сохранения в компонентах и службах, используя атрибут [SupplyParameterFromPersistentComponentState]. Свойства с этим атрибутом автоматически сохраняются с помощью службы PersistentComponentState при предпросмотре. Состояние извлекается при интерактивном рендеринге компонента или при создании экземпляра службы.

В предыдущих Blazor выпусках сохранение состояния компонента во время предварительного рендеринга с помощью PersistentComponentState сервиса требовало большого объема кода, как показано в следующем примере:

@page "/movies"
@implements IDisposable
@inject IMovieService MovieService
@inject PersistentComponentState ApplicationState

@if (MoviesList == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <QuickGrid Items="MoviesList.AsQueryable()">
        ...
    </QuickGrid>
}

@code {
    public List<Movie>? MoviesList { get; set; }
    private PersistingComponentStateSubscription? persistingSubscription;

    protected override async Task OnInitializedAsync()
    {
        if (!ApplicationState.TryTakeFromJson<List<Movie>>(nameof(MoviesList), 
            out var movies))
        {
            MoviesList = await MovieService.GetMoviesAsync();
        }
        else
        {
            MoviesList = movies;
        }

        persistingSubscription = ApplicationState.RegisterOnPersisting(() =>
        {
            ApplicationState.PersistAsJson(nameof(MoviesList), MoviesList);
            return Task.CompletedTask;
        });
    }

    public void Dispose() => persistingSubscription?.Dispose();
}

Теперь этот код можно упростить с помощью новой декларативной модели:

@page "/movies"
@inject IMovieService MovieService

@if (MoviesList == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <QuickGrid Items="MoviesList.AsQueryable()">
        ...
    </QuickGrid>
}

@code {
    [SupplyParameterFromPersistentComponentState]
    public List<Movie>? MoviesList { get; set; }

    protected override async Task OnInitializedAsync()
    {
        MoviesList ??= await MovieService.GetMoviesAsync();
    }
}

Дополнительные сведения см. в разделе Предварительный рендеринг компонентов ASP.NET CoreRazor. Дополнительные заметки о реализации API, которые могут изменяться в любое время, доступны в Blazor[] Поддержке декларативно сохраняемого состояния компонентов и служб (dotnet/aspnetcore#60634).

Blazor Hybrid

В этом разделе описываются новые функции для Blazor Hybrid.

Новая .NET MAUIBlazor Hybrid со статьёй и примером ASP.NET Core Blazor Web App и Identity

Добавлена новая статья и пример приложения для .NET MAUIBlazor Hybrid и веб-приложения с помощью ASP.NET Core Identity.

Дополнительные сведения см. в следующих ресурсах:

SignalR

В этом разделе описываются новые функции для SignalR.

Минимальные API

В этом разделе описываются новые функции для минимальных API.

Обработка пустой строки при отправке формы как null для nullable типов значений

При использовании атрибута [FromForm] со сложным объектом в минимальных API пустые строковые значения в записи формы теперь преобразуются в null вместо того, чтобы вызвать сбой синтаксического анализа. Это поведение соответствует логике обработки записей форм, не связанных с сложными объектами в минимальных API.

using Microsoft.AspNetCore.Http;

var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

app.MapPost("/todo", ([FromForm] Todo todo) => TypedResults.Ok(todo));

app.Run();

public class Todo
{
  public int Id { get; set; }
  public DateOnly? DueDate { get; set; } // Empty strings map to `null`
  public string Title { get; set; }
  public bool IsCompleted { get; set; }
}

Благодаря @nvmkpk за вклад в это изменение!

Поддержка проверки в минимальных API

Теперь доступна поддержка проверки в минимальных API. Эта функция позволяет запрашивать проверку данных, отправленных конечным точкам API. Включение проверки позволяет среде выполнения ASP.NET Core выполнять любые проверки, определенные в следующих параметрах:

  • Запрос
  • Заголовок
  • Основное содержание запроса

Проверки определяются с помощью атрибутов в DataAnnotations пространстве имен. Разработчики настраивают поведение системы проверки следующим образом:

  • Создание пользовательских реализаций атрибутов [Validation].
  • Реализация интерфейса IValidatableObject для сложной логики проверки.

Если проверка завершается ошибкой, среда выполнения возвращает ответ 400 Неверный запрос с подробными сведениями об ошибках проверки.

Включение встроенной поддержки проверки для минимальных API

Включите встроенную поддержку проверки минимальных API, вызвав AddValidation метод расширения, чтобы зарегистрировать необходимые службы в контейнере службы для приложения:

builder.Services.AddValidation();

Реализация автоматически обнаруживает типы, определенные в минимальных обработчиках API или в качестве базовых типов типов, определенных в минимальных обработчиках API. Фильтр конечной точки выполняет проверку этих типов и добавляется для каждой конечной точки.

Проверка может быть отключена для определенных конечных точек с помощью DisableValidation метода расширения, как показано в следующем примере:

app.MapPost("/products",
    ([EvenNumber(ErrorMessage = "Product ID must be even")] int productId, [Required] string name)
        => TypedResults.Ok(productId))
    .DisableValidation();

Поддержка событий, отправляемых сервером (SSE)

ASP.NET Core теперь поддерживает возврат результата ServerSentEvents с помощью API TypedResults.ServerSentEvents . Эта функция поддерживается как в минимальных API, так и в приложениях на основе контроллера.

Server-Sent События — это технология серверной передачи, которая позволяет серверу отправлять поток сообщений о событиях клиенту по единому HTTP-соединению. В .NET сообщения о событиях представлены как SseItem<T> объекты, которые могут содержать тип события, идентификатор и полезные данные типа T.

Класс TypedResults имеет новый статический метод с именем ServerSentEvents , который можно использовать для возврата ServerSentEvents результата. Первым параметром этого метода является IAsyncEnumerable<SseItem<T>> тот, который представляет поток сообщений о событиях, отправляемых клиенту.

В следующем примере показано, как использовать TypedResults.ServerSentEvents API для возврата потока событий пульса в качестве объектов JSON клиенту:

app.MapGet("/json-item", (CancellationToken cancellationToken) =>
{
    async IAsyncEnumerable<HeartRateRecord> GetHeartRate(
        [EnumeratorCancellation] CancellationToken cancellationToken)
    {
        while (!cancellationToken.IsCancellationRequested)
        {
            var heartRate = Random.Shared.Next(60, 100);
            yield return HeartRateRecord.Create(heartRate);
            await Task.Delay(2000, cancellationToken);
        }
    }

    return TypedResults.ServerSentEvents(GetHeartRate(cancellationToken),
                                                  eventType: "heartRate");
});

Дополнительные сведения можно найти здесь

  • Server-Sent события на MDN.
  • Минимальное API-приложение использует TypedResults.ServerSentEvents API для возврата потока событий пульса в виде строки и ServerSentEvents JSON-объектов клиенту.
  • Приложение-пример API контроллера, использующее API для передачи потока событий пульса клиенту в виде строки и объектов JSON TypedResults.ServerSentEvents.

OpenAPI

В этом разделе описываются новые возможности OpenAPI.

Поддержка OpenAPI 3.1

ASP.NET Core добавила поддержку создания документов OpenAPI версии 3.1 в .NET 10. Несмотря на незначительное увеличение версии, OpenAPI 3.1 является значительным обновлением спецификации OpenAPI, в частности с полной поддержкой черновика схемы JSON 2020-12.

Некоторые изменения, которые вы увидите в созданном документе OpenAPI, включают:

  • Типы nullable больше не имеют свойства nullable: true в схеме.
  • Вместо свойства nullable: true они имеют ключевое слово type, значение которого является массивом, который включает null в качестве одного из типов.
  • Свойства или параметры, определенные как C# int или long теперь отображаются в созданном документе OpenAPI без type: integer поля и имеют pattern поле, ограничивающее значение цифрами. Это происходит, когда свойство NumberHandling в JsonSerializerOptions установлено как AllowReadingFromString — значение по умолчанию для веб-приложений ASP.NET Core. Чтобы C# int и long могли представляться в документе OpenAPI как type: integer, установите для свойства NumberHandling значение Strict.

При использовании этой функции версия OpenAPI по умолчанию для созданных документов3.1. Версию можно изменить явным образом, задав свойство OpenApiVersion OpenApiOptions в параметре делегата configureOptionsAddOpenApi.

builder.Services.AddOpenApi(options =>
{
    // Specify the OpenAPI version to use.
    options.OpenApiVersion = Microsoft.OpenApi.OpenApiSpecVersion.OpenApi3_0;
});

При создании документа OpenAPI во время сборки можно выбрать версию OpenAPI, задав --openapi-version в элементе OpenApiGenerateDocumentsOptions MSBuild.

    <!-- Configure build-time OpenAPI generation to produce an OpenAPI 3.0 document. -->
    <OpenApiGenerateDocumentsOptions>--openapi-version OpenApi3_0</OpenApiGenerateDocumentsOptions>

Поддержка OpenAPI 3.1 была главным образом добавлена в следующий PR.

Изменения, нарушающие совместимость в OpenAPI 3.1

Для поддержки OpenAPI 3.1 требуется обновление базовой библиотеки OpenAPI.NET до новой основной версии 2.0. Эта новая версия содержит некоторые изменения, которые могут нарушить совместимость с предыдущей версией. Разрушающие изменения могут повлиять на приложения, если они используют трансформеры документов, операций или схем. Критические изменения в этой итерации включают следующие:

  • Сущности в документе OpenAPI, такие как операции и параметры, являются интерфейсами. Конкретные реализации существуют как для встроенных, так и для ссылочных вариантов сущности. Например, IOpenApiSchema может быть встроенным OpenApiSchema или OpenApiSchemaReference, указывающим на схему, определенную в другом месте документа.
  • Свойство Nullable было удалено из типа OpenApiSchema. Чтобы определить, является ли тип допускающим значение null, проверьте, устанавливает ли свойство OpenApiSchema.TypeJsonSchemaType.Null.

Одним из наиболее значительных изменений является то, что класс OpenApiAny был удален в пользу использования JsonNode напрямую. Для использования OpenApiAnyнеобходимо обновить преобразователи, использующие JsonNode. В следующем диффе показаны изменения преобразователя схемы с .NET 9 до .NET 10:

options.AddSchemaTransformer((schema, context, cancellationToken) =>
{
    if (context.JsonTypeInfo.Type == typeof(WeatherForecast))
    {
-       schema.Example = new OpenApiObject
+       schema.Example = new JsonObject
        {
-           ["date"] = new OpenApiString(DateTime.Now.AddDays(1).ToString("yyyy-MM-dd")),
+           ["date"] = DateTime.Now.AddDays(1).ToString("yyyy-MM-dd"),
-           ["temperatureC"] = new OpenApiInteger(0),
+           ["temperatureC"] = 0,
-           ["temperatureF"] = new OpenApiInteger(32),
+           ["temperatureF"] = 32,
-           ["summary"] = new OpenApiString("Bracing"),
+           ["summary"] = "Bracing",
        };
    }
    return Task.CompletedTask;
});

Обратите внимание, что эти изменения необходимы даже при настройке только версии OpenAPI до версии 3.0.

OpenAPI в YAML

ASP.NET теперь поддерживает обслуживание созданного документа OpenAPI в формате YAML. YAML может быть более кратким, чем JSON, устраняя фигурные скобки и кавычки, когда их можно вывести. YAML также поддерживает многострочный формат строк, которые могут быть полезны для длинных описаний.

Чтобы настроить приложение для обслуживания созданного документа OpenAPI в формате YAML, укажите конечную точку в вызове MapOpenApi с суффиксом "yaml" или ".yml", как показано в следующем примере:

app.MapOpenApi("/openapi/{documentName}.yaml");

Поддержка для:

  • В настоящее время YAML доступен только для OpenAPI, обслуживаемого из конечной точки OpenAPI.
  • Создание документов OpenAPI в формате YAML во время сборки будет добавлено в будущей предварительной версии.

См. этот PR, добавивший поддержку представления сгенерированного документа OpenAPI в формате YAML.

Описание ответа в ProducesResponseType

Атрибуты ProducesAttribute, ProducesResponseTypeAttribute, и ProducesDefaultResponseType теперь принимают необязательный строковый параметр Description, который задает описание ответа. Ниже приведен пример:

[HttpGet(Name = "GetWeatherForecast")]
[ProducesResponseType<IEnumerable<WeatherForecast>>(StatusCodes.Status200OK,
                   Description = "The weather forecast for the next 5 days.")]
public IEnumerable<WeatherForecast> Get()
{

А также сгенерированный OpenAPI:

        "responses": {
          "200": {
            "description": "The weather forecast for the next 5 days.",
            "content": {

вклад сообществаСандер тен Бринке🙏

Перенос комментариев из XML-документа в документ OpenAPI

ASP.NET Core генерация документов OpenAPI теперь будет включать метаданные из комментариев XML документации о методах, классах и их членах в документе OpenAPI. Чтобы использовать эту функцию, необходимо включить комментарии XML-документации в файле проекта. Это можно сделать, добавив в файл проекта следующее свойство:

  <PropertyGroup>
    <GenerateDocumentationFile>true</GenerateDocumentationFile>
  </PropertyGroup>

Во время сборки пакет OpenAPI будет использовать генератор источника для обнаружения XML-комментариев в текущей сборке приложения и любых ссылок на проекты и отправки исходного кода для вставки в документ с помощью преобразователя документов OpenAPI.

Обратите внимание, что процесс сборки C# не записывает комментарии XML-документации, размещенные в лямбда-экспресионах, поэтому для добавления метаданных в минимальную конечную точку API необходимо определить обработчик конечной точки как метод, поместить комментарии XML-документа в метод, а затем ссылаться на этот метод из метода MapXXX. Например, чтобы использовать примечания XML-документа для добавления метаданных в минимальную конечную точку API, изначально определенную как лямбда-выражение:

app.MapGet("/hello", (string name) =>$"Hello, {name}!");

Измените вызов MapGet для ссылки на метод:

app.MapGet("/hello", Hello);

Определите метод Hello с помощью комментариев xml-документации:

static partial class Program
{
    /// <summary>
    /// Sends a greeting.
    /// </summary>
    /// <remarks>
    /// Greeting a person by their name.
    /// </remarks>
    /// <param name="name">The name of the person to greet.</param>
    /// <returns>A greeting.</returns>
    public static string Hello(string name)
    {
        return $"Hello, {name}!";
    }
}

В предыдущем примере метод Hello добавляется в класс Program, но его можно добавить в любой класс в проекте.

В предыдущем примере показаны <summary>, <remarks> и <param> XML-комментарии. Дополнительные сведения о комментариях xml-документации, включая все поддерживаемые теги, см. в документации C#.

Так как основные функции предоставляются с помощью генератора источника, его можно отключить, добавив следующий MSBuild в файл проекта.

<ItemGroup>
  <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0-preview.2.*" GeneratePathProperty="true" />
</ItemGroup>

<Target Name="DisableCompileTimeOpenApiXmlGenerator" BeforeTargets="CoreCompile">
  <ItemGroup>
    <Analyzer Remove="$(PkgMicrosoft_AspNetCore_OpenApi)/analyzers/dotnet/cs/Microsoft.AspNetCore.OpenApi.SourceGenerators.dll" />
  </ItemGroup>
</Target>

Генератор исходного кода обрабатывает XML-файлы, включенные в свойство AdditionalFiles. Чтобы добавить (или удалить), источники изменяют свойство следующим образом:

<Target Name="AddXmlSources" BeforeTargets="CoreCompile">
  <ItemGroup>
    <AdditionalFiles Include="$(PkgSome_Package)/lib/net10.0/Some.Package.xml" />
  </ItemGroup>
</Target>

Microsoft.AspNetCore.OpenApi добавлен в шаблон веб-API ASP.NET Core (Native AOT)

Шаблон проекта ASP.NET Core Web API (native AOT) ( короткое имя webapiaot) теперь включает поддержку создания документов OpenAPI с помощью Microsoft.AspNetCore.OpenApi пакета по умолчанию. Эта поддержка отключена с помощью флага --no-openapi при создании нового проекта.

Это был вклад сообщества от @sander1095. Спасибо за этот вклад!

Проверка подлинности и авторизация

В этом разделе описываются новые функции проверки подлинности и авторизации.

Метрики проверки подлинности и авторизации

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

  • Аутентификация:
    • Длительность аутентифицированного запроса
    • Количество испытаний
    • Запретить подсчет
    • Количество авторизаций
    • Количество выходов из системы
  • Авторизация:
    • Количество запросов, требующих авторизации

На следующем рисунке показан пример метрики длительности аутентифицированного запроса на панели мониторинга Aspire.

длительность запроса с проверкой подлинности в панели мониторинга Aspire

Дополнительные сведения см. в ASP.NET Core метрики авторизации и аутентификации.

Разное

В этом разделе описаны другие новые функции в ASP.NET Core 10.0.

Улучшена поддержка тестирования приложений с помощью инструкций верхнего уровня

В .NET 10 теперь улучшена поддержка тестирования приложений, использующих инструкции верхнего уровня . Ранее разработчикам пришлось вручную добавить public partial class Program в файл Program.cs, чтобы тестовый проект мог ссылаться на Program class. public partial class Program требуется, так как оператор верхнего уровня в C# 9 создал Program class, объявленный как внутренний.

В .NET 10 source generator используется для создания объявления public partial class Program, если программист не объявил его явно. Кроме того, был добавлен анализатор, чтобы определить, когда public partial class Program объявлен явным образом, и рекомендовать разработчику его удалить.

изображение

Следующие PR-ы, внесшие вклад в эту функцию:

Определение локального URL-адреса с помощью RedirectHttpResult.IsLocalUrl

Используйте новый вспомогательный метод RedirectHttpResult.IsLocalUrl(url), чтобы определить, является ли URL-адрес локальным. URL-адрес считается локальным, если выполняются следующие условия:

URL-адреса с виртуальными путями "~/" также являются локальными.

IsLocalUrl полезно для проверки URL-адресов перед перенаправлением на них, чтобы предотвратить атаки открытого перенаправления.

if (RedirectHttpResult.IsLocalUrl(url))
{
    return Results.LocalRedirect(url);
}

Спасибо @martincostello за этот вклад!


Дополнительные ресурсы