중요한 통지 주요 버전간에 업그레이드하는 경우! |
---|
* 4.x에서 5.x로 업그레이드하는 경우 몇 가지 중단 변경 사항이 있습니다. 자세한 내용은 릴리스 노트를 참조하십시오 * 먼저 3.x에서 4.x로 점프한다면 드래곤도 있습니다. 여기에서 해당 릴리스 노트를 참조하십시오 |
ASP.NET Core와 함께 구축 된 API 용 Swagger Tooling. 경로, 컨트롤러 및 모델에서 직접 탐색 및 테스트 작업을 포함하여 UI를 포함한 아름다운 API 문서를 생성하십시오.
Swashbuckle은 Swagger 2.0 및 OpenApi 3.0 발전기 외에도 생성 된 Swagger JSON으로 구동되는 멋진 Swagger-UI의 내장 버전을 제공합니다. 즉, 항상 최신 코드와 동기화되는 생활 문서로 API를 보완 할 수 있습니다. 무엇보다도 최소한의 코딩 및 유지 보수가 필요하므로 멋진 API를 구축하는 데 집중할 수 있습니다.
그리고 그게 전부가 아닙니다 ...
Swagger에서 자신을 설명 할 수있는 API가 있으면 광범위한 인기있는 플랫폼을 대상으로 할 수있는 클라이언트 생성기를 포함하여 Swagger 기반 도구의 보물 상자를 열었습니다. 자세한 내용은 Swagger-Codegen을 참조하십시오.
swashbuckle 버전 | asp.net 코어 | Swagger / Openapi 사양. | Swagger-ui | Redoc UI |
---|---|---|---|---|
CI | > = 2.0.0 | 2.0, 3.0 | 5.xx | 2.xx |
6.9.0 | > = 2.0.0 | 2.0, 3.0 | 5.17.14 | 2.1.5 |
5.6.3 | > = 2.0.0 | 2.0, 3.0 | 3.32.5 | 2.0.0-RC.40 |
4.0.0 | > = 2.0.0, <3.0.0 | 2.0 | 3.19.5 | 1.22.2 |
3.0.0 | > = 1.0.4, <3.0.0 | 2.0 | 3.17.1 | 1.20.0 |
2.5.0 | > = 1.0.4, <3.0.0 | 2.0 | 3.16.0 | 1.20.0 |
표준 NUGET 패키지를 ASP.NET Core 응용 프로그램에 설치하십시오.
Package Manager : Install-Package Swashbuckle.AspNetCore CLI : dotnet add package Swashbuckle.AspNetCore
Startup.cs
의 ConfigureServices
메소드에서 하나 이상의 Swagger 문서를 정의하여 Swagger Generator를 등록하십시오.
Microsoft.openapi.Models 사용;
services.addmvc (); services.addswaggergen (c => {c.waggerdoc ( "v1", new openapiinfo {title = "my api", version = "v1"});});
API 동작 및 매개 변수가 명시 적 "HTTP"및 "Bins"바인딩으로 장식되어 있는지 확인하십시오.
[httppost] public void createproduct ([Body] 제품 제품) ...
[httpget] public ienumerable <Product> searchProducts ([Query] 문자열 키워드) ...
참고 : 명시 적 매개 변수 바인딩을 생략하면 생성기는 기본적으로 "쿼리"매개 변수로 설명합니다.
Configure
메소드에서 생성 된 Swagger를 다음 방법 중 하나로 JSON Endpoint로 노출시켜야합니다.
app.mapendPoints (endPoints => {// ... endPoints.mapSwagger ();});
app.useswagger ();
이 시점에서 "/swagger/v1/swagger.json"에서 생성 된 Swagger JSON을 볼 수 있습니다.
미들웨어를 삽입하십시오
엔드 포인트 기반 라우팅을 사용하는 경우 엔드 포인트를 추가하십시오.
선택적으로, 대화 형 문서를 노출시키려면 Swagger-UI 미들웨어를 삽입하여 Swagger JSON Endpoint를 지정하여 전원을 공급하십시오.
app.useswaggerui (c => {c.waggerendpoint ( "v1/swagger.json", "my api v1");});
이제 응용 프로그램을 다시 시작하고 "/swagger"에서 자동 생성 된 대화식 문서를 확인할 수 있습니다.
5.0.0
이전 버전에서 SwashBuckle은 NewTonsoft Serializer의 동작에 따라 Schema (API에 노출 된 데이터 유형에 대한 설명)를 생성합니다. 당시 ASP.NET Core와 함께 배송 된 직렬 라이저이기 때문에 이것은 의미가있었습니다. 그러나 버전 3.0.0
이므로 ASP.NET Core는 새로운 Serializer System.text.json (STJ)을 기본으로 소개하고 NewTonsoft를 계속 사용하려면 별도의 패키지를 설치하고 명시 적으로 설치해야합니다. 옵트 인. Swashbuckle에서 5.0.0
넘어 비슷한 패턴이 사용됩니다. 즉, 상자 외부 Swashbuckle은 STJ 시리얼 라이저를 사용하고 동작에 따라 Schema를 생성한다고 가정합니다. NewTonsoft를 사용하는 경우 별도의 Swashbuckle 패키지를 설치하고 명시 적으로 옵트 인해야합니다. 사용중인 ASP.NET Core 버전에 관계없이 필요한 단계입니다 .
요약 ...
System.text.json (STJ)을 사용하는 경우 위에서 설명한 설정이 충분하며 STJ 옵션/속성은 Swagger Generator에서 자동으로 영예됩니다.
NewTonsoft를 사용하는 경우 별도의 패키지와 명시 적으로 옵트 인을 설치하여 NewTonsoft 설정/속성이 Swagger Generator에서 자동으로 영예를 얻도록해야합니다.
Package Manager : Install-Package Swashbuckle.AspNetCore.Newtonsoft CLI : dotnet add package Swashbuckle.AspNetCore.Newtonsoft
services.addmvc (); services.addswaggergen (c => {c.waggerdoc ( "v1", new openapiinfo {title = "my api", version = "v1"}); adddswaggergennewtonsoftupport (); // addswaggergen () 이후에 명시 적 옵트 인 - 배치해야합니다.
Swashbuckle은 ASP.NET Core와 함께 제공되는 API 메타 데이터 레이어 ApiExplorer
에 크게 의존합니다. AddMvc
헬퍼를 사용하여 MVC 스택을 부트 스트랩하는 경우 ApieXPlorer가 자동으로 등록되고 SB가 문제없이 작동합니다. 그러나 더 짝을 이루는 MVC 스택에 AddMvcCore
사용하는 경우 ApieXplorer 서비스를 명시 적으로 추가해야합니다.
services.addmvccore (). addapiexplorer ();
또한 기존 라우팅 (속성 라우팅과 반대로)을 사용하는 경우, 기존 라우팅을 사용하는 컨트롤러 및 컨트롤러의 모든 조치는 ApiexPlorer에 표시되지 않으므로 Swashbuckle이 해당 컨트롤러를 찾고 Swagger를 생성 할 수 없음을 의미합니다. 그들로부터의 운영. 예를 들어:
app.usemvc (lours => {// swaggergen 은이 기술을 통해 라우팅되는 컨트롤러를 찾지 못합니다. lours.maproute ( "default", "{controller = home}/{action = index}/{id?}"). ;});
Swagger 문서에 표시하려는 모든 컨트롤러에 속성 라우팅을 사용해야 합니다 .
[Route ( "example")] 공개 클래스 exameplecontroller : 컨트롤러 {[httpget ( "")] public iCectionResult dostuff () { / ** /}}
자세한 내용은 라우팅 문서를 참조하십시오.
Swashbuckle은 귀하의 요구에 따라 함께 또는 개별적으로 사용할 수있는 여러 구성 요소로 구성됩니다. 핵심에는 Swagger Generator, Middleware가 JSON 엔드 포인트로 노출 및 Swagger-UI의 패키지 버전이 있습니다. 이 3 개의 패키지는 Swashbuckle.AspNetCore
"Metapackage"로 설치할 수 있으며 코드에서 자동으로 생성되는 아름다운 API 문서를 제공하기 위해 완벽하게 작동합니다 (시작 참조).
또한 필요에 따라 선택적으로 설치하고 구성 할 수있는 애드온 패키지 (CLI 도구, 대체 UI 등)가 있습니다.
패키지 | 설명 |
---|---|
swashbuckle.aspnetcore.swagger | Swagger JSON 엔드 포인트를 노출시킵니다. ISwaggerProvider 의 구현이 DI 컨테이너에 등록 될 것으로 예상되며, 이는 OpenAPIDocument(s) 를 검색하여 직렬화 된 JSON으로 노출됩니다. |
swashbuckle.aspnetcore.waggergen | 위 구성 요소에서 사용할 수있는 ISwaggerProvider 의 구현을 주입합니다. 이 특정 구현은 경로, 컨트롤러 및 모델에서 OpenApiDocument(s) 생성합니다. |
swashbuckle.aspnetcore.waggerui | Swagger-UI의 임베디드 버전을 노출시킵니다. Swagger JSON을 얻을 수있는 API 엔드 포인트를 지정하고이를 사용하여 API의 대화식 문서에 전원을 공급합니다. |
패키지 | 설명 |
---|---|
swashbuckle.aspnetcore.annotations | 생성 된 Swagger를 풍부하게하기 위해 컨트롤러, 작업 및 모델에 적용 할 수있는 일련의 사용자 정의 속성이 포함되어 있습니다. |
swashbuckle.aspnetcore.cli | 스타트 업 어셈블리에서 직접 Swagger를 검색하고 파일 쓰기를위한 명령 줄 인터페이스를 제공합니다. |
swashbuckle.aspnetcore.redoc | Redoc UI의 임베디드 버전 (Swagger-UI 대안)을 노출시킵니다. |
이 패키지는 오픈 소스 커뮤니티에서 제공합니다.
패키지 | 설명 |
---|---|
swashbuckle.aspnetcore.filters | 추가 문서, 예를 들어 요청 및 응답 예제, 인증 정보 등을 추가하는 유용한 Swashbuckle 필터 등에 대한 자세한 내용은 ReadMe를 참조하십시오. |
unchase.washbuckle.aspnetcore.extensions | 추가 문서를 추가하는 유용한 확장 (필터), 예를 들어 받아 들여지지 않은 역할에 대한 Pathitems, 클라이언트 코드 생성을위한 열거 수정 등. 자세한 내용은 readme를 참조하십시오. |
미세 요소 .washbuckle.fluentValidation | 생성 된 Swagger Schemas를 보강하기 위해 ComponentModel 속성 대신 fluentValidation 규칙을 사용하십시오. |
mmlib.waggerforocelot | Ocelot API 게이트웨이에서 직접 마이크로 서비스에 대한 문서를 집계하십시오 |
위에서 설명한 단계를 통해 최소한의 설정으로 실행할 수 있습니다. 그러나 Swashbuckle은 적합한대로 사용자 정의 할 수있는 많은 유연성을 제공합니다. 전체 옵션 목록은 아래 표를 확인하십시오.
swashbuckle.aspnetcore.swagger
Swagger JSON 엔드 포인트의 경로를 변경하십시오
요청 컨텍스트로 Swagger를 수정하십시오
2.0 형식으로 Swagger JSON을 직렬화하십시오
가상 디렉토리 및 리버스 프록시로 작업합니다
OpenAPI 문서가 직렬화되는 방식을 사용자 정의합니다
swashbuckle.aspnetcore.waggergen
명시 적 Operations를 할당합니다
작업 응답을 나열합니다
플래그 필수 매개 변수 및 스키마 속성
양식 및 파일 업로드를 처리합니다
파일 다운로드를 처리합니다
XML 주석의 설명을 포함하십시오
글로벌 API 메타 데이터를 제공하십시오
여러 Swagger 문서를 생성합니다
쓸모없는 작업 및/또는 스키마 속성을 생략하십시오
임의의 작업을 생략하십시오
작동 태그 사용자 정의 (예 : UI 그룹화용)
조작 정렬 순서 변경 (예 : UI 정렬 용)
스키마 ID를 사용자 정의합니다
특정 유형의 스키마를 무시하십시오
작동, 스키마 및 문서 필터로 생성기를 확장하십시오
보안 정의 및 요구 사항을 추가하십시오
Bearer Auth에 대한 보안 정의 및 요구 사항을 추가하십시오
상속 및 다형성
swashbuckle.aspnetcore.waggerui
UI 로의 상대 경로를 변경하십시오
문서 제목을 변경하십시오
CSS 또는 JS 경로를 변경하십시오
여러 Swagger 문서를 나열하십시오
Swagger-UI 매개 변수를 적용하십시오
사용자 정의 자바 스크립트를 주입합니다
사용자 정의 CSS를 주입하십시오
Index.html을 사용자 정의하십시오
OAUTH2.0 흐름을 활성화하십시오
클라이언트 측 요청 및 응답 인터셉터를 사용하십시오
swashbuckle.aspnetcore.annotations
주석을 설치하고 활성화하십시오
조작 메타 데이터를 강화하십시오
반응 메타 데이터를 풍부하게하십시오
매개 변수 메타 데이터를 강화합니다
요청 신체 메타 데이터를 강화하십시오
스키마 메타 데이터를 강화하십시오
스키마 필터를 특정 유형에 적용하십시오
태그 메타 데이터를 추가하십시오
swashbuckle.aspnetcore.cli
스타트 업 어셈블리에서 직접 Swagger를 검색하십시오
사용자 정의 호스트 구성과 함께 CLI 도구를 사용하십시오
swashbuckle.aspnetcore.redoc
UI 로의 상대 경로를 변경하십시오
문서 제목을 변경하십시오
개도 매개 변수를 적용하십시오
사용자 정의 CSS를 주입하십시오
Index.html을 사용자 정의하십시오
기본적으로 Swagger JSON은 다음 경로에 노출됩니다. 필요한 경우 Swagger Middleware를 활성화 할 때이를 변경할 수 있습니다. 사용자 정의 경로에는 {documentName}
매개 변수가 포함되어야합니다.
app.useswagger (c => {c.routetemplate = "api-docs/{documentname} /wagger.json";})
참고 : Swaggerui Middleware를 사용하는 경우 새로운 엔드 포인트를 반영하기 위해 구성을 업데이트해야합니다.
app.useswaggerui (c => {c.waggerendpoint ( "/api-docs/v1/swagger.json", "my api v1");})
참고 : UI 자체를 사용할 수있는 상대 경로를 업데이트 해야하는 경우 UI에 대한 변경 상대 경로에서 발견 된 지침을 따라야합니다.
현재 요청에 따라 일부 Swagger 메타 데이터를 설정 해야하는 경우 문서를 직렬화하기 전에 실행 된 필터를 구성 할 수 있습니다.
app.useswagger (c => {c.preserializefilters.add ((swagger, httpreq) => {swagger.servers = new List <OpenApiserVer> {new OpenApiserVer {url = $ "{httpreq.scheme} : // {httpreq. host.value} "}};});});
OpenApiDocument
와 현재 HttpRequest
둘 다 필터로 전달됩니다. 이것은 많은 유연성을 제공합니다. 예를 들어, "호스트"헤더를 기반으로 명시 적 API 서버를 추가하거나 (그림과 같이) 세션 정보 또는 인증 헤더를 검사하고 사용자 권한을 기반으로 문서에서 작업을 제거 할 수 있습니다.
기본적으로 Swashbuckle은 공식적으로 OpenAPI 사양이라고하는 사양의 버전 3.0에서 Swagger JSON을 생성하고 노출시킵니다. 그러나 Backwards 호환성을 지원하기 위해 다음 옵션을 사용하여 2.0 형식으로 계속 노출하도록 선택할 수 있습니다.
app.useswagger (c => {c.serializeasv2 = true;});
가상 디렉토리 및 리버스 프록시는 특히 앱이 Host
헤더 및 현재 요청의 기타 정보를 기반으로 절대 URL을 반환하는 경우 링크 및 리디렉션을 생성하는 응용 프로그램에 문제를 일으킬 수 있습니다. 이러한 문제를 피하기 위해 Swashbuckle은 가능한 경우 상대 URL을 사용하고 Swaggerui 및 Redoc Middleware를 구성 할 때 사용을 장려합니다.
예를 들어, Swaggerui Middleware를 연결하려면 하나 이상의 OpenApi/Swagger 문서에 URL을 제공합니다. 클라이언트 측 응용 프로그램 인 Swagger-UI가 호출하여 API 메타 데이터를 검색하는 URL입니다. 이것이 가상 디렉토리 및 리버스 프록시 뒤에 작동하는지 확인하려면 Swagger-UI 자체의 RoutePrefix
와 비교하여이를 표현해야합니다.
app.useswaggerui (c => {c.routeprefix = "swagger"; c.waggerendpoint ( "v1/swagger.json", "my api v1");});
참고 : 이전 버전의 문서에서는이를 루트 관련 링크 (예 : /swagger/v1/swagger.json
)로 표시했을 수 있습니다. 앱이 IIS 가상 디렉토리에서 호스팅되거나 전달하기 전에 요청 경로를 다듬는 프록시 뒤에 호스팅되는 경우에는 작동하지 않습니다. 위에 표시된 페이지 관계 구문으로 전환하면 모든 경우에 작동해야합니다.
기본적으로 SwashBuckle은 OpenAPI 문서 개체의 직렬화 메소드를 사용하여 OpenAPI 문서를 직렬화합니다. 맞춤형 직렬화가 필요한 경우 ISwaggerDocumentSerializer
인터페이스를 구현하는 사용자 정의 문서 직렬 라이저를 만들 수 있습니다. ConfigureSwagger()
사용하여 서비스 컬렉션의 SwaggerOptions
에서 설정할 수 있습니다.
메모
OpenAPI 사양 파일을 생성하기 위해 명령 줄 도구를 사용하려는 경우 ConfigureSwagger()
사용하여 서비스 컬렉션에서 수행해야합니다.
services.configureswagger (옵션 => {옵션 .setCustomDocumentsErializer <CustommentDocumentsErializer> ();})
명령 줄 도구를 사용하지 않으면 응용 프로그램 호스트에서도 수행 할 수도 있습니다.
app.useswagger (옵션 => {Options.SetCustomDocumentsEerializer <CustommentDocumentsErializer> ();})
Swagger에서는 작업에 operationId
가 할당 될 수 있습니다. 이 ID는 API에 설명 된 모든 작업 중에서 고유해야합니다. 도구 및 라이브러리 (예 : 클라이언트 생성기)는 OperationID를 사용하여 작업을 고유하게 식별 할 수 있으므로 일반적인 프로그래밍 명명 규칙을 따르는 것이 좋습니다.
이러한 요구 사항과 일치하는 ID를 자동 생성하는 반면 클라이언트 라이브러리에서 의미있는 이름을 제공하는 것은 사소한 작업이므로 SwashBuckle은 기본적으로 operationId
를 생략합니다. 그러나 필요한 경우 개별 경로를 장식하거나 사용자 정의 전략을 제공하여 operationIds
할당 할 수 있습니다.
옵션 1) Name
속성으로 경로를 장식하십시오
[httpget ( "{id}", name = "getProductById")] public iCectionResult get (int id) // operatId = "getProductById"
옵션 2) 사용자 정의 전략을 제공합니다
// startup.csservices.addswaggergen (c => {... // 메소드 이름을 OperatId C.CustomOperationIds로 사용합니다 (apidesc => {return apidesc.trygetMethodinfo (out methodinfo methodinfo)? methodinfo.name : null;});}. ) // productsController.cs [httpget ( "{id}")] public iCectionResult getProductById (int id) // operatId = "getProductById"
참고 : API 저자는 두 가지 접근 방식으로 모든 작업에서 operationIds
의 독창성을 보장 할 책임이 있습니다.
기본적으로 Swashbuckle은 각 작업에 대해 "200"응답을 생성합니다. 작업이 응답 DTO를 반환하면 응답 본문에 대한 스키마를 생성하는 데 사용됩니다. 예를 들어 ...
[httppost ( "{id}")] 공개 제품 getbyid (int id)
다음과 같은 응답 메타 데이터를 생성합니다.
responses: { 200: { description: "OK", content: { "application/json": { schema: { $ref: "#/components/schemas/Product" } } } } }
다른 상태 코드 및/또는 추가 응답을 지정해야하거나 응답 DTO 대신 IActionResult
반환 해야하는 경우 ASP.NET Core와 함께 제공되는 ProducesResponseTypeAttribute
와의 응답을 명시 적으로 설명 할 수 있습니다. 예를 들어 ...
[httppost ( "{id}")] [producesResponseType (typeof (uppubled), 200)] [produceSpronsEtype (typeof (idictionary <string, string>), 400) [ProducesResponsEtype (500)] public IctionResult getById (int id)
다음과 같은 응답 메타 데이터를 생성합니다.
responses: { 200: { description: "OK", content: { "application/json": { schema: { $ref: "#/components/schemas/Product" } } } }, 400: { description: "Bad Request", content: { "application/json": { schema: { type: "object", additionalProperties: { type: "string" } } } } }, 500: { description: "Internal Server Error", content: {} } }
Swagger 문서에서 요청에 필요한 매개 변수 및 스키마 속성을 플래그 할 수 있습니다. 매개 변수 (최상위 또는 속성 기반)가 BindRequiredAttribute
또는 RequiredAttribute
로 장식 된 경우 SwashBuckle은 자동으로 생성 된 Swagger에서 "필수"매개 변수로 표시됩니다.
// productsController.cspublic iActionResult 검색 ([Query, bindRequired] 문자열 키워드, [fromQuery] pagingparams pagingparams) {if (! modelstate.isvalid) badrequest (modelstate); ...} // spoolpparams.cspublic class pagingparams {필요합니다. ] public int pageno {get; 세트; } public int pagesize {get; 세트; }}
Swashbuckle은 매개 변수 외에도 요청 본문에 바인딩되는 모델에 사용될 때 RequiredAttribute
존중합니다. 이 경우, 장식 된 특성은 신체에서 "필수"속성으로 표시됩니다.
// productsController.cspublic iactionResult 만들기 ([Body] Product Products) {if (! modelstate.isvalid) return badrequest (modelstate); ...} // uppubled.cspublic class product {[필수] public String name {get; 세트; } 공개 문자열 설명 {get; 세트; }}
이 컨트롤러는 두 가지 양식 필드 값과 동일한 형식의 파일 업로드를 허용합니다.
[httppost] public void uploadfile ([from form] 문자열 설명, [form] dateTime clientDate, iformfile 파일)
중요 참고 : ASP.NET Core Docs에 따라 바인딩 소스가 유형에서 자동으로 추론되므로
IFormFile
매개 변수를[FromForm]
속성으로 장식해서는 안됩니다. 실제로, 추론 된 값은BindingSource.FormFile
이며 속성을 적용하면 대신BindingSource.Form
으로 설정되어 Asp.net Core와 함께 제공되고 SwashBuckle에 의해 크게 의존하는 메타 데이터 구성 요소 인ApiExplorer
망칩니다. 여기서 특별한 문제 중 하나는 Swaggerui가 매개 변수를 파일로 취급하지 않으므로이 속성을 잘못 포함하는 경우 파일 업로드 버튼을 표시하지 않는다는 것입니다.
ApiExplorer
(Swashbuckle이 구축 된 ASP.NET Core Metadata 구성 요소)는 기본적으로 FileResult
유형을 표면 하지 않으므로 ProducesResponseType
속성 (또는 .NET 5 이상에서 .NET 5 이상에서 Produces
)과 명시 적으로 알려야합니다.
[httpget ( "{filename}")] [CroferesResponsEtype (typeof (filestreamresult), statescodes.status200ok, "image/jpeg")] public filestreamresult getfile (String filename)
인간 친화적 인 설명을 통해 생성 된 문서를 향상시키기 위해 XML 주석으로 컨트롤러 동작 및 모델을 주석을 달고 SwashBuckle을 구성하여 해당 주석을 출력 된 Swagger JSON에 포함시킬 수 있습니다.
프로젝트의 속성 대화 상자를 열고 "빌드"탭을 클릭하고 "XML 문서 파일"이 확인되었는지 확인하거나 <csproj 프로젝트 파일의 <PropertyGroup>
섹션에 <GenerateDocumentationFile>true</GenerateDocumentationFile>
element를 추가하십시오. 이렇게하면 빌드 타임에 모든 XML 주석이 포함 된 파일이 생성됩니다.
이 시점에서 XML 주석으로 주석이없는 클래스 또는 메소드는 빌드 경고를 유발합니다. 이를 억제하려면 경고 코드 "1591"을 속성 대화 상자에서 "경고 억제"필드에 입력하거나 .csproj 프로젝트 파일의 <PropertyGroup>
섹션에 <NoWarn>1591</NoWarn>
추가하십시오.
SwashBuckle 구성 파일에 XML 주석을 생성 된 Swagger JSON에 통합하도록 구성하십시오.
services.addswaggergen (c => {c.waggerdoc ( "v1", new openapiinfo {title = "my api -v1", version = "v1"}); c.includexmlcomments (astembly.getexecutingAssembly ()); // c.includexmlcomments (typeof (myController) .Assembly));}
요약, 비고, 매개 변수 및 응답 태그로 행동을 주석을 달았습니다.
/// <summary> /// 고유 한 ID /// </summary> /// <tarking> awesomeness! </warting> // <param name = "id"example = "123"으로 특정 제품을 검색합니다. > 제품 ID </param> /// <응답 코드 = "200"> 제품 검색 </respone> /// <응답 코드 = "404"> 제품을 찾지 못함 </respone> // <응답 코드 = "500"> 죄송합니다! 지금 당장 제품을 조회 할 수 없습니다 </respons> [httpget ( "{id}")] [crofertesResponsetype (typeof (product), 200)] [producesResponsEtype (404)] [ProducesResponsEtype (500)] 공개 제품 getByid (int ID)
요약 및 예제 태그로 유형에 주석을 달 수도 있습니다.
공개 클래스 제품 {/// <summary> /// 제품 이름 /// </summary> /// <emasial> 남자 농구화 </example> 공개 문자열 이름 {get; 세트; } /// <summary> /// stock에 남아있는 수량 /// </summary> /// <emasion> 10 </example> public int availablestock {get; 세트; } /// <summary> /// 제품은 /// </summary> /// <emasion> [ "small", "medium", "large"</example> 공개 목록 < 문자열> 크기 {get; 세트; }}
프로젝트를 재구성하여 XML 주석 파일을 업데이트하고 Swagger JSON Endpoint로 이동하십시오. 설명이 해당 Swagger 필드에 어떻게 매핑되는지 확인하십시오.
참고 : API 모델과 속성에 요약 태그에 속성에 주석을 달면 Swagger 스키마 설명을 제공 할 수도 있습니다. 여러 XML 댓글 파일 (예 : 컨트롤러 및 모델에 대한 별도 라이브러리)이있는 경우 IncludexmlComments 메소드를 여러 번 호출 할 수 있으며 모두 출력 된 Swagger JSON으로 병합됩니다.
Swashbuckle이 귀하를 위해 생성하는 "Pathitems", "Operations"및 "Responses"외에도 Swagger는 글로벌 메타 데이터도 지원합니다 (https://swagger.io/specification/#oasobject 참조). 예를 들어, API, 서비스 약관 또는 연락처 및 라이센스 정보에 대한 전체 설명을 제공 할 수 있습니다.
C.waggerDoc ( "v1", New OpenApiInfo {title = "my api -v1", version = "v1", description = "샘플 API에서 데모 스파쉬 버클", orverservice = new URI ( "http://tempuri.org /order "), contact = new OpenApicOntact {name ="joe developer ", email ="[email protected] "}, 라이센스 = new OpenApilicense {name ="apache 2.0 ", url = new URI ("https : //www.apache.org/licenses/license-2.0.html ")});
팁 : Intellisense를 사용하여 다른 분야를 사용할 수있는 다른 분야를 확인하십시오.
위에서 설명한 설정을 사용하면 생성기에는 단일 Swagger 문서에 모든 API 작업이 포함됩니다. 그러나 필요한 경우 여러 문서를 만들 수 있습니다. 예를 들어, 각 버전의 API에 대해 별도의 문서를 원할 수 있습니다. 이렇게하려면 Startup.cs
에서 여러 Swagger 문서를 정의하여 시작하십시오.
services.addswaggergen (c => {c.waggerdoc ( "v1", new openapiinfo {title = "my api -v1", version = "v1"}); c.waggerdoc ( "v2", new openapiinfo {title = " 내 API -v2 ", version ="v2 "});})
SwaggerDoc에 대한 첫 번째 주장을 기록하십시오. 문서를 독특하게 식별하는 Uri 친화적 인 이름이어야합니다. 그 후에 해당 Swagger JSON을 요청하기위한 길을 보충하는 데 사용됩니다. 예를 들어, 기본 라우팅을 사용하면 위의 문서는 "/wagger/v1/swagger.json"및 "/wagger/v2/swagger.json"에서 사용할 수 있습니다.
다음으로, 각 문서에 포함 할 조치에 swashbuckle에 알릴 필요가 있습니다. 이를 사용자 정의 할 수 있지만 (아래 참조) 기본적으로 생성기는 Asp.net Core와 함께 제공되는 내장 메타 데이터 레이어의 일부인 ApiDescription.GroupName
속성을 사용하여 이러한 구별을합니다. 개별 행동을 꾸미거나 응용 프로그램 과이드 컨벤션을 적용하여이를 설정할 수 있습니다.
특정 Swagger 문서에 작업을 포함하려면 ApiExplorerSettingsAttribute
로 장식하고 GroupName
해당 문서 이름 (CASE 민감성)으로 설정하십시오.
[httppost] [apiexplorersettings (groupname = "v2")] public void post ([body] 제품 제품)
모든 액션을 장식하는 대신 컨벤션별로 그룹화하려면 사용자 정의 컨트롤러 또는 액션 컨벤션을 적용 할 수 있습니다. 예를 들어, 다음 컨벤션을 사용하여 컨트롤러 네임 스페이스를 기반으로 문서에 작업을 할당 할 수 있습니다.
// apiexplorergroupperversionconvention.cspublic class apiexplorergroupperversionconvention : icontrollermodelconvention {public void apply (controllerModel controller) {var controllernamespace = controller.controllertype.namespace; // "컨트롤러 .v1"var apiversion = 컨트롤러 이름표 .split ( '.'). last (). tolower (); 컨트롤러.apiexplorer.groupname = apiversion;}} // startup.cspublic void configureservices (iservecececection services) { services.addmvc (c => c.conventions.add (new apiexplorergroupperversionvention ()); ...}
주어진 Swagger 문서에 대한 조치를 선택할 때 Generator는 프레임 워크에 의해 표면 된 모든 ApiDescription
에 대한 DocInclusionPredicate
호출합니다. 기본 구현은 ApiDescription.GroupName
검사하고 값이 요청 된 문서 이름과 널 또는 동일 한 경우 true를 반환합니다. 그러나 사용자 정의 포함 술어를 제공 할 수도 있습니다. 예를 들어, 속성 기반 접근 방식을 사용하여 API 버전을 구현하는 경우 (예 : Microsoft.aspnetCore.mvc.versioning) 버전화 속성을 대신 활용하는 사용자 정의 술어를 구성 할 수 있습니다.
c.docinclusionPredicate ((DocName, apidesc) => {if (! apidesc.rygetMethodinfo (out methodinfo methodinfo)) return false; var versions = methodinfo.declaringtype .getCustomAttributes (true) .oftype <apiversionattription (attrectmany). > attr.versions); return 버전.
SwaggerUI
Middleware를 사용하는 경우 노출하려는 추가 Swagger 엔드 포인트를 지정해야합니다. 자세한 내용은 여러 Swagger 문서 목록을 참조하십시오.
Swagger 사양에는 작업이 더 이상 사용되지 않았으며 사용을 자제해야한다는 것을 나타내는 deprecated
플래그가 포함되어 있습니다. Swagger Generator는 해당 동작이 ObsoleteAttribute
로 장식되면이 플래그를 자동으로 설정합니다. 그러나 플래그를 설정하는 대신 생성기가 쓸모없는 작업을 모두 무시하도록 구성 할 수 있습니다.
services.addswaggergen (c => {... c.ignoreobsoleteactions ();};
비슷한 접근법을 사용하여 Swagger 출력에서 스키마로부터 구식 특성을 생략 할 수 있습니다. 즉, JSON Schemas를 생성 할 때 다음과 같은 특성을 생략하도록 ObsoleteAttribute
을 생략하도록 Swashbuckle을 구성하고 Swashbuckle을 구성 할 수 있습니다.
services.addswaggergen (c => {... C. ingoreobsoleteproperties ();};
개별 행동을 장식하거나 응용 프로그램 와이드 컨벤션을 적용하여 Swagger 출력에서 작업을 생략 할 수 있습니다.
특정 조치를 생략하려면 ApiExplorerSettingsAttribute
로 장식하고 IgnoreApi
깃발을 설정하십시오.
[httpget ( "{id}")] [apiexplorersettings (ingoreapi = true)] 공개 제품 getbyid (int id)
개별적으로 장식하는 대신 컨벤션별로 행동을 생략하려면 사용자 정의 행동 컨벤션을 적용 할 수 있습니다. 예를 들어, 다음 컨벤션을 사용하여 문서화 작업 만 문서화 할 수 있습니다.
// apiexplorergetsonlyconvention.cspublic class apiexplorergetsonlyconvention : iCectionModelConvention {public void apply (action.apiexplorer.isvisible = action.oftributes.oftype <httpgettattific> () 정리 서비스) {services.addmvc (c => c.conventions.add (new apiexplorergetsonlyconvention ()); ...}
Swagger 사양을 사용하면 하나 이상의 "태그"를 작업에 할당 할 수 있습니다. Swagger 생성기는 컨트롤러 이름을 기본 태그로 할당합니다. 이 값이 그룹 운영 에이 값을 사용하므로 SwaggerUI
Middleware를 사용하는 경우에 유의해야합니다.
컨벤션별로 태그를 적용하는 함수를 제공하여 기본 태그를 무시할 수 있습니다. 예를 들어, 다음 구성은 http 메소드에 의해 UI의 그룹 작업에 태그가됩니다.
services.addswaggergen (c => {... c.tagactionsby (api => api.httpmethod);};
기본적으로 작업은 Swagger 사양의 경로 중심 중첩 구조로 그룹화되기 전에 할당 된 태그 (위 참조)에 의해 주문됩니다. 그러나 사용자 지정 정렬 전략으로 작업의 기본 순서를 변경할 수 있습니다.
services.addswaggergen (c => {... C.OrderActionSby ((apidesc) => $ "{apidesc.actionDescriptor.routevalues ["컨트롤러 "]} {apidesc.httpmethod}");};
참고 : 이것은 작업이 그룹화되어 Swagger 형식으로 변환되기 전에 정렬 순서를 지시합니다. 따라서 그룹 순서 (예 : Swagger "Pathitems") 및 Swagger 출력에서 그룹 내 작업 순서에 영향을 미칩니다.
Generator가 복잡한 매개 변수 또는 응답 유형을 만나면 해당 JSON 스키마를 생성하고 Global components/schemas
Dictionary에 추가하여 고유 ID로 작동 설명에서 참조하십시오. 예를 들어, Product
유형을 반환하는 작업이 있으면 생성 된 스키마가 다음과 같이 참조됩니다.
responses: { 200: { description: "OK", content: { "application/json": { schema: { $ref: "#/components/schemas/Product" } } } } }
그러나 이름이 동일한 이름이지만 다른 네임 스페이스 (예 : RequestModels.Product
& ResponseModels.Product
)로 여러 유형이 발생하면 SwashBuckle은 "충돌하는 스키미드"로 인해 예외가 발생합니다. 이 경우 이름을 추가로 평가하는 사용자 정의 ID 전략을 제공해야합니다.
services.addswaggergen (c => {... C.CustomSchemaids ((type) => type.fullname);};
중첩 유형을 지원하려면 #2703을 참조하십시오.
Box 외부에서 Swashbuckle은 귀하의 요청 및 응답 페이로드를 정확하게 설명하는 JSON 스키마를 생성하는 데 괜찮은 작업을 수행합니다. 그러나 API의 특정 유형에 대해 직렬화 동작을 사용자 정의하는 경우 도움이 필요할 수 있습니다.
예를 들어, JSON에서 쉼표로 구분 된 문자열로 표현하려는 여러 속성이있는 클래스가있을 수 있습니다. 이를 위해 사용자 정의 JsonConverter
구현할 수 있습니다. 이 경우 SwashBuckle은 변환기가 구현되는 방법을 알지 못하므로 유형을 정확하게 설명하는 스키마를 제공해야합니다.
// phonEnumber.cspublic 클래스 PhoneNumber {public String CountryCode {get; 세트; } public String areaCode {get; 세트; } public String SubscriberId {get; 세트; }} // startup.csservices.addswaggergen (c => {... c.maptype <phonenumb> (() => new OpenApischema {type = "String"});};
Swashbuckle은 생성 프로세스에 연결되는 필터 파이프 라인을 노출시킵니다. 일단 생성되면, 개별 메타 데이터 객체는 파이프 라인으로 전달되어 더 이상 수정할 수 있습니다. 사용자 정의 필터를 연결하여 생성 된 "작업", "스키마"및 "문서"를 풍부하게 할 수 있습니다.
Swashbuckle은 모든 동작에 대해 ASP.NET Core의 일부인 ApiDescription
을 검색하여 해당 OpenApiOperation
생성하는 데 사용합니다. 일단 생성되면 구성된 작동 필터 목록을 통해 OpenApiOperation
및 ApiDescription
전달합니다.
In a typical filter implementation, you would inspect the ApiDescription
for relevant information (eg route info, action attributes etc.) and then update the OpenApiOperation
accordingly. For example, the following filter lists an additional "401" response for all actions that are decorated with the AuthorizeAttribute
:
// AuthResponsesOperationFilter.cspublic class AuthResponsesOperationFilter : IOperationFilter{public void Apply(OpenApiOperation operation, OperationFilterContext context){var authAttributes = context.MethodInfo.DeclaringType.GetCustomAttributes(true).Union(context.MethodInfo.GetCustomAttributes(true)).OfType<AuthorizeAttribute>();if (authAttributes.Any())operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" });}}// Startup.csservices.AddSwaggerGen(c =>{...c.OperationFilter<AuthResponsesOperationFilter>();};
NOTE: Filter pipelines are DI-aware. That is, you can create filters with constructor parameters and if the parameter types are registered with the DI framework, they'll be automatically injected when the filters are instantiated
Swashbuckle generates a Swagger-flavored JSONSchema for every parameter, response and property type that's exposed by your controller actions. Once generated, it passes the schema and type through the list of configured Schema Filters.
The example below adds an AutoRest vendor extension (see https://github.com/Azure/autorest/blob/master/docs/extensions/readme.md#x-ms-enum) to inform the AutoRest tool how enums should be modelled when it generates the API client.
// AutoRestSchemaFilter.cspublic class AutoRestSchemaFilter : ISchemaFilter{public void Apply(OpenApiSchema schema, SchemaFilterContext context){var type = context.Type;if (type.IsEnum){schema.Extensions.Add("x-ms-enum",new OpenApiObject{["name"] = new OpenApiString(type.Name),["modelAsString"] = new OpenApiBoolean(true)});};}}// Startup.csservices.AddSwaggerGen(c =>{...c.SchemaFilter<AutoRestSchemaFilter>();};
The example below allows for automatic schema generation of generic Dictionary<Enum, TValue>
objects. Note that this only generates the swagger; System.Text.Json
is not able to parse dictionary enums by default, so you will need a special JsonConverter, like in the .NET docs
// DictionaryTKeyEnumTValueSchemaFilter.cspublic class DictionaryTKeyEnumTValueSchemaFilter : ISchemaFilter{ public void Apply(OpenApiSchema schema, SchemaFilterContext context) {// Only run for fields that are a Dictionary<Enum, TValue>if (!context.Type.IsGenericType || !context.Type.GetGenericTypeDefinition().IsAssignableFrom(typeof(Dictionary<,>))){return;}var keyType = context.Type.GetGenericArguments()[0];var valueType = context.Type.GetGenericArguments()[1];if (!keyType.IsEnum){return;}schema.Type = "object";schema.Properties = keyType.GetEnumNames().ToDictionary(name => name,name => context.SchemaGenerator.GenerateSchema(valueType, context.SchemaRepository)); }}// Startup.csservices.AddSwaggerGen(c =>{...// These will be replaced by DictionaryTKeyEnumTValueSchemaFilter, but are needed to avoid an error.// You will need one for every kind of Dictionary<,> you have.c.MapType<Dictionary<MyEnum, List<string>>>(() => new OpenApiSchema());c.SchemaFilter<DictionaryTKeyEnumTValueSchemaFilter>();};
Once an OpenApiDocument
has been generated, it too can be passed through a set of pre-configured Document Filters. This gives full control to modify the document however you see fit. To ensure you're still returning valid Swagger JSON, you should have a read through the specification before using this filter type.
The example below provides a description for any tags that are assigned to operations in the document:
public class TagDescriptionsDocumentFilter : IDocumentFilter{public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context){swaggerDoc.Tags = new List<OpenApiTag> {new OpenApiTag { Name = "Products", Description = "Browse/manage the product catalog" },new OpenApiTag { Name = "Orders", Description = "Submit orders" }};}}
NOTE: If you're using the SwaggerUI
middleware, the TagDescriptionsDocumentFilter
demonstrated above could be used to display additional descriptions beside each group of Operations.
In Swagger, you can describe how your API is secured by defining one or more security schemes (eg basic, api key, oauth2 etc.) and declaring which of those schemes are applicable globally OR for specific operations. For more details, take a look at the Security Requirement Object in the Swagger spec..
In Swashbuckle, you can define schemes by invoking the AddSecurityDefinition
method, providing a name and an instance of OpenApiSecurityScheme
. For example you can define an OAuth 2.0 - implicit flow as follows:
// Startup.csservices.AddSwaggerGen(c =>{ ... // Define the OAuth2.0 scheme that's in use (ie Implicit Flow) c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme { Type = SecuritySchemeType.OAuth2, Flows = new OpenApiOAuthFlows { Implicit = new OpenApiOAuthFlow { AuthorizationUrl = new Uri("/auth-server/connect/authorize", UriKind.Relative), Scopes = new Dictionary<string, string> { { "readAccess", "Access read operations" }, { "writeAccess", "Access write operations" } } } } });};
NOTE: In addition to defining a scheme, you also need to indicate which operations that scheme is applicable to. You can apply schemes globally (ie to ALL operations) through the AddSecurityRequirement
method. The example below indicates that the scheme called "oauth2" should be applied to all operations, and that the "readAccess" and "writeAccess" scopes are required. When applying schemes of type other than "oauth2", the array of scopes MUST be empty.
c.AddSwaggerGen(c =>{ ... c.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" } }, new[] { "readAccess", "writeAccess" } } });})
If you have schemes that are only applicable for certain operations, you can apply them through an Operation filter. For example, the following filter adds OAuth2 requirements based on the presence of the AuthorizeAttribute
:
// SecurityRequirementsOperationFilter.cspublic class SecurityRequirementsOperationFilter : IOperationFilter{public void Apply(OpenApiOperation operation, OperationFilterContext context){// Policy names map to scopesvar requiredScopes = context.MethodInfo.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Select(attr => attr.Policy).Distinct();if (requiredScopes.Any()){operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" });operation.Responses.Add("403", new OpenApiResponse { Description = "Forbidden" });var oAuthScheme = new OpenApiSecurityScheme{Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" }};operation.Security = new List<OpenApiSecurityRequirement>{new OpenApiSecurityRequirement{[ oAuthScheme ] = requiredScopes.ToList()}};}}}
NOTE: If you're using the SwaggerUI
middleware, you can enable interactive OAuth2.0 flows that are powered by the emitted security metadata. See Enabling OAuth2.0 Flows for more details.
services.AddSwaggerGen(c =>{ c.AddSecurityDefinition("bearerAuth", new OpenApiSecurityScheme { Type = SecuritySchemeType.Http, Scheme = "bearer", BearerFormat = "JWT", Description = "JWT Authorization header using the Bearer scheme." }); c.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "bearerAuth" } }, new string[] {} } });});
Swagger / OpenAPI defines the allOf
and oneOf
keywords for describing inheritance and polymorphism relationships in schema definitions. For example, if you're using a base class for models that share common properties you can use the allOf
keyword to describe the inheritance hierarchy. Or, if your serializer supports polymorphic serialization/deserialization, you can use the oneOf
keyword to document all the "possible" schemas for requests/responses that vary by subtype.
By default, Swashbuckle flattens inheritance hierarchies. That is, for derived models, the inherited properties are combined and listed alongside the declared properties. This can cause a lot of duplication in the generated Swagger, particularly when there's multiple subtypes. It's also problematic if you're using a client generator (eg NSwag) and would like to maintain the inheritance hierarchy in the generated client models. To work around this, you can apply the UseAllOfForInheritance
setting, and this will leverage the allOf
keyword to incorporate inherited properties by reference in the generated Swagger:
Circle: { type: "object", allOf: [ { $ref: "#/components/schemas/Shape" } ], properties: { radius: { type: "integer", format: "int32", } }, }, Shape: { type: "object", properties: { name: { type: "string", nullable: true, } }, }
If your serializer supports polymorphic serialization/deserialization and you would like to list the possible subtypes for an action that accepts/returns abstract base types, you can apply the UseOneOfForPolymorphism
setting. As a result, the generated request/response schemas will reference a collection of "possible" schemas instead of just the base class schema:
requestBody: { content: { application/json: { schema: { oneOf: [ { $ref: "#/components/schemas/Rectangle" }, { $ref: "#/components/schemas/Circle" }, ], } } }
As inheritance and polymorphism relationships can often become quite complex, not just in your own models but also within the .NET class library, Swashbuckle is selective about which hierarchies it does and doesn't expose in the generated Swagger. By default, it will pick up any subtypes that are defined in the same assembly as a given base type. If you'd like to override this behavior, you can provide a custom selector function:
services.AddSwaggerGen(c =>{ ... c.UseAllOfForInheritance(); c.SelectSubTypesUsing(baseType => { return typeof(Startup).Assembly.GetTypes().Where(type => type.IsSubclassOf(baseType)); })});
NOTE: If you're using the Swashbuckle Annotations library, it contains a custom selector that's based on the presence of SwaggerSubType
attributes on base class definitions. This way, you can use simple attributes to explicitly list the inheritance and/or polymorphism relationships you want to expose. To enable this behavior, check out the Annotations docs.
In conjunction with the oneOf
and/or allOf
keywords, Swagger / OpenAPI supports a discriminator
field on base schema definitions. This keyword points to the property that identifies the specific type being represented by a given payload. In addition to the property name, the discriminator description MAY also include a mapping
which maps discriminator values to specific schema definitions.
For example, the Newtonsoft serializer supports polymorphic serialization/deserialization by emitting/accepting a "$type" property on JSON instances. The value of this property will be the assembly qualified type name of the type represented by a given JSON instance. So, to explicitly describe this behavior in Swagger, the corresponding request/response schema could be defined as follows:
components: { schemas: { Shape: { required: [ "$type" ], type: "object", properties: { $type: { type": "string" }, discriminator: { propertyName: "$type", mapping: { Rectangle: "#/components/schemas/Rectangle", Circle: "#/components/schemas/Circle" } } }, Rectangle: { type: "object", allOf: [ { "$ref": "#/components/schemas/Shape" } ], ... }, Circle: { type: "object", allOf: [ { "$ref": "#/components/schemas/Shape" } ], ... } } }
If UseAllOfForInheritance
or UseOneOfForPolymorphism
is enabled, and your serializer supports (and has enabled) emitting/accepting a discriminator property, then Swashbuckle will automatically generate the corresponding discriminator
metadata on base schema definitions.
Alternatively, if you've customized your serializer to support polymorphic serialization/deserialization, you can provide some custom selector functions to determine the discriminator name and corresponding mapping:
services.AddSwaggerGen(c =>{ ... c.UseOneOfForInheritance(); c.SelectDiscriminatorNameUsing((baseType) => "TypeName"); c.SelectDiscriminatorValueUsing((subType) => subType.Name);});
NOTE: If you're using the Swashbuckle Annotations library, it contains custom selector functions that are based on the presence of SwaggerDiscriminator
and SwaggerSubType
attributes on base class definitions. This way, you can use simple attributes to explicitly provide discriminator metadata. To enable this behavior, check out the Annotations docs.
By default, the Swagger UI will be exposed at "/swagger". If necessary, you can alter this when enabling the SwaggerUI middleware:
app.UseSwaggerUI(c =>{ c.RoutePrefix = "api-docs"}
By default, the Swagger UI will have a generic document title. When you have multiple Swagger pages open, it can be difficult to tell them apart. You can alter this when enabling the SwaggerUI middleware:
app.UseSwaggerUI(c =>{ c.DocumentTitle = "My Swagger UI";}
By default, the Swagger UI include default CSS and JS, but if you wish to change the path or URL (for example to use a CDN):
app.UseSwaggerUI(c =>{ c.StylesPath = "https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.17.10/swagger-ui.min.css"; c.ScriptBundlePath = "https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.17.10/swagger-ui-bundle.min.js"; c.ScriptPresetsPath = "https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.17.10/swagger-ui-standalone-preset.min.js";}
When enabling the middleware, you're required to specify one or more Swagger endpoints (fully qualified or relative to the UI page) to power the UI. If you provide multiple endpoints, they'll be listed in the top right corner of the page, allowing users to toggle between the different documents. For example, the following configuration could be used to document different versions of an API.
app.UseSwaggerUI(c =>{ c.SwaggerEndpoint("/swagger/v1/swagger.json", "V1 Docs"); c.SwaggerEndpoint("/swagger/v2/swagger.json", "V2 Docs"); }
The swagger-ui ships with its own set of configuration parameters, all described here. In Swashbuckle, most of these are surfaced through the SwaggerUI middleware options:
app.UseSwaggerUI(c =>{ c.DefaultModelExpandDepth(2); c.DefaultModelRendering(ModelRendering.Model); c.DefaultModelsExpandDepth(-1); c.DisplayOperationId(); c.DisplayRequestDuration(); c.DocExpansion(DocExpansion.None); c.EnableDeepLinking(); c.EnableFilter(); c.EnablePersistAuthorization(); c.EnableTryItOutByDefault(); c.MaxDisplayedTags(5); c.ShowExtensions(); c.ShowCommonExtensions(); c.Plugins = ["myCustomPlugin"]; c.EnableValidator(); c.SupportedSubmitMethods(SubmitMethod.Get, SubmitMethod.Head); c.UseRequestInterceptor("(request) => { return request; }"); c.UseResponseInterceptor("(response) => { return response; }");});
메모
When adding custom plugins, make sure you add any custom js
files that define the plugin function(s).
To tweak the behavior, you can inject additional JavaScript files by adding them to your wwwroot
folder and specifying the relative paths in the middleware options:
app.UseSwaggerUI(c =>{ c.InjectJavascript("/swagger-ui/custom.js");}
NOTE: The InjectOnCompleteJavaScript
and InjectOnFailureJavaScript
options have been removed because the latest version of swagger-ui doesn't expose the necessary hooks. Instead, it provides a flexible customization system based on concepts and patterns from React and Redux. To leverage this, you'll need to provide a custom version of index.html as described below.
The custom index sample app demonstrates this approach, using the swagger-ui plugin system provide a custom topbar, and to hide the info component.
To tweak the look and feel, you can inject additional CSS stylesheets by adding them to your wwwroot
folder and specifying the relative paths in the middleware options:
app.UseSwaggerUI(c =>{ c.InjectStylesheet("/swagger-ui/custom.css");}
To customize the UI beyond the basic options listed above, you can provide your own version of the swagger-ui index.html page:
app.UseSwaggerUI(c =>{ c.IndexStream = () => GetType().Assembly .GetManifestResourceStream("CustomUIIndex.Swagger.index.html"); // requires file to be added as an embedded resource});
To get started, you should base your custom index.html on the default version
The swagger-ui has built-in support to participate in OAuth2.0 authorization flows. It interacts with authorization and/or token endpoints, as specified in the Swagger JSON, to obtain access tokens for subsequent API calls. See Adding Security Definitions and Requirements for an example of adding OAuth2.0 metadata to the generated Swagger.
If your Swagger endpoint includes the appropriate security metadata, the UI interaction should be automatically enabled. However, you can further customize OAuth support in the UI with the following settings below. See Swagger-UI documentation for more info:
app.UseSwaggerUI(c =>{ c.OAuthClientId("test-id"); c.OAuthClientSecret("test-secret"); c.OAuthUsername("test-user"); c.OAuthRealm("test-realm"); c.OAuthAppName("test-app"); c.OAuth2RedirectUrl("url"); c.OAuthScopeSeparator(" "); c.OAuthScopes("scope1", "scope2"); c.OAuthAdditionalQueryStringParams(new Dictionary<string, string> { { "foo", "bar" }}); c.OAuthUseBasicAuthenticationWithAccessCodeGrant(); c.OAuthUsePkce();});
To use custom interceptors on requests and responses going through swagger-ui you can define them as javascript functions in the configuration:
app.UseSwaggerUI(c =>{ c.UseRequestInterceptor("(req) => { req.headers['x-my-custom-header'] = 'MyCustomValue'; return req; }"); c.UseResponseInterceptor("(res) => { console.log('Custom interceptor intercepted response from:', res.url); return res; }");});
This can be useful in a range of scenarios where you might want to append local xsrf tokens to all requests for example:
app.UseSwaggerUI(c =>{ c.UseRequestInterceptor("(req) => { req.headers['X-XSRF-Token'] = localStorage.getItem('xsrf-token'); return req; }"); });
Install the following Nuget package into your ASP.NET Core application.
Package Manager : Install-Package Swashbuckle.AspNetCore.Annotations CLI : dotnet add package Swashbuckle.AspNetCore.Annotations
In the ConfigureServices
method of Startup.cs
, enable annotations within in the Swagger config block:
services.AddSwaggerGen(c =>{ ... c.EnableAnnotations();});
Once annotations have been enabled, you can enrich the generated Operation metadata by decorating actions with a SwaggerOperationAttribute
.
[HttpPost][SwaggerOperation( Summary = "Creates a new product", Description = "Requires admin privileges", OperationId = "CreateProduct", Tags = new[] { "Purchase", "Products" })]public IActionResult Create([FromBody]Product product)
ASP.NET Core provides the ProducesResponseTypeAttribute
for listing the different responses that can be returned by an action. These attributes can be combined with XML comments, as described above, to include human friendly descriptions with each response in the generated Swagger. If you'd prefer to do all of this with a single attribute, and avoid the use of XML comments, you can use SwaggerResponseAttribute
s instead:
[HttpPost][SwaggerResponse(201, "The product was created", typeof(Product))][SwaggerResponse(400, "The product data is invalid")]public IActionResult Create([FromBody]Product product)
You can annotate "path", "query" or "header" bound parameters or properties (ie decorated with [FromRoute]
, [FromQuery]
or [FromHeader]
) with a SwaggerParameterAttribute
to enrich the corresponding Parameter
metadata that's generated by Swashbuckle:
[HttpGet]public IActionResult GetProducts([FromQuery, SwaggerParameter("Search keywords", Required = true)]string keywords)
You can annotate "body" bound parameters or properties (ie decorated with [FromBody]
) with a SwaggerRequestBodyAttribute
to enrich the corresponding RequestBody
metadata that's generated by Swashbuckle:
[HttpPost]public IActionResult CreateProduct([FromBody, SwaggerRequestBody("The product payload", Required = true)]Product product)
You can annotate classes or properties with a SwaggerSchemaAttribute
to enrich the corresponding Schema
metadata that's generated by Swashbuckle:
[SwaggerSchema(Required = new[] { "Description" })]public class Product{[SwaggerSchema("The product identifier", ReadOnly = true)]public int Id { get; 세트; }[SwaggerSchema("The product description")]public string Description { get; 세트; }[SwaggerSchema("The date it was created", Format = "date")]public DateTime DateCreated { get; 세트; }}
NOTE: In Swagger / OpenAPI, serialized objects AND contained properties are represented as Schema
instances, hence why this annotation can be applied to both classes and properties. Also worth noting, "required" properties are specified as an array of property names on the top-level schema as opposed to a flag on each individual property.
The SwaggerGen
package provides several extension points, including Schema Filters (described here) for customizing ALL generated Schemas. However, there may be cases where it's preferable to apply a filter to a specific Schema. For example, if you'd like to include an example for a specific type in your API. This can be done by decorating the type with a SwaggerSchemaFilterAttribute
:
// Product.cs[SwaggerSchemaFilter(typeof(ProductSchemaFilter))]public class Product{...}// ProductSchemaFilter.cspublic class ProductSchemaFilter : ISchemaFilter{public void Apply(OpenApiSchema schema, SchemaFilterContext context){schema.Example = new OpenApiObject{[ "Id" ] = new OpenApiInteger(1),[ "Description" ] = new OpenApiString("An awesome product")};}}
By default, the Swagger generator will tag all operations with the controller name. This tag is then used to drive the operation groupings in the swagger-ui. If you'd like to provide a description for each of these groups, you can do so by adding metadata for each controller name tag via the SwaggerTagAttribute
:
[SwaggerTag("Create, read, update and delete Products")]public class ProductsController{...}
NOTE: This will add the above description specifically to the tag named "Products". Therefore, you should avoid using this attribute if you're tagging Operations with something other than controller name - eg if you're customizing the tagging behavior with TagActionsBy
.
If you want to use Swashbuckle's inheritance and/or polymorphism behavior, you can use annotations to explicitly indicate the "known" subtypes for a given base type. This will override the default selector function, which selects all subtypes in the same assembly as the base type, and therefore needs to be explicitly enabled when you enable Annotations:
// Startup.csservices.AddSwaggerGen(c =>{ c.EnableAnnotations(enableAnnotationsForInheritance: true, enableAnnotationsForPolymorphism: true);});// Shape.cs[SwaggerSubType(typeof(Rectangle))][SwaggerSubType(typeof(Circle))]public abstract class Shape{}
If you're using annotations to explicitly indicate the "known" subtypes for a polymorphic base type, you can combine the SwaggerDiscriminatorAttribute
with the SwaggerSubTypeAttribute
to provide additional metadata about the "discriminator" property, which will then be incorporated into the generated schema definition:
// Startup.csservices.AddSwaggerGen(c =>{ c.EnableAnnotations(enableAnnotationsForInheritance: true, enableAnnotationsForPolymorphism: true);});// Shape.cs[SwaggerDiscriminator("shapeType")][SwaggerSubType(typeof(Rectangle), DiscriminatorValue = "rectangle")][SwaggerSubType(typeof(Circle), DiscriminatorValue = "circle")]public abstract class Shape{public ShapeType { get; 세트; }}
This indicates that the corresponding payload will have a "shapeType" property to discriminate between subtypes, and that property will have a value of "rectangle" if the payload represents a Rectangle
type and a value of "circle" if it represents a Circle
type. This detail will be described in the generated schema definition as follows:
schema: { oneOf: [ { $ref: "#/components/schemas/Rectangle" }, { $ref: "#/components/schemas/Circle" }, ], discriminator: { propertyName: shapeType, mapping: { rectangle: "#/components/schemas/Rectangle", circle: "#/components/schemas/Circle", } } }
Once your application has been setup with Swashbuckle (see Getting Started), you can use the Swashbuckle CLI tool to retrieve Swagger / OpenAPI JSON directly from your application's startup assembly, and write it to file. This can be useful if you want to incorporate Swagger generation into a CI/CD process, or if you want to serve it from static file at run-time.
It's packaged as a .NET Tool that can be installed and used via the dotnet SDK.
켈 The tool needs to load your Startup DLL and its dependencies at runtime. Therefore, you should use a version of thedotnet
SDK that is compatible with your application. For example, if your app targetsnet6.0
, then you should use version 6.0.xxx of the SDK to run the CLI tool. If it targetsnet8.0
, then you should use version 8.0.xxx of the SDK and so on.
Install as a global tool
dotnet tool install -g Swashbuckle.AspNetCore.Cli
Verify that the tool was installed correctly
swagger tofile --help
Generate a Swagger/ OpenAPI document from your application's startup assembly
swagger tofile --output [output] [startupassembly] [swaggerdoc]
어디 ...
[output] is the relative path where the Swagger JSON will be output to
[startupassembly] is the relative path to your application's startup assembly
[swaggerdoc] is the name of the swagger document you want to retrieve, as configured in your startup class
In your project root, create a tool manifest file:
dotnet new tool-manifest
Install as a local tool
dotnet tool install Swashbuckle.AspNetCore.Cli
Verify that the tool was installed correctly
dotnet swagger tofile --help
Generate a Swagger / OpenAPI document from your application's startup assembly
dotnet swagger tofile --output [output] [startupassembly] [swaggerdoc]
어디 ...
[output] is the relative path where the Swagger JSON will be output to
[startupassembly] is the relative path to your application's startup assembly
[swaggerdoc] is the name of the swagger document you want to retrieve, as configured in your startup class
Out-of-the-box, the tool will execute in the context of a "default" web host. However, in some cases you may want to bring your own host environment, for example if you've configured a custom DI container such as Autofac. For this scenario, the Swashbuckle CLI tool exposes a convention-based hook for your application.
That is, if your application contains a class that meets either of the following naming conventions, then that class will be used to provide a host for the CLI tool to run in.
public class SwaggerHostFactory
, containing a public static method called CreateHost
with return type IHost
public class SwaggerWebHostFactory
, containing a public static method called CreateWebHost
with return type IWebHost
For example, the following class could be used to leverage the same host configuration as your application:
public class SwaggerHostFactory{public static IHost CreateHost(){return Program.CreateHostBuilder(new string[0]).Build();}}
By default, the Redoc UI will be exposed at "/api-docs". If necessary, you can alter this when enabling the Redoc middleware:
app.UseReDoc(c =>{ c.RoutePrefix = "docs" ...}
By default, the Redoc UI will have a generic document title. You can alter this when enabling the Redoc middleware:
app.UseReDoc(c =>{c.DocumentTitle = "My API Docs";...}
Redoc ships with its own set of configuration parameters, all described here https://github.com/Rebilly/redoc/blob/main/README.md#redoc-options-object. In Swashbuckle, most of these are surfaced through the Redoc middleware options:
app.UseReDoc(c =>{ c.SpecUrl("/v1/swagger.json"); c.EnableUntrustedSpec(); c.ScrollYOffset(10); c.HideHostname(); c.HideDownloadButton(); c.ExpandResponses("200,201"); c.RequiredPropsFirst(); c.NoAutoAuth(); c.PathInMiddlePanel(); c.HideLoading(); c.NativeScrollbars(); c.DisableSearch(); c.OnlyRequiredInSamples(); c.SortPropsAlphabetically();});
Using c.SpecUrl("/v1/swagger.json")
multiple times within the same UseReDoc(...)
will not add multiple urls.
To tweak the look and feel, you can inject additional CSS stylesheets by adding them to your wwwroot
folder and specifying the relative paths in the middleware options:
app.UseReDoc(c =>{ ... c.InjectStylesheet("/redoc/custom.css");}
It is also possible to modify the theme by using the AdditionalItems
property, see https://github.com/Rebilly/redoc/blob/main/README.md#redoc-options-object for more information.
app.UseReDoc(c =>{ ... c.ConfigObject.AdditionalItems = ...}
To customize the UI beyond the basic options listed above, you can provide your own version of the Redoc index.html page:
app.UseReDoc(c =>{ c.IndexStream = () => GetType().Assembly .GetManifestResourceStream("CustomIndex.ReDoc.index.html"); // requires file to be added as an embedded resource});
To get started, you should base your custom index.html on the default version