Поддержка OpenAPI в минимальных приложениях API
Спецификация OpenAPI — это стандарт программирования, не зависящий от языка для документирования API HTTP. Этот стандарт поддерживается в минимальных API с помощью сочетания встроенных API и библиотек с открытым кодом. В приложении существует три ключевых аспекта интеграции OpenAPI:
- Создание сведений о конечных точках в приложении.
- Сбор сведений в формате, который соответствует схеме OpenAPI.
- Предоставление созданной схемы OpenAPI с помощью визуального интерфейса или сериализованного файла.
Минимальные API обеспечивают встроенную поддержку создания сведений о конечных точках в приложении с помощью Microsoft.AspNetCore.OpenApi
пакета. Для предоставления созданного определения OpenAPI через визуальный пользовательский интерфейс требуется сторонний пакет.
Следующий код создается шаблоном 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; ТребуетсяSwashbuckle.AspNetCore
пакет nuget.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
метод расширения или TypedResults.Problem
можно использовать для добавления соответствующей заметки в метаданные конечной точки.
Если нет явных заметок, предоставляемых одной из описанных выше стратегий, платформа пытается определить тип ответа по умолчанию, проверив подпись ответа. Этот ответ по умолчанию заполняется 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. Эти входные данные делятся на две категории:
- Параметры, отображаемые в пути, строке запроса, заголовках или cookies
- Данные, передаваемые как часть текста запроса
Платформа определяет типы параметров запроса в пути, запросе и строке заголовка автоматически на основе подписи обработчика маршрутов.
Чтобы определить тип входных данных, передаваемых в виде текста запроса, настройте свойства с помощью 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
Дополнительные ресурсы
Спецификация OpenAPI — это стандарт программирования, не зависящий от языка для документирования API HTTP. Этот стандарт поддерживается в минимальных API с помощью сочетания встроенных API и библиотек с открытым кодом. В приложении существует три ключевых аспекта интеграции OpenAPI:
- Создание сведений о конечных точках в приложении.
- Сбор сведений в формате, который соответствует схеме OpenAPI.
- Предоставление созданной схемы OpenAPI с помощью визуального интерфейса или сериализованного файла.
Минимальные API обеспечивают встроенную поддержку создания сведений о конечных точках в приложении с помощью Microsoft.AspNetCore.OpenApi
пакета. Для предоставления созданного определения OpenAPI через визуальный пользовательский интерфейс требуется сторонний пакет.
Следующий код создается шаблоном 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
метод расширения или TypedResults.Problem
можно использовать для добавления соответствующей заметки в метаданные конечной точки.
Если нет явных заметок, предоставляемых одной из описанных выше стратегий, платформа пытается определить тип ответа по умолчанию, проверив подпись ответа. Этот ответ по умолчанию заполняется 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. Эти входные данные делятся на две категории:
- Параметры, отображаемые в пути, строке запроса, заголовках или cookies
- Данные, передаваемые как часть текста запроса
Платформа определяет типы параметров запроса в пути, запросе и строке заголовка автоматически на основе подписи обработчика маршрутов.
Чтобы определить тип входных данных, передаваемых в виде текста запроса, настройте свойства с помощью 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
Дополнительные ресурсы
Приложение может описать спецификацию OpenAPI для обработчиков маршрутов с помощью Swashbuckle.
Следующий код является типичным приложением 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
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по