Создание документов OpenAPI
Пакет Microsoft.AspNetCore.OpenApi
обеспечивает встроенную поддержку создания документов OpenAPI в ASP.NET Core. Пакет предоставляет следующие функции:
- Поддержка создания документов OpenAPI во время выполнения и доступа к ним через конечную точку приложения.
- Поддержка API-интерфейсов "преобразователя", позволяющих изменять созданный документ.
- Поддержка создания нескольких документов OpenAPI из одного приложения.
- Использует преимущества поддержки схемы JSON,
System.Text.Json
предоставляемой . - Совместим с собственным AoT.
Установка пакета
Установите пакет Microsoft.AspNetCore.OpenApi
.
Выполните следующую команду из консоли диспетчер пакетов:
Install-Package Microsoft.AspNetCore.OpenApi -IncludePrerelease
Чтобы добавить поддержку создания документов OpenAPI во время сборки, установите Microsoft.Extensions.ApiDescription.Server
пакет:
Выполните следующую команду из консоли диспетчер пакетов:
Install-Package Microsoft.Extensions.ApiDescription.Server -IncludePrerelease
Настройка создания документов OpenAPI
Следующий код:
- Добавляет службы OpenAPI.
- Включает конечную точку для просмотра документа OpenAPI в формате JSON.
var builder = WebApplication.CreateBuilder();
builder.Services.AddOpenApi();
var app = builder.Build();
app.MapOpenApi();
app.MapGet("/", () => "Hello world!");
app.Run();
Запустите приложение и перейдите к https://localhost:<port>/openapi/v1.json
просмотру созданного документа OpenAPI.
Включение метаданных OpenAPI в веб-приложение ASP.NET
Включение метаданных OpenAPI для конечных точек
ASP.NET собирает метаданные из конечных точек веб-приложения и использует его для создания документа OpenAPI.
В приложениях на основе контроллера метаданные собираются из таких атрибутов, как [EndpointDescription]
, [HttpPost]
и [Produces]
.
В минимальных API метаданные могут собираться из атрибутов, но также можно задать с помощью методов расширения и других стратегий, таких как возврат TypedResults из обработчиков маршрутов.
В следующей таблице представлен обзор собранных метаданных и стратегий его настройки.
Метаданные | Атрибут | Метод расширения | Другие стратегии |
---|---|---|---|
Итоги | [EndpointSummary] |
WithSummary | |
описание | [EndpointDescription] |
WithDescription | |
tags | [Tags] |
WithTags | |
operationId | [EndpointName] |
WithName | |
parameters | [FromQuery] , , [FromRoute] [FromHeader] [FromForm] |
||
Описание параметра | [EndpointDescription] |
||
requestBody | [FromBody] |
Accepts | |
Ответы на запросы | [Produces] |
Produces, ProducesProblem | TypedResults |
Исключение конечных точек | [ExcludeFromDescription] , [ApiExplorerSettings] |
ExcludeFromDescription |
ASP.NET Core не собирает метаданные из комментариев XML-документации.
В следующих разделах показано, как включить метаданные в приложение для настройки созданного документа OpenAPI.
Сводка и описание
Сводка и описание конечной точки можно задать с помощью [EndpointSummary]
атрибутов [EndpointDescription]
и атрибутов или в минимальных API с помощью WithSummary методов расширения и WithDescription методов расширения.
В следующем примере показаны различные стратегии настройки сводок и описаний.
Обратите внимание, что атрибуты помещаются в метод делегата, а не в приложении. Метод MapGet.
app.MapGet("/extension-methods", () => "Hello world!")
.WithSummary("This is a summary.")
.WithDescription("This is a description.");
app.MapGet("/attributes",
[EndpointSummary("This is a summary.")]
[EndpointDescription("This is a description.")]
() => "Hello world!");
tags
OpenAPI поддерживает указание тегов на каждой конечной точке в виде классификации.
В минимальных API теги можно задать с помощью атрибута [Tags]
WithTags или метода расширения.
В следующем примере показаны различные стратегии настройки тегов.
app.MapGet("/extension-methods", () => "Hello world!")
.WithTags("todos", "projects");
app.MapGet("/attributes",
[Tags("todos", "projects")]
() => "Hello world!");
operationId
OpenAPI поддерживает идентификатор операции на каждой конечной точке в качестве уникального идентификатора или имени для операции.
В минимальных API идентификатор операции можно задать с помощью атрибута [EndpointName]
WithName или метода расширения.
В следующем примере показаны различные стратегии настройки идентификатора операции.
app.MapGet("/extension-methods", () => "Hello world!")
.WithName("FromExtensionMethods");
app.MapGet("/attributes",
[EndpointName("FromAttributes")]
() => "Hello world!");
parameters
OpenAPI поддерживает аннотирование пути, строки запроса, заголовка и cookie параметров, используемых API.
Платформа определяет типы параметров запроса автоматически на основе сигнатуры обработчика маршрутов.
Атрибут [EndpointDescription]
можно использовать для предоставления описания параметра.
В следующем примере показано, как задать описание параметра.
app.MapGet("/attributes",
([Description("This is a description.")] string name) => "Hello world!");
Описание текста запроса
Поле requestBody
в OpenAPI описывает текст запроса, который клиент API может отправлять на сервер, включая поддерживаемые типы контента и схему для содержимого текста.
Когда метод обработчика конечных точек принимает параметры, привязанные из текста запроса, ASP.NET Core создает соответствующую requestBody
операцию в документе OpenAPI. Метаданные для текста запроса также можно указать с помощью атрибутов или методов расширения. Дополнительные метаданные можно задать с помощью преобразователя документов или преобразователя операций.
Если конечная точка не определяет какие-либо параметры, привязанные к тексту запроса, но вместо этого использует текст запроса из непосредственного HttpContext , ASP.NET Core предоставляет механизмы для указания метаданных тела запроса. Это распространенный сценарий для конечных точек, обрабатывающих текст запроса в виде потока.
Некоторые метаданные тела запроса можно определить из FromBody
метода обработчика маршрутов или FromForm
параметров.
Описание текста запроса можно задать с атрибутом [Description]
для параметра или FromBody
FromForm
.
FromBody
Если параметр не имеет значения NULL и EmptyBodyBehavior не задан Allow в FromBody
атрибуте, текст запроса является обязательным, а required
поле requestBody
задано true
в созданном документе OpenAPI.
Тела форм всегда обязательны и имеют required
значение true
.
Используйте преобразователь документов или преобразователь операций для задания examples
example
полей или encoding
полей или добавления расширений спецификаций для текста запроса в созданном документе OpenAPI.
Другие механизмы настройки метаданных текста запроса зависят от типа разрабатываемого приложения и описаны в следующих разделах.
Типы контента для текста запроса в созданном документе OpenAPI определяются из типа параметра, привязанного к тексту запроса или заданного методом Accepts расширения.
По умолчанию тип FromBody
контента параметра будет иметь application/json
значение, и тип контента для FromForm
параметров будет multipart/form-data
или application/x-www-form-urlencoded
.
Поддержка этих типов контента по умолчанию встроена в минимальные API, а другие типы контента можно обрабатывать с помощью пользовательской привязки. Дополнительные сведения см. в разделе о пользовательской привязке документации по минимальным API.
Существует несколько способов указать другой тип контента для текста запроса.
Если тип FromBody
параметра реализуется IEndpointParameterMetadataProvider, ASP.NET Core использует этот интерфейс для определения типов контента в тексте запроса.
Платформа использует PopulateMetadata метод этого интерфейса для задания типов контента и типа текста запроса. Например, класс, принимаюющий или application/xml
text/xml
тип контента, Todo
может использовать IEndpointParameterMetadataProvider для предоставления этой информации платформе.
public class Todo : IEndpointParameterMetadataProvider
{
public static void PopulateMetadata(ParameterInfo parameter, EndpointBuilder builder)
{
builder.Metadata.Add(new AcceptsMetadata(["application/xml", "text/xml"], typeof(Todo)));
}
}
Accepts Метод расширения также можно использовать для указания типа контента текста запроса.
В следующем примере конечная точка принимает Todo
объект в тексте запроса с ожидаемым типом application/xml
контента.
app.MapPut("/todos/{id}", (int id, Todo todo) => ...)
.Accepts<Todo>("application/xml");
Так как application/xml
не является встроенным типом контента, Todo
класс должен реализовать IBindableFromHttpContext<TSelf> интерфейс для предоставления пользовательской привязки для текста запроса. Например:
public class Todo : IBindableFromHttpContext<Todo>
{
public static async ValueTask<Todo?> BindAsync(HttpContext context, ParameterInfo parameter)
{
var xmlDoc = await XDocument.LoadAsync(context.Request.Body, LoadOptions.None, context.RequestAborted);
var serializer = new XmlSerializer(typeof(Todo));
return (Todo?)serializer.Deserialize(xmlDoc.CreateReader());
}
Если конечная точка не определяет параметры, привязанные к тексту запроса, используйте Accepts метод расширения, чтобы указать тип контента, который принимает конечная точка.
Если указать <AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.Accepts%2A> несколько раз, используются только метаданные из последнего. Они не объединяются.
Описание типов ответов
OpenAPI поддерживает описание ответов, возвращаемых API. ASP.NET Core предоставляет несколько стратегий настройки метаданных ответа конечной точки. Метаданные ответа, которые можно задать, включают код состояния, тип текста ответа и тип контента ответа. Ответы в OpenAPI могут иметь дополнительные метаданные, такие как описание, заголовки, ссылки и примеры. Эти дополнительные метаданные можно задать с помощью преобразователя документов или преобразователя операций.
Конкретные механизмы настройки метаданных ответа зависят от типа разрабатываемого приложения.
В приложениях с минимальными api ASP.NET Core может извлекать метаданные ответа, добавленные методами расширения в конечной точке, атрибутами обработчика маршрутов и возвращаемым типом обработчика маршрутов.
- Метод Produces расширения можно использовать в конечной точке для указания кода состояния, типа текста ответа и типов контента ответа из конечной точки.
- Можно
[ProducesResponseType]
использовать атрибут для ProducesResponseTypeAttribute<T> указания типа текста отклика. - Обработчик маршрута можно использовать для возврата типа, реализующего IEndpointMetadataProvider указание типа и типов контента текста ответа.
- ProducesProblem Метод расширения конечной точки можно использовать для указания кода состояния и типов контента ответа об ошибке.
Обратите внимание, что Produces методы расширения поддерживаются как в, RouteHandlerBuilder так и ProducesProblem вRouteGroupBuilder. Это позволяет, например, определить общий набор ответов на ошибки для всех операций в группе.
Если не указано одно из предыдущих стратегий, выполните указанные ниже действия.
- Код состояния ответа по умолчанию — 200.
- Схема для текста ответа может быть выведена из неявного или явного типа возвращаемого типа метода конечной точки, например из
T
, в Task<TResult>противном случае считается неуказаемым. - Тип контента для указанного или выводного текста ответа — application/json.
В минимальных Produces API метод расширения и [ProducesResponseType]
атрибут задают только метаданные ответа для конечной точки. Они не изменяют или ограничивают поведение конечной точки, которая может возвращать другой тип текста состояния или ответа, отличный от метаданных, и тип контента определяется возвращаемым типом метода обработчика маршрутов, независимо от любого типа контента, указанного в атрибутах или методах расширения.
Метод Produces расширения может указать тип ответа конечной точки с кодом состояния по умолчанию 200 и типом application/json
контента по умолчанию. Проиллюстрируем это на примере.
app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
.Produces<IList<Todo>>();
Его [ProducesResponseType]
можно использовать для добавления метаданных ответа в конечную точку. Обратите внимание, что атрибут применяется к методу обработчика маршрутов, а не вызову метода для создания маршрута, как показано в следующем примере:
app.MapGet("/todos",
[ProducesResponseType<List<Todo>>(200)]
async (TodoDb db) => await db.Todos.ToListAsync());
Использование TypedResults в реализации обработчика маршрутов конечной точки автоматически включает метаданные типа ответа для конечной точки. Например, следующий код автоматически заметит конечную точку с ответом в коде 200
состояния с типом application/json
контента.
app.MapGet("/todos", async (TodoDb db) =>
{
var todos = await db.Todos.ToListAsync();
return TypedResults.Ok(todos);
});
Возвращаются только типы, реализующие IEndpointMetadataProvider создание responses
записи в документе OpenAPI. Ниже приведен частичный список некоторых TypedResults вспомогательных методов, которые создают responses
запись:
Вспомогательный метод TypedResults | Код состояния |
---|---|
Ok() | 200 |
Created() | 201 |
CreatedAtRoute() | 201 |
Accepted() | 202 |
AcceptedAtRoute() | 202 |
NoContent() | 204 |
BadRequest() | 400 |
ValidationProblem() | 400 |
NotFound() | 404 |
Conflict() | 409 |
UnprocessableEntity() | 422 |
Все эти методы, кроме NoContent
универсальной перегрузки, задающей тип тела отклика.
Класс можно реализовать, чтобы задать метаданные конечной точки и вернуть его из обработчика маршрутов.
Настройка ответов для ProblemDetails
При настройке типа ответа для конечных точек, которые могут возвращать ответ ProblemDetails, можно использовать следующее, чтобы добавить соответствующие метаданные ответа для конечной точки:
- ProducesProblem
- Метод расширения ProducesValidationProblem.
- TypedResults с кодом состояния в диапазоне (400-499).
Дополнительные сведения о настройке минимального приложения API для возврата ответов ProblemDetails см. в разделе "Обработка ошибок в минимальных API".
Несколько типов ответов
Если конечная точка может возвращать различные типы ответов в разных сценариях, можно предоставить метаданные следующим образом:
Produces Вызов метода расширения несколько раз, как показано в следующем примере:
app.MapGet("/api/todoitems/{id}", async (int id, TodoDb db) => await db.Todos.FindAsync(id) is Todo todo ? Results.Ok(todo) : Results.NotFound()) .Produces<Todo>(StatusCodes.Status200OK) .Produces(StatusCodes.Status404NotFound);
Используйте Results<TResult1,TResult2,TResult3,TResult4,TResult5,TResult6> сигнатуру и TypedResults в тексте обработчика, как показано в следующем примере:
app.MapGet("/book/{id}", Results<Ok<Book>, NotFound> (int id, List<Book> bookList) => { return bookList.FirstOrDefault((i) => i.Id == id) is Book book ? TypedResults.Ok(book) : TypedResults.NotFound(); });
Results<TResult1,TResult2,TResultN>
Типы объединения объявляют, что обработчик маршрутов возвращает несколькоIResult
конкретных типов, и любой из этих типов, которые реализуютIEndpointMetadataProvider, будут способствовать метаданным конечной точки.Типы объединения реализуют неявные операторы приведения. Эти операторы позволяют компилятору автоматически преобразовывать типы, указанные в универсальных аргументах, в экземпляр типа объединения. Эта возможность обладает дополнительным преимуществом для проверки времени компиляции, что обработчик маршрутов возвращает только результаты, объявленные им. Попытка вернуть тип, который не объявлен как один из универсальных аргументов, приводит к
Results<TResult1,TResult2,TResultN>
ошибке компиляции.
Исключение конечных точек из созданного документа
По умолчанию все конечные точки, определенные в приложении, документируются в созданном файле OpenAPI, но конечные точки могут быть исключены из документа с помощью атрибутов или методов расширения.
Механизм указания конечной точки, которая должна быть исключена, зависит от типа разрабатываемого приложения.
Минимальные API поддерживают две стратегии исключения заданной конечной точки из документа OpenAPI:
- Метод расширения ExcludeFromDescription
- Атрибут
[ExcludeFromDescription]
В следующем примере показаны различные стратегии исключения заданной конечной точки из созданного документа OpenAPI.
app.MapGet("/extension-method", () => "Hello world!")
.ExcludeFromDescription();
app.MapGet("/attributes",
[ExcludeFromDescription]
() => "Hello world!");
Включение метаданных OpenAPI для типов данных
Классы или записи C#, используемые в телах запроса или ответа, представлены в виде схем в созданном документе OpenAPI. По умолчанию в схеме представлены только общедоступные свойства, но также необходимо JsonSerializerOptions создать свойства схемы для полей.
PropertyNamingPolicy Если задано значение верблюдьего регистра (это по умолчанию в ASP.NET веб-приложениях), имена свойств в схеме представляют собой форму регистра верблюда или имени свойства записи.
Его [JsonPropertyName]
можно использовать для отдельного свойства, чтобы указать имя свойства в схеме.
тип и формат
Библиотека схем JSON сопоставляет стандартные типы C# с OpenAPI type
и format
следующим образом:
Тип C# | OpenAPI type |
OpenAPI format |
---|---|---|
INT | integer | int32 |
длинный | integer | int64 |
short | integer | int16 |
byte | integer | uint8 |
с плавающей запятой | number | с плавающей запятой |
двойной точности | number | двойной точности |
десятичное | number | двойной точности |
bool | boolean | |
строка | строка | |
char | строка | char |
byte[] | строка | byte |
DateTimeOffset | строка | date-time |
DateOnly | строка | Дата |
TimeOnly | строка | Время |
URI-адрес | строка | uri |
GUID | строка | uuid |
объект | упущенный | |
по строкам | упущенный |
Обратите внимание, что у объектов и динамических типов нет типов, определенных в OpenAPI, так как они могут содержать данные любого типа, включая примитивные типы, такие как int или string.
format
Его type
также можно задать с помощью преобразователя схемы. Например, может потребоватьсяformat
, чтобы десятичные типы не double
былиdecimal
.
Использование атрибутов для добавления метаданных
ASP.NET использует метаданные из атрибутов в свойствах класса или записи для задания метаданных соответствующих свойств созданной схемы.
В следующей таблице перечислены атрибуты из System.ComponentModel
пространства имен, предоставляющего метаданные для созданной схемы:
Атрибут | Description |
---|---|
[Description] |
description Задает свойство в схеме. |
[Required] |
Помечает свойство как required в схеме. |
[DefaultValue] |
default Задает значение свойства в схеме. |
[Range] |
minimum Задает и maximum значение целого числа или числа. |
[MinLength] |
minLength Задает строку. |
[MaxLength] |
maxLength Задает строку. |
[RegularExpression] |
pattern Задает строку. |
Обратите внимание, что в приложениях на основе контроллера эти атрибуты добавляют фильтры в операцию, чтобы убедиться, что все входящие данные удовлетворяют ограничениям. В минимальных API эти атрибуты задают метаданные в созданной схеме, но проверка должна выполняться явным образом через фильтр конечной точки, в логике обработчика маршрутов или через сторонний пакет.
Другие источники метаданных для созданных схем
обязательно
Свойства также можно пометить как required
обязательный модификатор.
перечисление
Типы перечисления в C# являются целыми числами, но могут представляться как строки в JSON с помощью a [JsonConverter]
и a JsonStringEnumConverter. Если тип перечисления представлен как строка в ФОРМАТЕ JSON, созданная схема будет иметь enum
свойство со строковыми значениями перечисления.
Тип перечисления без нее [JsonConverter]
будет определен как type: integer
в созданной схеме.
Примечание. Значения [AllowedValues]
свойства не задаются enum
.
nullable
Свойства, определенные как значение null или ссылочный тип, имеются nullable: true
в созданной схеме. Это согласуется с поведением десериализатора по умолчанию, которое принимает null
в качестве допустимого System.Text.Json значения для свойства, допускающего значение NULL.
additionalProperties
Схемы создаются без additionalProperties
утверждения по умолчанию, что подразумевает значение по умолчанию true
. Это согласуется с поведением десериализатора System.Text.Json по умолчанию, которое автоматически игнорирует дополнительные свойства в объекте JSON.
Если дополнительные свойства схемы должны иметь только значения определенного типа, определите свойство или класс как класс Dictionary<string, type>
. Тип ключа для словаря должен быть string
. Это создает схему с additionalProperties
указанием схемы для типа типа в качестве обязательных типов значений.
Метаданные для полиморфных типов
[JsonPolymorphic]
[JsonDerivedType]
Используйте атрибуты родительского класса для указания дискриминационных полей и подтипов для полиморфного типа.
Добавляет [JsonDerivedType]
поле дискриминационных в схему для каждого подкласса с перечислением, указывающим конкретное дискриминационные значения для подкласса. Этот атрибут также изменяет конструктор каждого производного класса для задания дискриминационных значений.
Абстрактный класс с [JsonPolymorphic]
атрибутом discriminator
имеет поле в схеме, но конкретный класс с [JsonPolymorphic]
атрибутом не имеет discriminator
поля. OpenAPI требует, чтобы дискриминационные свойства были обязательным свойством в схеме, но поскольку дискриминационные свойства не определены в конкретном базовом классе, схема не может включать discriminator
поле.
Добавление метаданных с преобразователем схемы
Преобразователь схемы можно использовать для переопределения любых метаданных по умолчанию или добавления дополнительных метаданных, таких как example
значения, в созданную схему. Дополнительные сведения см. в разделе "Использование преобразователей схем".
Параметры настройки создания документов OpenAPI
В следующих разделах показано, как настроить создание документов OpenAPI.
Настройка имени документа OpenAPI
Каждый документ OpenAPI в приложении имеет уникальное имя. Имя документа по умолчанию, зарегистрированного v1
.
builder.Services.AddOpenApi(); // Document name is v1
Имя документа можно изменить, передав имя в качестве параметра вызову AddOpenApi
.
builder.Services.AddOpenApi("internal"); // Document name is internal
Имя документа отображается в нескольких местах в реализации OpenAPI.
При получении созданного документа OpenAPI имя документа указывается в качестве documentName
аргумента параметра в запросе. Следующие запросы разрешают v1
документы и internal
документы.
GET http://localhost:5000/openapi/v1.json
GET http://localhost:5000/openapi/internal.json
Настройка версии OpenAPI созданного документа
По умолчанию создание документов OpenAPI создает документ, соответствующий спецификации OpenAPI версии 3.0. В следующем коде показано, как изменить версию документа OpenAPI по умолчанию:
builder.Services.AddOpenApi(options =>
{
options.OpenApiVersion = OpenApiSpecVersion.OpenApi2_0;
});
Настройка маршрута конечной точки OpenAPI
По умолчанию конечная точка OpenAPI, зарегистрированная с помощью вызова, предоставляет MapOpenApi документ в конечной точке /openapi/{documentName}.json
. В следующем коде показано, как настроить маршрут, в котором зарегистрирован документ OpenAPI:
app.MapOpenApi("/openapi/{documentName}/openapi.json");
Возможно, но не рекомендуется удалить documentName
параметр маршрута из маршрута конечной точки. documentName
При удалении параметра маршрута из маршрута конечной точки платформа пытается разрешить имя документа из параметра запроса. Не предоставляя documentName
маршрут или запрос, может привести к непредвиденному поведению.
Настройка конечной точки OpenAPI
Так как документ OpenAPI обслуживается через конечную точку обработчика маршрутов, любая настройка, доступная для стандартных минимальных конечных точек, доступна для конечной точки OpenAPI.
Ограничение доступа к документам OpenAPI авторизованным пользователям
Конечная точка OpenAPI не включает проверки авторизации по умолчанию. Однако проверки авторизации можно применить к документу OpenAPI. В следующем коде доступ к документу OpenAPI ограничен тем, кто имеет tester
роль:
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
var builder = WebApplication.CreateBuilder();
builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddAuthorization(o =>
{
o.AddPolicy("ApiTesterPolicy", b => b.RequireRole("tester"));
});
builder.Services.AddOpenApi();
var app = builder.Build();
app.MapOpenApi()
.RequireAuthorization("ApiTesterPolicy");
app.MapGet("/", () => "Hello world!");
app.Run();
Созданный в кэше документ OpenAPI
Документ OpenAPI создается каждый раз, когда отправляется запрос к конечной точке OpenAPI. Восстановление позволяет преобразователям включать динамическое состояние приложения в свою работу. Например, повторное создание запроса с подробными сведениями о контексте HTTP. При необходимости документ OpenAPI можно кэшировать, чтобы избежать выполнения конвейера создания документов для каждого HTTP-запроса.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
var builder = WebApplication.CreateBuilder();
builder.Services.AddOutputCache(options =>
{
options.AddBasePolicy(policy => policy.Expire(TimeSpan.FromMinutes(10)));
});
builder.Services.AddOpenApi();
var app = builder.Build();
app.UseOutputCache();
app.MapOpenApi()
.CacheOutput();
app.MapGet("/", () => "Hello world!");
app.Run();
Преобразователи документов OpenAPI
В этом разделе показано, как настроить документы OpenAPI с помощью преобразователей.
Настройка документов OpenAPI с помощью преобразователей
Преобразователи предоставляют API для изменения документа OpenAPI с пользовательскими настройками. Преобразователи полезны для таких сценариев:
- Добавление параметров ко всем операциям в документе.
- Изменение описания параметров или операций.
- Добавление сведений верхнего уровня в документ OpenAPI.
Преобразователи делятся на три категории:
- Преобразователи документов имеют доступ ко всему документу OpenAPI. Их можно использовать для внесения глобальных изменений в документ.
- Преобразователи операций применяются к каждой отдельной операции. Каждая отдельная операция — это сочетание пути и метода HTTP. Их можно использовать для изменения параметров или ответов на конечных точках.
- Преобразователи схем применяются к каждой схеме в документе. Их можно использовать для изменения схемы тел запроса или ответа или любых вложенных схем.
Преобразователи можно зарегистрировать в документе, вызвав AddDocumentTransformer метод объекта OpenApiOptions . В следующем фрагменте кода показаны различные способы регистрации преобразователей в документе:
- Зарегистрируйте преобразователь документов с помощью делегата.
- Зарегистрируйте преобразователь документов с помощью экземпляра IOpenApiDocumentTransformer.
- Зарегистрируйте преобразователь документов с помощью активации IOpenApiDocumentTransformerDI.
- Зарегистрируйте преобразователь операций с помощью делегата.
- Зарегистрируйте преобразователь операций с помощью экземпляра IOpenApiOperationTransformer.
- Зарегистрируйте преобразователь операций с помощью активации IOpenApiOperationTransformerDI.
- Зарегистрируйте преобразователь схемы с помощью делегата.
- Зарегистрируйте преобразователь схемы с помощью экземпляра IOpenApiSchemaTransformer.
- Зарегистрируйте преобразователь схемы с помощью активированного IOpenApiSchemaTransformerDI.
using Microsoft.AspNetCore.OpenApi;
using Microsoft.OpenApi.Models;
var builder = WebApplication.CreateBuilder();
builder.Services.AddOpenApi(options =>
{
options.AddDocumentTransformer((document, context, cancellationToken)
=> Task.CompletedTask);
options.AddDocumentTransformer(new MyDocumentTransformer());
options.AddDocumentTransformer<MyDocumentTransformer>();
options.AddOperationTransformer((operation, context, cancellationToken)
=> Task.CompletedTask);
options.AddOperationTransformer(new MyOperationTransformer());
options.AddOperationTransformer<MyOperationTransformer>();
options.AddSchemaTransformer((schema, context, cancellationToken)
=> Task.CompletedTask);
options.AddSchemaTransformer(new MySchemaTransformer());
options.AddSchemaTransformer<MySchemaTransformer>();
});
var app = builder.Build();
app.MapOpenApi();
app.MapGet("/", () => "Hello world!");
app.Run();
Порядок выполнения для преобразователей
Преобразователи выполняются в первом порядке на основе регистрации. В следующем фрагменте кода преобразователь документов имеет доступ к изменениям, внесенным преобразователем операций:
var builder = WebApplication.CreateBuilder();
builder.Services.AddOpenApi(options =>
{
options.AddOperationTransformer((operation, context, cancellationToken)
=> Task.CompletedTask);
options.AddDocumentTransformer((document, context, cancellationToken)
=> Task.CompletedTask);
});
var app = builder.Build();
app.MapOpenApi();
app.MapGet("/", () => "Hello world!");
app.Run();
Использование преобразователей документов
Преобразователи документов имеют доступ к объекту контекста, который включает в себя:
- Имя измененного документа.
- Связанный с этим документом ApiDescriptionGroups .
- Используется IServiceProvider в создании документов.
Преобразователи документов также могут изменить созданный документ OpenAPI. В следующем примере показан преобразователь документов, который добавляет некоторые сведения об API в документ OpenAPI.
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Builder;
var builder = WebApplication.CreateBuilder();
builder.Services.AddOpenApi(options =>
{
options.AddDocumentTransformer((document, context, cancellationToken) =>
{
document.Info = new()
{
Title = "Checkout API",
Version = "v1",
Description = "API for processing checkouts from cart."
};
return Task.CompletedTask;
});
});
var app = builder.Build();
app.MapOpenApi();
app.MapGet("/", () => "Hello world!");
app.Run();
Преобразователи документов, активируемые службой, могут использовать экземпляры из DI для изменения приложения. В следующем примере показан преобразователь документов, использующий IAuthenticationSchemeProvider службу из уровня проверки подлинности. Он проверяет, зарегистрированы ли в приложении схемы, связанные с носителями JWT, и добавляет их на верхний уровень документа OpenAPI:
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
var builder = WebApplication.CreateBuilder();
builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddOpenApi(options =>
{
options.AddDocumentTransformer<BearerSecuritySchemeTransformer>();
});
var app = builder.Build();
app.MapOpenApi();
app.MapGet("/", () => "Hello world!");
app.Run();
internal sealed class BearerSecuritySchemeTransformer(IAuthenticationSchemeProvider authenticationSchemeProvider) : IOpenApiDocumentTransformer
{
public async Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransformerContext context, CancellationToken cancellationToken)
{
var authenticationSchemes = await authenticationSchemeProvider.GetAllSchemesAsync();
if (authenticationSchemes.Any(authScheme => authScheme.Name == "Bearer"))
{
var requirements = new Dictionary<string, OpenApiSecurityScheme>
{
["Bearer"] = new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
Scheme = "bearer", // "bearer" refers to the header name here
In = ParameterLocation.Header,
BearerFormat = "Json Web Token"
}
};
document.Components ??= new OpenApiComponents();
document.Components.SecuritySchemes = requirements;
}
}
}
Преобразователи документов уникальны для экземпляра документа, с которым они связаны. В следующем примере преобразователь:
- Регистрирует требования, связанные с проверкой подлинности, в документе
internal
. - Оставляет
public
документ не измененным.
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
var builder = WebApplication.CreateBuilder();
builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddOpenApi("internal", options =>
{
options.AddDocumentTransformer<BearerSecuritySchemeTransformer>();
});
builder.Services.AddOpenApi("public");
var app = builder.Build();
app.MapOpenApi();
app.MapGet("/world", () => "Hello world!")
.WithGroupName("internal");
app.MapGet("/", () => "Hello universe!")
.WithGroupName("public");
app.Run();
internal sealed class BearerSecuritySchemeTransformer(IAuthenticationSchemeProvider authenticationSchemeProvider) : IOpenApiDocumentTransformer
{
public async Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransformerContext context, CancellationToken cancellationToken)
{
var authenticationSchemes = await authenticationSchemeProvider.GetAllSchemesAsync();
if (authenticationSchemes.Any(authScheme => authScheme.Name == "Bearer"))
{
// Add the security scheme at the document level
var requirements = new Dictionary<string, OpenApiSecurityScheme>
{
["Bearer"] = new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
Scheme = "bearer", // "bearer" refers to the header name here
In = ParameterLocation.Header,
BearerFormat = "Json Web Token"
}
};
document.Components ??= new OpenApiComponents();
document.Components.SecuritySchemes = requirements;
// Apply it as a requirement for all operations
foreach (var operation in document.Paths.Values.SelectMany(path => path.Operations))
{
operation.Value.Security.Add(new OpenApiSecurityRequirement
{
[new OpenApiSecurityScheme { Reference = new OpenApiReference { Id = "Bearer", Type = ReferenceType.SecurityScheme } }] = Array.Empty<string>()
});
}
}
}
}
Использование преобразователей операций
Операции — это уникальные сочетания путей и методов HTTP в документе OpenAPI. Преобразователи операций полезны при изменении:
- Необходимо сделать каждую конечную точку в приложении или
- Условно применяется к определенным маршрутам.
Преобразователи операций имеют доступ к объекту контекста, который содержит:
- Имя документа, к которому принадлежит операция.
- Объект ApiDescription, связанный с операцией.
- Используется IServiceProvider в создании документов.
Например, следующий преобразователь операций добавляется 500
в виде кода состояния ответа, поддерживаемого всеми операциями в документе.
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
var builder = WebApplication.CreateBuilder();
builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddOpenApi(options =>
{
options.AddOperationTransformer((operation, context, cancellationToken) =>
{
operation.Responses.Add("500", new OpenApiResponse { Description = "Internal server error" });
return Task.CompletedTask;
});
});
var app = builder.Build();
app.MapOpenApi();
app.MapGet("/", () => "Hello world!");
app.Run();
Использование преобразователей схем
Схемы — это модели данных, используемые в телах запросов и ответов в документе OpenAPI. Преобразователи схем полезны при изменении:
- Должен быть сделан для каждой схемы в документе или
- Условно применяется к определенным схемам.
Преобразователи схемы имеют доступ к объекту контекста, который содержит:
- Имя документа, к которому принадлежит схема.
- Сведения о типе JSON, связанные с целевой схемой.
- Используется IServiceProvider в создании документов.
Например, следующий преобразователь схемы задает format
десятичные типы decimal
вместо double
:
using Microsoft.AspNetCore.OpenApi;
var builder = WebApplication.CreateBuilder();
builder.Services.AddOpenApi(options => {
// Schema transformer to set the format of decimal to 'decimal'
options.AddSchemaTransformer((schema, context, cancellationToken) =>
{
if (context.JsonTypeInfo.Type == typeof(decimal))
{
schema.Format = "decimal";
}
return Task.CompletedTask;
});
});
var app = builder.Build();
app.MapOpenApi();
app.MapGet("/", () => new Body { Amount = 1.1m });
app.Run();
public class Body {
public decimal Amount { get; set; }
}
Дополнительные ресурсы
Минимальные API обеспечивают встроенную поддержку создания сведений о конечных точках в приложении с помощью Microsoft.AspNetCore.OpenApi
пакета. Для предоставления созданного определения OpenAPI через визуальный пользовательский интерфейс требуется сторонний пакет. Сведения о поддержке OpenAPI в API на основе контроллеров см. в версии .NET 9 этой статьи.
Следующий код создается шаблоном ASP.NET Core для минимального веб-API и использует стандарт OpenAPI:
using Microsoft.AspNetCore.OpenApi;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
var summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
app.MapGet("/weatherforecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateTime.Now.AddDays(index),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
})
.WithName("GetWeatherForecast")
.WithOpenApi();
app.Run();
internal record WeatherForecast(DateTime Date, int TemperatureC, string? Summary)
{
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
В предыдущем выделенном коде:
Microsoft.AspNetCore.OpenApi
рассматривается в следующем разделе;- AddEndpointsApiExplorer настраивает в приложении обнаружение и описание конечных точек с заметками по умолчанию с помощью обозревателя API;
WithOpenApi
переопределяет заметки по умолчанию, созданные обозревателем API, соответствующими заметками, которые были созданы из пакетаMicrosoft.AspNetCore.OpenApi
; UseSwagger
добавляет ПО промежуточного слоя Swagger;- UseSwaggerUI включает встроенную версию средства пользовательского интерфейса Swagger.
- WithName означает, что IEndpointNameMetadata для конечной точки используется для создания ссылок и рассматривается как идентификатор операции в спецификации OpenAPI для конкретной конечной точки;
WithOpenApi
объясняется далее в этой статье.
пакет NuGet Microsoft.AspNetCore.OpenApi
;
ASP.NET Core предоставляет пакет Microsoft.AspNetCore.OpenApi
для взаимодействия со спецификациями OpenAPI для конечных точек. Этот пакет создает связь между моделями OpenAPI, определенными в пакете Microsoft.AspNetCore.OpenApi
, и конечными точками, определенными в минимальных API. Этот пакет предоставляет API, который проверяет параметры, ответы и метаданные конечной точки и создает тип заметки OpenAPI, подходящий для описания этой конечной точки.
Microsoft.AspNetCore.OpenApi
добавляется в проект в формате PackageReference (ссылка на пакет):
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.*-*" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
</Project>
При использовании с Swashbuckle.AspNetCore
Microsoft.AspNetCore.OpenApi
параметром Swashbuckle.AspNetCore
6.4.0 или более поздней версии необходимо использовать. Microsoft.OpenApi
Для использования конструкторов копирования в WithOpenApi
вызовах необходимо использовать 1.4.3 или более поздней версии.
Добавление заметок OpenAPI в конечные точки с помощью WithOpenApi
Вызов WithOpenApi
конечной точки добавляется в метаданные конечной точки. Эти метаданные применяются следующим образом.
- Используются в сторонних пакетах, например Swashbuckle.AspNetCore.
- Отображается в пользовательском интерфейсе Swagger или в YAML или JSON, созданном для определения API.
app.MapPost("/todoitems/{id}", async (int id, Todo todo, TodoDb db) =>
{
todo.Id = id;
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
})
.WithOpenApi();
Изменение заметки OpenAPI в WithOpenApi
Метод WithOpenApi
принимает функцию, которую можно использовать для изменения заметки OpenAPI. Например, следующий код добавляет описание в первый параметр конечной точки:
app.MapPost("/todo2/{id}", async (int id, Todo todo, TodoDb db) =>
{
todo.Id = id;
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
})
.WithOpenApi(generatedOperation =>
{
var parameter = generatedOperation.Parameters[0];
parameter.Description = "The ID associated with the created Todo";
return generatedOperation;
});
Добавление идентификаторов операций в OpenAPI
Идентификаторы операций используются для уникальной идентификации заданной конечной точки в OpenAPI. WithName
Метод расширения можно использовать для задания идентификатора операции, используемого для метода.
app.MapGet("/todoitems2", async (TodoDb db) =>
await db.Todos.ToListAsync())
.WithName("GetToDoItems");
Кроме того, OperationId
свойство можно задать непосредственно в заметке OpenAPI.
app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
.WithOpenApi(operation => new(operation)
{
OperationId = "GetTodos"
});
Добавление тегов в описание OpenAPI
OpenAPI поддерживает использование объектов тегов для классификации операций. Эти теги обычно используются для группирования операций в пользовательском интерфейсе Swagger. Эти теги можно добавить в операцию, вызвав метод расширения WithTags в конечной точке с нужными тегами.
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.ToListAsync())
.WithTags("TodoGroup");
Кроме того, список OpenApiTags
можно задать в заметке OpenAPI с помощью WithOpenApi
метода расширения.
app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
.WithOpenApi(operation => new(operation)
{
Tags = new List<OpenApiTag> { new() { Name = "Todos" } }
});
Добавление сводки или описания конечной точки
Сводка и описание конечной WithOpenApi
точки можно добавить, вызвав метод расширения. В следующем коде сводки задаются непосредственно в заметке OpenAPI.
app.MapGet("/todoitems2", async (TodoDb db) => await db.Todos.ToListAsync())
.WithOpenApi(operation => new(operation)
{
Summary = "This is a summary",
Description = "This is a description"
});
Исключение описания OpenAPI
В следующем примере конечная точка /skipme
исключается из создания описания OpenAPI:
using Microsoft.AspNetCore.OpenApi;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.MapGet("/swag", () => "Hello Swagger!")
.WithOpenApi();
app.MapGet("/skipme", () => "Skipping Swagger.")
.ExcludeFromDescription();
app.Run();
Пометить API как устаревший
Чтобы пометить конечную точку как устаревшую, задайте Deprecated
свойство в заметке OpenAPI.
app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
.WithOpenApi(operation => new(operation)
{
Deprecated = true
});
Описание типов ответов
OpenAPI поддерживает описание ответов, возвращаемых API. Минимальные API поддерживают три стратегии настройки типа ответа конечной точки:
- С помощью метода расширения в конечной
Produces
точке - С помощью атрибута
ProducesResponseType
в обработчике маршрутов - Возврат
TypedResults
из обработчика маршрутов
Produces
Метод расширения можно использовать для добавления Produces
метаданных в конечную точку. Если параметры отсутствуют, метод расширения заполняет метаданные целевого типа в коде 200
состояния и application/json
типе контента.
app
.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
.Produces<IList<Todo>>();
Использование TypedResults
в реализации обработчика маршрутов конечной точки автоматически включает метаданные типа ответа для конечной точки. Например, следующий код автоматически заметит конечную точку с ответом в коде 200
состояния с типом application/json
контента.
app.MapGet("/todos", async (TodoDb db) =>
{
var todos = await db.Todos.ToListAsync());
return TypedResults.Ok(todos);
});
Настройка ответов для ProblemDetails
При настройке типа ответа для конечных точек, которые могут возвращать ответ ProblemDetails, ProducesProblem метод ProducesValidationProblemрасширения или TypedResults.Problem
можно использовать для добавления соответствующей заметки в метаданные конечной точки. Обратите внимание, что ProducesProblem
методы расширения и ProducesValidationProblem
методы расширения нельзя использовать с группами маршрутов в .NET 8 и более ранних версиях.
Если нет явных заметок, предоставляемых одной из описанных выше стратегий, платформа пытается определить тип ответа по умолчанию, проверив подпись ответа. Этот ответ по умолчанию заполняется 200
кодом состояния в определении OpenAPI.
Несколько типов ответов
Если конечная точка может возвращать различные типы ответов в разных сценариях, можно предоставить метаданные следующим образом:
Produces
Вызов метода расширения несколько раз, как показано в следующем примере:app.MapGet("/api/todoitems/{id}", async (int id, TodoDb db) => await db.Todos.FindAsync(id) is Todo todo ? Results.Ok(todo) : Results.NotFound()) .Produces<Todo>(StatusCodes.Status200OK) .Produces(StatusCodes.Status404NotFound);
Используйте
Results<TResult1,TResult2,TResultN>
сигнатуру иTypedResults
в тексте обработчика, как показано в следующем примере:app.MapGet("/book/{id}", Results<Ok<Book>, NotFound> (int id, List<Book> bookList) => { return bookList.FirstOrDefault((i) => i.Id == id) is Book book ? TypedResults.Ok(book) : TypedResults.NotFound(); });
Results<TResult1,TResult2,TResultN>
Типы объединения объявляют, что обработчик маршрутов возвращает несколькоIResult
конкретных типов, и любой из этих типов, которые реализуютIEndpointMetadataProvider
, будут способствовать метаданным конечной точки.Типы объединения реализуют неявные операторы приведения. Эти операторы позволяют компилятору автоматически преобразовывать типы, указанные в универсальных аргументах, в экземпляр типа объединения. Эта возможность обладает дополнительным преимуществом для проверки времени компиляции, что обработчик маршрутов возвращает только результаты, объявленные им. Попытка вернуть тип, который не объявлен как один из универсальных аргументов, приводит к
Results<TResult1,TResult2,TResultN>
ошибке компиляции.
Описание текста запроса и параметров
Помимо описания типов, возвращаемых конечной точкой, OpenAPI также поддерживает аннотирование входных данных, используемых API. Эти входные данные делятся на две категории:
- Параметры, отображаемые в пути, строке запроса, заголовках или файлах cookie
- Данные, передаваемые как часть текста запроса
Платформа определяет типы параметров запроса в пути, запросе и строке заголовка автоматически на основе подписи обработчика маршрутов.
Чтобы определить тип входных данных, передаваемых в виде текста запроса, настройте свойства с помощью Accepts
метода расширения для определения типа объекта и типа контента, ожидаемого обработчиком запроса. В следующем примере конечная точка принимает Todo
объект в тексте запроса с ожидаемым типом application/xml
контента.
app.MapPost("/todos/{id}", (int id, Todo todo) => ...)
.Accepts<Todo>("application/xml");
Accepts
Помимо метода расширения тип параметра может описать собственную заметку, реализуя IEndpointParameterMetadataProvider
интерфейс. Например, следующий Todo
тип добавляет заметку, требующую текст запроса с типом application/xml
контента.
public class Todo : IEndpointParameterMetadataProvider
{
public static void PopulateMetadata(ParameterInfo parameter, EndpointBuilder builder)
{
builder.Metadata.Add(new ConsumesAttribute(typeof(Todo), isOptional: false, "application/xml"));
}
}
Если нет явной заметки, платформа пытается определить тип запроса по умолчанию, если в обработчике конечной точки есть параметр текста запроса. Вывод использует следующие эвристики для создания заметки:
- Параметры текста запроса, которые считываются из формы с помощью атрибута
[FromForm]
, описываются с типомmultipart/form-data
контента. - Все остальные параметры текста запроса описываются с типом
application/json
контента. - Текст запроса рассматривается как необязательный, если он имеет значение NULL или
AllowEmpty
если свойство задано для атрибутаFromBody
.
Поддержка управления версиями API
Минимальные API поддерживают управление версиями API с помощью пакета Asp.Versioning.Http. Примеры настройки управления версиями с минимальными API можно найти в репозитории управления версиями API.
Исходный код OpenAPI ASP.NET Core на GitHub
Дополнительные ресурсы
Минимальное приложение API может описать спецификацию OpenAPI для обработчиков маршрутов с помощью Swashbuckle.
Сведения о поддержке OpenAPI в API на основе контроллеров см. в версии .NET 9 этой статьи.
Следующий код является типичным приложением ASP.NET Core с поддержкой OpenAPI:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new() { Title = builder.Environment.ApplicationName,
Version = "v1" });
});
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger(); // UseSwaggerUI Protected by if (env.IsDevelopment())
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json",
$"{builder.Environment.ApplicationName} v1"));
}
app.MapGet("/swag", () => "Hello Swagger!");
app.Run();
Исключение описания OpenAPI
В следующем примере конечная точка /skipme
исключается из создания описания OpenAPI:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(); // UseSwaggerUI Protected by if (env.IsDevelopment())
}
app.MapGet("/swag", () => "Hello Swagger!");
app.MapGet("/skipme", () => "Skipping Swagger.")
.ExcludeFromDescription();
app.Run();
Описание типов ответов
В следующем примере для настройки ответа используются встроенные типы результатов:
app.MapGet("/api/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound())
.Produces<Todo>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound);
Добавление идентификаторов операций в OpenAPI
app.MapGet("/todoitems2", async (TodoDb db) =>
await db.Todos.ToListAsync())
.WithName("GetToDoItems");
Добавление тегов в описание OpenAPI
В следующем коде используется тег группирования OpenAPI:
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.ToListAsync())
.WithTags("TodoGroup");
ASP.NET Core