OpenAPI 문서 생성
이 패키지는 Microsoft.AspNetCore.OpenApi
ASP.NET Core에서 OpenAPI 문서 생성을 기본적으로 지원합니다. 패키지는 다음과 같은 기능을 제공합니다.
- 런타임에 OpenAPI 문서를 생성하고 애플리케이션의 엔드포인트를 통해 액세스할 수 있도록 지원합니다.
- 생성된 문서를 수정할 수 있는 "변환기" API를 지원합니다.
- 단일 앱에서 여러 OpenAPI 문서 생성을 지원합니다.
- 에서 제공하는
System.Text.Json
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 서비스를 추가합니다.
- 엔드포인트가 JSON 형식으로 OpenAPI 문서를 볼 수 있도록 합니다.
var builder = WebApplication.CreateBuilder();
builder.Services.AddOpenApi();
var app = builder.Build();
app.MapOpenApi();
app.MapGet("/", () => "Hello world!");
app.Run();
앱을 시작하고 생성된 OpenAPI 문서를 보려면 이동합니다 https://localhost:<port>/openapi/v1.json
.
ASP.NET 웹앱에 OpenAPI 메타데이터 포함
엔드포인트에 대한 OpenAPI 메타데이터 포함
ASP.NET 웹앱의 엔드포인트에서 메타데이터를 수집하고 이를 사용하여 OpenAPI 문서를 생성합니다.
컨트롤러 기반 앱에서 메타데이터는 < [HttpPost]
a0/>와 같은 [EndpointDescription]
특성에서 수집됩니다[Produces]
.
최소 API에서는 특성에서 메타데이터를 수집할 수 있지만 확장 메서드 및 경로 처리기에서 반환하는 TypedResults 등의 기타 전략을 사용하여 설정할 수도 있습니다.
다음 표에서는 수집된 메타데이터 및 설정 전략에 대한 개요를 제공합니다.
메타데이터 | attribute | 확장 메서드 | 기타 전략 |
---|---|---|---|
요약 | [EndpointSummary] |
WithSummary | |
description | [EndpointDescription] |
WithDescription | |
tags | [Tags] |
WithTags | |
operationId | [EndpointName] |
WithName | |
매개 변수 | [FromQuery] , [FromRoute] , [FromHeader] [FromForm] |
||
매개 변수 설명 | [EndpointDescription] |
||
requestBody | [FromBody] |
Accepts | |
응답 | [Produces] |
Produces, ProducesProblem | TypedResults |
엔드포인트 제외 | [ExcludeFromDescription] , [ApiExplorerSettings] |
ExcludeFromDescription |
ASP.NET Core는 XML 문서 주석에서 메타데이터를 수집하지 않습니다.
다음 섹션에서는 생성된 OpenAPI 문서를 사용자 지정하기 위해 앱에 메타데이터를 포함하는 방법을 보여 줍니다.
요약 및 설명
엔드포인트 요약 및 설명은 및 [EndpointDescription]
특성 또는 최소 API에서 확장 메서드 및 WithDescription 확장 메서드를 사용하여 WithSummary 설정할 [EndpointSummary]
수 있습니다.
다음 샘플에서는 요약 및 설명을 설정하기 위한 다양한 전략을 보여 줍니다.
특성은 앱이 아닌 대리자 메서드에 배치됩니다. 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는 각 엔드포인트에서 operationId를 작업의 고유 식별자 또는 이름으로 지원합니다.
최소 API에서 operationId는 특성 또는 WithName 확장 메서드를 [EndpointName]
사용하여 설정할 수 있습니다.
다음 샘플에서는 operationId를 설정하기 위한 다양한 전략을 보여 줍니다.
app.MapGet("/extension-methods", () => "Hello world!")
.WithName("FromExtensionMethods");
app.MapGet("/attributes",
[EndpointName("FromAttributes")]
() => "Hello world!");
매개 변수
OpenAPI는 API에서 사용하는 경로, 쿼리 문자열, 헤더 및 cookie 매개 변수에 주석을 추가합니다.
프레임워크는 경로 처리기의 서명에 따라 요청 매개 변수의 형식을 자동으로 유추합니다.
이 [EndpointDescription]
특성을 사용하여 매개 변수에 대한 설명을 제공할 수 있습니다.
다음 샘플에서는 매개 변수에 대한 설명을 설정하는 방법을 보여 줍니다.
app.MapGet("/attributes",
([Description("This is a description.")] string name) => "Hello world!");
요청 본문 설명
requestBody
OpenAPI의 필드는 지원되는 콘텐츠 형식 및 본문 콘텐츠에 대한 스키마를 포함하여 API 클라이언트가 서버에 보낼 수 있는 요청의 본문을 설명합니다.
엔드포인트 처리기 메서드가 요청 본문에서 바인딩된 매개 변수를 수락하면 ASP.NET Core는 OpenAPI 문서에서 작업에 해당하는 requestBody
매개 변수를 생성합니다. 특성 또는 확장 메서드를 사용하여 요청 본문에 대한 메타데이터를 지정할 수도 있습니다. 문서 변환기 또는 작업 변환기를 사용하여 추가 메타데이터를 설정할 수 있습니다.
엔드포인트가 요청 본문에 바인딩된 매개 변수를 정의하지 않고 대신 직접 요청 본문을 HttpContext 사용하는 경우 ASP.NET Core는 요청 본문 메타데이터를 지정하는 메커니즘을 제공합니다. 이는 요청 본문을 스트림으로 처리하는 엔드포인트에 대한 일반적인 시나리오입니다.
일부 요청 본문 메타데이터는 경로 처리기 메서드의 FromBody
매개 변수에서 FromForm
확인할 수 있습니다.
요청 본문에 대한 설명은 매개 변수에 대한 특성과 함께 [Description]
FromBody
설정할 수 있습니다 FromForm
.
매개 변수가 FromBody
null을 허용하지 EmptyBodyBehavior 않고 특성에서 FromBody
설정 Allow 되지 않은 경우 요청 본문이 필요하며 required
생성된 OpenAPI 문서에서 해당 필드 requestBody
가 설정 true
됩니다.
양식 본문은 항상 필수이며 required
true
.
문서 변환기 또는 작업 변환기를 사용하여 , 또는 필드를 설정example
examples
하거나 encoding
생성된 OpenAPI 문서에서 요청 본문에 대한 사양 확장을 추가합니다.
요청 본문 메타데이터를 설정하는 다른 메커니즘은 개발 중인 앱의 유형에 따라 달라지며 다음 섹션에 설명되어 있습니다.
생성된 OpenAPI 문서의 요청 본문에 대한 콘텐츠 형식은 요청 본문에 바인딩되거나 확장 메서드로 Accepts 지정된 매개 변수 형식에서 결정됩니다.
기본적으로 매개 변수의 콘텐츠 형식은 FromBody
/>이고 매개 변수의 콘텐츠 형식 FromForm
은 multipart/form-data
.application/json
이러한 기본 콘텐츠 형식에 대한 지원은 최소 API에 기본 제공되며 사용자 지정 바인딩을 사용하여 다른 콘텐츠 형식을 처리할 수 있습니다. 자세한 내용은 최소 API 설명서의 사용자 지정 바인딩 항목을 참조하세요.
요청 본문에 다른 콘텐츠 형식을 지정하는 방법에는 여러 가지가 있습니다.
매개 변수 형식 FromBody
이 구현되는 경우 ASP.NET Core는 이 인터페이스를 사용하여 요청 본문의 콘텐츠 형식을 결정합니다 IEndpointParameterMetadataProvider.
프레임워크는 이 인터페이스의 메서드를 사용하여 PopulateMetadata 요청 본문의 콘텐츠 형식 및 본문 콘텐츠 형식을 설정합니다. 예를 들어 Todo
콘텐츠 형식 또는 application/xml
text/xml
콘텐츠 형식을 허용하는 클래스는 이 정보를 프레임워크에 제공하는 데 사용할 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 사용하여 요청 본문의 콘텐츠 형식을 지정할 수도 있습니다.
다음 예제에서 엔드포인트는 요청 본문에 예상되는 콘텐츠 형식이 application/xml
인 Todo
개체를 허용합니다.
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 메서드와 ProducesProblem 확장 메서드는 둘 다 RouteHandlerBuilder 에서 RouteGroupBuilder지원됩니다. 예를 들어 그룹의 모든 작업에 대해 일반적인 오류 응답 집합을 정의할 수 있습니다.
이전 전략 중 하나로 지정하지 않은 경우 다음을 수행합니다.
- 응답의 상태 코드는 기본적으로 200입니다.
- 응답 본문에 대한 스키마는 엔드포인트 메서드의 암시적 또는 명시적 반환 형식에서 유추할 수 있습니다( 예: in에서
T
Task<TResult>). 그렇지 않으면 지정되지 않은 것으로 간주됩니다. - 지정하거나 유추된 응답 본문의 콘텐츠 형식은 "application/json"입니다.
최소 API Produces 에서 확장 메서드와 특성은 [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를 사용하면 엔드포인트에 대한 응답 형식 메타데이터가 자동으로 포함됩니다. 예를 들어, 다음 코드는 application/json
콘텐츠 형식의 200
상태 코드 아래에 응답으로 엔드포인트에 자동으로 주석을 추가합니다.
app.MapGet("/todos", async (TodoDb db) =>
{
var todos = await db.Todos.ToListAsync();
return TypedResults.Ok(todos);
});
OpenAPI 문서에서 항목 만들기를 구현 IEndpointMetadataProvider 하는 responses
형식만 반환합니다. 다음은 항목을 생성하는 도우미 메서드의 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) 범위의 상태 코드가 있는 경우
ProblemDetails 응답을 반환하도록 최소 API 앱을 구성하는 방법에 대한 자세한 내용은 최소 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 문서에서 지정된 엔드포인트를 제외하기 위한 두 가지 전략을 지원합니다.
다음 샘플에서는 생성된 OpenAPI 문서에서 지정된 엔드포인트를 제외하기 위한 다양한 전략을 보여 줍니다.
app.MapGet("/extension-method", () => "Hello world!")
.ExcludeFromDescription();
app.MapGet("/attributes",
[ExcludeFromDescription]
() => "Hello world!");
데이터 형식에 대한 OpenAPI 메타데이터 포함
요청 또는 응답 본문에 사용되는 C# 클래스 또는 레코드는 생성된 OpenAPI 문서에서 스키마로 표시됩니다. 기본적으로 공용 속성만 스키마에 표시되지만 JsonSerializerOptions 필드에 대한 스키마 속성도 만들어야 합니다.
PropertyNamingPolicy 카멜 대/소문자(ASP.NET 웹 애플리케이션의 기본값)로 설정된 경우 스키마의 속성 이름은 클래스 또는 레코드 속성 이름의 camel 대/소문자 형식입니다.
[JsonPropertyName]
개별 속성에서 스키마의 속성 이름을 지정하는 데 사용할 수 있습니다.
형식 및 형식
JSON 스키마 라이브러리는 다음과 같이 표준 C# 형식을 OpenAPI type
format
에 매핑합니다.
C# 형식 | OpenAPI type |
OpenAPI format |
---|---|---|
int | 정수 | int32 |
long | 정수 | int64 |
short | 정수 | int16 |
바이트 | 정수 | uint8 |
float | 번호 | float |
double | 번호 | double |
decimal | 번호 | double |
bool | 부울 값 | |
string | string | |
char | string | char |
byte[] | string | 바이트 |
DateTimeOffset | string | 날짜-시간 |
DateOnly | string | date |
TimeOnly | string | 시간 |
URI | string | uri |
GUID | string | uuid |
개체 | 생략 | |
dynamic | 생략 |
개체 및 동적 형식은 Int 또는 문자열과 같은 기본 형식을 포함하여 모든 형식의 데이터를 포함할 수 있으므로 OpenAPI에 정의된 형식이 없습니다 .
type
format
스키마 변환기를 사용하여 설정할 수도 있습니다. 예를 들어 10진수 형식이 format
대신 되도록 decimal
double
할 수 있습니다.
특성을 사용하여 메타데이터 추가
ASP.NET 클래스 또는 레코드 속성의 특성에서 메타데이터를 사용하여 생성된 스키마의 해당 속성에 대한 메타데이터를 설정합니다.
다음 표에는 생성된 스키마에 대한 메타데이터를 System.ComponentModel
제공하는 네임스페이스의 특성이 요약되어 있습니다.
attribute | 설명 |
---|---|
[Description] |
스키마에서 description 속성의 집합입니다. |
[Required] |
스키마에서와 같이 required 속성을 표시합니다. |
[DefaultValue] |
스키마의 default 속성 값을 설정합니다. |
[Range] |
정수 minimum 또는 숫자의 값과 maximum 값을 설정합니다. |
[MinLength] |
문자열을 minLength 설정합니다. |
[MaxLength] |
문자열을 maxLength 설정합니다. |
[RegularExpression] |
문자열을 pattern 설정합니다. |
컨트롤러 기반 앱에서 이러한 특성은 들어오는 데이터가 제약 조건을 충족하는지 확인하기 위해 작업에 필터를 추가합니다. 최소 API에서 이러한 특성은 생성된 스키마에서 메타데이터를 설정하지만 유효성 검사는 엔드포인트 필터, 경로 처리기 논리 또는 타사 패키지를 통해 명시적으로 수행되어야 합니다.
생성된 스키마에 대한 메타데이터의 다른 원본
필수
필요한 한정자로 속성을 표시 required
할 수도 있습니다.
enum
C#의 열거형 형식은 정수 기반이지만 a 및 a [JsonConverter]
JsonStringEnumConverter를 사용하여 JSON에서 문자열로 나타낼 수 있습니다. 열거형 형식이 JSON에서 문자열로 표현되면 생성된 스키마에는 enum
열거형의 문자열 값이 있는 속성이 있습니다.
없는 열거형 형식 [JsonConverter]
은 생성된 스키마에서와 같이 type: integer
정의됩니다.
참고: [AllowedValues]
속성 값을 설정 enum
하지 않습니다.
nullable
nullable 값 또는 참조 형식으로 정의된 속성은 생성된 스키마에 있습니다 nullable: true
. 이는 nullable 속성에 System.Text.Json 유효한 값으로 허용하는 null
역직렬 변환기의 기본 동작과 일치합니다.
additionalProperties
스키마는 기본적으로 어설션 없이 additionalProperties
생성되며 이는 기본값 true
을 의미합니다. 이는 JSON 개체의 System.Text.Json 추가 속성을 자동으로 무시하는 역직렬 변환기의 기본 동작과 일치합니다.
스키마의 추가 속성에 특정 형식의 값만 있어야 하는 경우 속성 또는 클래스를 Dictionary<string, type>
로 정의합니다. 사전의 키 형식은 .이어야 string
합니다. 이렇게 하면 "type"에 대한 스키마를 필수 값 형식으로 지정하는 스키마 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
매개 변수 인수로 제공됩니다. 다음 요청은 해당 및 internal
문서를 확인 v1
합니다.
GET http://localhost:5000/openapi/v1.json
GET http://localhost:5000/openapi/internal.json
생성된 문서의 OpenAPI 버전 사용자 지정
기본적으로 OpenAPI 문서 생성은 OpenAPI 사양의 v3.0을 준수하는 문서를 만듭니다. 다음 코드는 OpenAPI 문서의 기본 버전을 수정하는 방법을 보여 줍니다.
builder.Services.AddOpenApi(options =>
{
options.OpenApiVersion = OpenApiSpecVersion.OpenApi2_0;
});
OpenAPI 엔드포인트 경로 사용자 지정
기본적으로 호출 MapOpenApi 을 통해 등록된 OpenAPI 엔드포인트는 엔드포인트에 /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 컨텍스트의 세부 정보를 사용하여 요청을 다시 생성합니다. 해당하는 경우 각 HTTP 요청에서 문서 생성 파이프라인을 실행하지 않도록 OpenAPI 문서를 캐시할 수 있습니다.
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 문서 사용자 지정
변환기는 사용자 정의 사용자 지정을 사용하여 OpenAPI 문서를 수정하기 위한 API를 제공합니다. 변환기는 다음과 같은 시나리오에 유용합니다.
- 문서의 모든 작업에 매개 변수를 추가합니다.
- 매개 변수 또는 작업에 대한 설명 수정
- OpenAPI 문서에 최상위 정보 추가
변환기는 다음 세 가지 범주로 분류됩니다.
- 문서 변환기는 전체 OpenAPI 문서에 액세스할 수 있습니다. 문서를 전역으로 수정하는 데 사용할 수 있습니다.
- 작업 변환기는 각 개별 작업에 적용됩니다. 각 개별 작업은 경로와 HTTP 메서드의 조합입니다. 엔드포인트에서 매개 변수 또는 응답을 수정하는 데 사용할 수 있습니다.
- 스키마 변환기는 문서의 각 스키마에 적용됩니다. 요청 또는 응답 본문 또는 중첩된 스키마의 스키마를 수정하는 데 사용할 수 있습니다.
변환기는 개체의 메서드 OpenApiOptions 를 호출 AddDocumentTransformer 하여 문서에 등록할 수 있습니다. 다음 코드 조각은 변환기를 문서에 등록하는 다양한 방법을 보여줍니다.
- 대리자를 사용하여 문서 변환기를 등록합니다.
- 인스턴스를 사용하여 문서 변환기를 등록합니다 IOpenApiDocumentTransformer.
- DI 활성화를 사용하여 문서 변환기를 등록합니다 IOpenApiDocumentTransformer.
- 대리자를 사용하여 작업 변환기를 등록합니다.
- 인스턴스를 사용하여 작업 변환기를 등록합니다 IOpenApiOperationTransformer.
- DI 활성화를 사용하여 작업 변환기를 등록합니다 IOpenApiOperationTransformer.
- 대리자를 사용하여 스키마 변환기를 등록합니다.
- 인스턴스를 사용하여 스키마 변환기를 등록합니다 IOpenApiSchemaTransformer.
- DI 활성화를 사용하여 스키마 변환기를 등록합니다 IOpenApiSchemaTransformer.
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 문서를 변경할 수도 있습니다. 다음 예제에서는 OpenAPI 문서에 API에 대한 일부 정보를 추가하는 문서 변환기를 보여 줍니다.
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>()
});
}
}
}
}
작업 변환기 사용
작업은 OpenAPI 문서에서 HTTP 경로 및 메서드의 고유한 조합입니다. 작업 변환기는 다음과 같이 수정할 때 유용합니다.
- 앱의 각 엔드포인트에 대해 만들어야 합니다. 또는
- 특정 경로에 조건부로 적용됩니다.
작업 변환기는 다음을 포함하는 컨텍스트 개체에 액세스할 수 있습니다.
- 작업이 속한 문서의 이름입니다.
- 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 문서 생성에 사용되는 것입니다.
예를 들어 다음 스키마 변환기는 소수점 형식 decimal
을 format
다음 대신 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
패키지를 통해 앱의 엔드포인트에 대한 정보를 생성하기 위한 기본 제공 지원을 제공합니다. 시각적 UI를 통해 생성된 OpenAPI 정의를 노출하려면 타사 패키지가 필요합니다. 컨트롤러 기반 API에서 OpenAPI 지원에 대한 자세한 내용은 이 문서의 .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 UI 도구를 사용할 수 있습니다.
- WithName: 엔드포인트의 IEndpointNameMetadata는 링크 생성에 사용되며 지정된 엔드포인트의 OpenAPI 사양에서 작업 ID로 처리됩니다.
WithOpenApi
는 이 문서 뒷부분에 설명되어 있습니다.
Microsoft.AspNetCore.OpenApi
NuGet 패키지
ASP.NET Core는 엔드포인트에 대한 OpenAPI 사양과 상호 작용하는 Microsoft.AspNetCore.OpenApi
패키지를 제공합니다. 이 패키지는 Microsoft.AspNetCore.OpenApi
패키지에 정의된 OpenAPI 모델과 최소 API에 정의된 엔드포인트 간의 링크 역할을 합니다. 이 패키지는 엔드포인트의 매개 변수, 응답 및 메타데이터를 검사하여 엔드포인트를 설명하는 데 사용되는 OpenAPI 주석 형식을 생성하는 API를 제공합니다.
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>
Microsoft.AspNetCore.OpenApi
, Swashbuckle.AspNetCore
와 함께 Swashbuckle.AspNetCore
를 사용할 때 6.4.0 이상을 사용해야 합니다. WithOpenApi
호출에서 복사 생성자를 활용하려면 Microsoft.OpenApi
1.4.3 이상을 사용해야 합니다.
WithOpenApi
를 통해 엔드포인트에 OpenAPI 주석 추가
엔드포인트에서 WithOpenApi
를 호출하면 엔드포인트의 메타데이터가 추가됩니다. 이 메타데이터는 다음과 같습니다.
- Swashbuckle.AspNetCore와 같은 타사 패키지에서 사용합니다.
- Swagger 사용자 인터페이스 또는 API를 정의하기 위해 생성된 YAML 또는 JSON에 표시됩니다.
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();
WithOpenApi
에서 OpenAPI 주석 수정
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에 작업 ID 추가
작업 ID는 OpenAPI에서 지정된 엔드포인트를 고유하게 식별하는 데 사용됩니다. WithName
확장 메서드를 사용하여 메서드에 사용되는 작업 ID를 설정할 수 있습니다.
app.MapGet("/todoitems2", async (TodoDb db) =>
await db.Todos.ToListAsync())
.WithName("GetToDoItems");
또는 OpenAPI 주석에서 직접 OperationId
속성을 설정할 수 있습니다.
app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
.WithOpenApi(operation => new(operation)
{
OperationId = "GetTodos"
});
OpenAPI 설명에 태그 추가
OpenAPI는 태그 개체 를 사용하여 작업을 분류할 수 있도록 지원합니다. 이러한 태그는 일반적으로 Swagger UI에서 작업을 그룹화하는 데 사용됩니다. 이러한 태그는 원하는 태그를 사용하여 엔드포인트에서 WithTags 확장 메서드를 호출하여 작업에 추가할 수 있습니다.
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.ToListAsync())
.WithTags("TodoGroup");
또는 WithOpenApi
확장 메서드를 통해 OpenAPI 주석에서 OpenApiTags
목록을 설정할 수 있습니다.
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를 사용되지 않는 것으로 표시
엔드포인트를 사용되지 않는 것으로 표시하려면 OpenAPI 주석에서 Deprecated
속성을 설정합니다.
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
를 사용하면 엔드포인트에 대한 응답 형식 메타데이터가 자동으로 포함됩니다. 예를 들어, 다음 코드는 application/json
콘텐츠 형식의 200
상태 코드 아래에 응답으로 엔드포인트에 자동으로 주석을 추가합니다.
app.MapGet("/todos", async (TodoDb db) =>
{
var todos = await db.Todos.ToListAsync());
return TypedResults.Ok(todos);
});
ProblemDetails
에 대한 응답 설정
ProblemDetails 응답, ProducesProblem 확장 메서드 ProducesValidationProblem를 반환하거나 TypedResults.Problem
엔드포인트의 메타데이터에 적절한 주석을 추가하는 데 사용할 수 있는 엔드포인트에 대한 응답 유형을 설정하는 경우 ProducesProblem
.NET 8 이하의 경로 그룹에는 ProducesValidationProblem
확장 메서드와 확장 메서드를 사용할 수 없습니다.
위의 전략 중 하나에서 제공하는 명시적 주석이 없는 경우, 프레임워크는 응답의 서명을 검사하여 기본 응답 유형을 확인하려고 시도합니다. 이 기본 응답은 OpenAPI 정의의 200
상태 코드 아래에 채워집니다.
여러 응답 유형
엔드포인트가 다양한 시나리오에서 다른 응답 형식을 반환할 수 있는 경우 다음과 같은 방법으로 메타데이터를 제공할 수 있습니다.
다음 예제와 같이
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에서 사용하는 입력에 주석을 추가하는 것도 지원합니다. 이러한 입력은 다음 두 가지 범주로 분류됩니다.
- 경로, 쿼리 문자열, 헤더 또는 쿠키에 표시되는 매개 변수
- 요청 본문의 일부로 전송되는 데이터
프레임워크는 경로 처리기의 서명에 따라 경로, 쿼리 및 헤더 문자열의 요청 매개 변수 형식을 자동으로 유추합니다.
요청 본문으로 전송되는 입력 유형을 정의하려면 Accepts
확장 메서드를 사용하여 요청 처리기에서 예상하는 개체 형식 및 콘텐츠 형식을 정의하여 속성을 구성합니다. 다음 예제에서 엔드포인트는 요청 본문에 예상되는 콘텐츠 형식이 application/xml
인 Todo
개체를 허용합니다.
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
콘텐츠 형식으로 설명됩니다. - 요청 본문은 nullable이거나
AllowEmpty
속성이FromBody
특성에 설정된 경우 선택 사항으로 처리됩니다.
API 버전 관리 지원
최소 API는 Asp.Versioning.Http 패키지를 통해 API 버전 관리를 지원합니다. 최소 API를 사용하여 버전 관리를 구성하는 예제는 API 버전 관리 리포지토리에서 찾을 수 있습니다.
GitHub의 ASP.NET Core OpenAPI 소스 코드
추가 리소스
최소 API 앱은 Swashbuckle을 사용하는 경로 처리기에 대한 OpenAPI 사양을 설명할 수 있습니다.
컨트롤러 기반 API에서 OpenAPI 지원에 대한 자세한 내용은 이 문서의 .NET 9 버전을 참조 하세요.
다음 코드는 OpenAPI를 지원하는 일반적인 ASP.NET Core 앱입니다.
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에 작업 ID 추가
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