重要的通知,如果您在主要版本之間升級! |
---|
*如果您將4.x升級到5.x,則需要了解幾種破裂的更改。有關詳細信息,請參見發行說明 *如果您首先從3.x跳到4.x,那裡也有龍。在這裡查看這些發行說明 |
使用ASP.NET Core構建的API的Swagger Tooling。直接從您的路線,控制器和模型中生成精美的API文檔,包括用於探索和測試操作的UI。
除了Swagger 2.0和OpenAPI 3.0發電機外,Swashbuckle還提供了由生成的Swagger Json提供動力的Awesome Swagger-UI的嵌入式版本。這意味著您可以與始終與最新代碼同步的生活文檔相輔相成。最重要的是,它需要最少的編碼和維護,使您可以專注於構建出色的API。
那不是全部...
一旦擁有可以用誇張描述自己的API,您就可以打開基於誇張的工具的寶藏,包括可以針對廣泛流行平台的客戶生成器。有關更多詳細信息,請參見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核心應用程序中。
Package Manager : Install-Package Swashbuckle.AspNetCore CLI : dotnet add package Swashbuckle.AspNetCore
在Startup.cs
的ConfigureServices
方法中,註冊Swagger Generator,定義一個或多個Swagger文檔。
使用microsoft.openapi.models;
services.addmvc(); services.AddSwaggerGen(C => {C.SwaggerDoc(“ V1”,新的OpenApiInfo {title =“ my api”,version =“ v1”});});});
確保您的API動作和參數用明確的“ HTTP”和“來自”綁定裝飾。
[httppost]公共空白createproduct([[來自Body]產品產品)...
[httpget] public iEnumerable <product> searchproducts([frofquery]字符串關鍵字)...
注意:如果省略顯式參數綁定,則默認情況下,生成器將它們描述為“查詢”參數。
在Configure
方法中,您應該通過以下方法之一將生成的搖動作為JSON端點:
app.mapendpoints(endpoints => {// ... endpoints.mapswagger();});
app.useswagger();
此時,您可以旋轉應用程序,並在“/swagger/v1/swagger.json”上查看生成的Swagger Json。
插入中間件
如果您使用的是基於端點的路由,請添加端點。
可選地,如果要揭示交互式文檔,請插入Swagger-UI中間件,並指定Swagger JSON Endpoint(S)向其供電。
app.useswaggerui(c => {c.swaggerendpoint(“ v1/swagger.json”,“我的api v1”);});
現在,您可以重新啟動應用程序,並在“/Swagger”中查看自動生成的交互式文檔。
在5.0.0
之前的版本中,SwashBuckle將根據NewtonSoft Serialializer的行為生成模式(由API展示的數據類型的描述)。這是有道理的,因為那是當時用ASP.NET核心運送的序列化器。但是,由於版本3.0.0
,ASP.NET Core引入了新的Serializer System.Text.json(STJ)開箱即用,如果您想繼續使用Newtonsoft ,則需要安裝單獨的軟件包並明確地安裝選擇加入。使用Swashbuckle 5.0.0
及以後的模式。也就是說,開箱即用的swashbuckle將假定您使用的是STJ序列化器,並根據其行為生成模式。如果您使用的是Newtonsoft ,則需要安裝單獨的Swashbuckle軟件包並明確選擇加入。無論您使用哪種版本的ASP.NET核心,這都是必需的步驟。
總之 ...
如果您使用的是System.Text.json(STJ) ,則上述設置將足夠, STJ選項/屬性將被Swagger Generator自動尊重。
如果您使用的是Newtonsoft ,則需要安裝單獨的軟件包並明確選擇加入,以確保Swagger Generator自動尊重NewtonSoft設置/屬性:
Package Manager : Install-Package Swashbuckle.AspNetCore.Newtonsoft CLI : dotnet add package Swashbuckle.AspNetCore.Newtonsoft
services.Addmvc(); services.AddSwaggerGer(C => {C.SwaggerDoc(“ V1”,新的OpenApiInfo {title =“ my api”,version =“ v1”}); services.addswaggergnewtswaggergnewtonsoftsoftsoftsoftsoftsupport(); //明確選擇 - 需要在AddSwaggergen()之後放置
Swashbuckle在很大程度上依賴於ApiExplorer
,Apiexplorer是API元數據層,該層帶有ASP.NET核心。如果您使用AddMvc
助手來引導MVC堆棧,則將自動註冊APIEXPLORER,並且SB將無問題。但是,如果您使用AddMvcCore
進行更多配對的MVC堆棧,則需要明確添加ApieXplorer服務:
services.addmvccore()。addapiexplorer();
此外,如果您使用的是常規路由(與屬性路由相反),則在Apiexplorer中不會表示任何控制器和使用常規路由的控制器的操作,這意味著Swashbuckle將無法找到這些控制器並生成Swagger他們的操作。例如:
app.usemvc(routes => {// Swaggergen找不到通過此技術路由的控制器。ROUTES.MAPROUTE(“ default”,“ {controller = home}/{action}/{action = index}/{idex} /{id?}”) ;});
您必須使用Swagger文檔中所需的任何控制器使用屬性路由:
[ROUTE(“示例”)] public Class esupplecontroller:Controller {[httpget(“”)] public iCultionResult dostuff(){ / ** /}}
有關更多信息,請參閱路由文檔。
Swashbuckle由多個組件組成,可以根據您的需求一起使用或單獨使用。從本質上講,有一個搖搖欲墜的發電機,中間件將其暴露為JSON端點,以及包裝的Swagger-UI版本。這3個軟件包可以使用Swashbuckle.AspNetCore
“ metapackage”安裝,並將無縫合作(請參閱入門),以提供從您的代碼自動生成的精美API文檔。
此外,還有附加軟件包(CLI工具,備用UI等),您可以根據需要選擇安裝和配置。
包裹 | 描述 |
---|---|
swashbuckle.aspnetcore.swagger | 露出大肆宣傳JSON端點。它預計將在DI容器中註冊ISwaggerProvider 的實現,並查詢檢索OpenAPIDocument(s) 然後將其暴露為序列化的JSON |
swashbuckle.aspnetcore.swaggergen | 注入以上組件可以使用的ISwaggerProvider 的實現。該特定實現從您的路線,控制器和模型生成OpenApiDocument(s) |
swashbuckle.aspnetcore.swaggerui | 暴露了Swagger-UI的嵌入式版本。您指定可以獲得Swagger JSON的API端點,並使用它們為您的API供電 |
包裹 | 描述 |
---|---|
swashbuckle.aspnetcore.annotations | 包括一組可以應用於控制器,操作和模型以豐富生成的招搖的自定義屬性 |
swashbuckle.aspnetcore.cli | 提供了一個命令行接口,用於直接從啟動組件中檢索Swagger,然後寫入文件 |
swashbuckle.aspnetcore.redoc | 暴露了REDOC UI的嵌入式版本(Swagger-UI的替代品) |
這些軟件包由開源社區提供。
包裹 | 描述 |
---|---|
swashbuckle.aspnetcore.filters | 一些有用的Swashbuckle過濾器,這些過濾器添加了其他文檔,例如請求和響應示例,授權信息等。有關更多詳細信息,請參見其README |
unchase.swashbuckle.aspnetcore.extensions | 一些有用的擴展名(過濾器),這些擴展(過濾器)添加了其他文檔,例如,為未知的角色隱藏patiTems,修復了客戶代碼生成的枚舉等。有關更多詳細信息,請參見其讀數。 |
微元素 | 使用FulentValidation規則,而不是ComponentModel屬性來增強生成的Swagger Schemas |
mmlib.swaggerforocelot | 直接在Ocelot API網關上的微服務的匯總文檔 |
上述步驟將使您啟動並以最少的設置運行。但是,Swashbuckle提供了很多靈活性來自定義,這是您所覺得合適的。查看下表以獲取選項的完整列表:
swashbuckle.aspnetcore.swagger
改變Swagger JSON端點的道路
通過請求上下文修改Swagger
以2.0格式序列化搖搖JSON
使用虛擬目錄和反向代理
自定義OpenAPI文檔如何序列化
swashbuckle.aspnetcore.swaggergen
分配顯式操作ID
列表操作響應
標誌所需的參數和模式屬性
處理表格和文件上傳
處理文件下載
包括XML評論中的描述
提供全球API元數據
生成多個招搖文件
省略過時的操作和/或模式屬性
省略任意操作
自定義操作標籤(例如,UI分組)
更改操作排序順序(例如,UI排序)
自定義模式ID
特定類型的覆蓋模式
使用操作,模式和文檔過濾器擴展發電機
添加安全定義和要求
添加載體Auth的安全定義和要求
繼承和多態性
swashbuckle.aspnetcore.swaggerui
將相對路徑更改為UI
更改文檔標題
更改CSS或JS路徑
列出多個宣傳文件
應用Swagger-UI參數
注入自定義JavaScript
注入自定義CSS
自定義index.html
啟用oauth2.0流
使用客戶端請求和響應攔截器
swashbuckle.aspnetcore.annotations
安裝和啟用註釋
富集操作元數據
豐富響應元數據
豐富參數元數據
豐富請求boby元數據
富集模式元數據
將模式過濾器應用於特定類型
添加標籤元數據
swashbuckle.aspnetcore.cli
直接從初創企業組裝中取出Swagger
使用具有自定義主機配置的CLI工具
swashbuckle.aspnetcore.redoc
將相對路徑更改為UI
更改文檔標題
應用重複參數
注入自定義CSS
自定義index.html
默認情況下,Swagger Json將在以下路線上暴露 -“/swagger/ {documentName }/swagger.json”。如有必要,您可以在啟用Swagger中間件時更改此操作。自定義路由必須包括{documentName}
參數。
app.useswagger(c => {c.routetemplate =“ api-docs/{documenname}/swagger.json”;})
注意:如果您使用的是Swaggerui中間件,則還需要更新其配置以反映新的端點:
app.useswaggerui(c => {c.swaggerendpoint(“/api-docs/v1/swagger.json”,“我的api v1”);})
注意:如果您還需要更新UI本身可用的相對路徑,則需要遵循在變更中發現的UI相對路徑中發現的說明。
如果您需要根據當前請求設置一些Swagger Metadata,則可以配置在序列化文檔之前執行的過濾器。
app.useswagger(c => {c.preserializefilters.add(((Swagger,httpReq)=> {Swagger.Servers =新列表<OpenApiserver> {new OpenApiserver {new OpenApiserver {url = $ {url = $“ {httpreq. scheme}:// host.value}“}};});});
OpenApiDocument
和當前的HttpRequest
都將其傳遞給過濾器。這提供了很大的靈活性。例如,您可以根據“主機”標頭添加明確的API服務器(如圖所示),也可以檢查會話信息或授權標題,並根據用戶權限從文檔中刪除操作。
默認情況下,SwashBuckle將在規範的3.0版中生成和揭露Swagger JSON,正式稱為OpenAPI規範。但是,為了支持向後兼容性,您可以選擇以2.0格式將其曝光,並具有以下選項:
app.useswagger(c => {c.serializeasv2 = true;});
虛擬目錄和反向代理可能會引起生成鏈接和重定向的應用程序的問題,尤其是當應用程序根據Host
標頭返回絕對URL以及從當前請求返回其他信息時。為了避免這些問題,Swashbuckle在可能的情況下使用相對URL,並在配置Swaggerui和Redoc中間件時鼓勵使用它們。
例如,要連接Swaggerui中間件,您將URL提供給一個或多個OpenAPI/Swagger文檔。這是客戶端應用程序Swagger-UI將呼籲檢索API元數據的URL。為了確保虛擬目錄和反向代理背後的作用,您應該相對於Swagger-UI本身的RoutePrefix
表達這一點:
app.useswaggerui(c => {c.RoutepRefix =“ Swagger”; c.swaggerendpoint(“ v1/swagger.json”,“我的api v1”);});});
注意:在文檔的先前版本中,您可能已經將其表示為詞根相關鏈接(例如/swagger/v1/swagger.json
)。如果您的應用程序託管在IIS虛擬目錄上或在轉發前修剪請求路徑的代理後面,則該應用程序將不起作用。如果切換到上面顯示的頁面相關語法,則在所有情況下都應使用。
默認情況下,SwashBuckle將使用OpenAPI文檔對像上的序列化方法序列化OpenAPI文檔。如果需要定制的序列化,則可以創建一個實現ISwaggerDocumentSerializer
接口的自定義文檔序列化器。可以使用ConfigureSwagger()
在服務集合中的SwaggerOptions
上設置這一點:
筆記
如果您打算使用命令行工俱生成OpenAPI規範文件,則必須在Service Collection上使用ConfigureSwagger()
完成此操作。
services.configureswagger(options => {option.setCustomDocumentserizer <customDocumentsErializer>();})
當不使用命令行工具時,也可以在應用程序主機上完成:
app.useswagger(options => {options.setCustomDocumentserizer <customDocumentserializer>();})
搖搖欲墜,可以將操作分配一個operationId
。此ID必須在API中描述的所有操作中是唯一的。工具和庫(例如客戶端生成器)可以使用操作ID唯一識別操作,因此,建議遵循常見的編程命名約定。
自動生成與這些要求匹配的ID,同時還提供了在客戶端庫中有意義的名稱是一項非平凡的任務,因此,Swashbuckle默認情況下省略了operationId
。但是,如有必要,您可以通過裝飾單個路線或提供自定義策略來分配operationIds
。
選項1)用Name
屬性裝飾路線
[httpget(“ {id}”,name =“ getProductById”)] public iCultionResult get(int ID)// aperationid =“ getProductById”
選項2)提供自定義策略
// startup.csservices.addswaggergen(c => {... //使用方法名稱為aperationId c.customoperations(apidesc => {return apidesc.trygetc.trygetmethodinfo(out methodInfo methodInfo)?methodinfo)?methodinfo.name:name :null;});});});};}) )// productscontroller.cs [httpget(“ {id}”)] public iNuctionResult getProductById(int ID)// aperationid =“ getProductById”
注意:使用這兩種方法,API作者負責確保所有操作中operationIds
的唯一性
默認情況下,Swashbuckle將為每個操作產生“ 200”響應。如果動作返迴響應DTO,則將使用該動作為響應主體生成模式。例如 ...
[httppost(“ {id}”)]公共產品getByid(int id)
將產生以下響應元數據:
responses: { 200: { description: "OK", content: { "application/json": { schema: { $ref: "#/components/schemas/Product" } } } } }
如果您需要指定不同的狀態代碼和/或其他響應,或者您的操作返回IActionResult
而不是響應dto,則可以用ProducesResponseTypeAttribute
明確描述響應,該響應以ASP.NET核心寄送。例如 ...
[httppost(“ {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 iictionResult搜索([FromQuery,BindRequired]字符串關鍵字,[FromQuery] PagingParams pagingParams){if(!modelState.isvalid) ] public int pageno {get;放; } public int pagesize {get;放; }}}
除了參數外,Swashbuckle還將在與請求主體綁定的模型中使用時RequiredAttribute
工作。在這種情況下,裝飾的屬性將被標記為身體描述中的“必需”屬性:
// productscontroller.cspublic iRinctionResult create([來自Body]產品產品){if(!modelState.isvalid)返回badrequest(modelState); ...} // product.cspublic class class products {[[必需] public string string name {放; }公共字符串描述{get;放; }}}
該控制器將接受兩個表單字段值和一個從同一表單上傳的命名文件:
[httppost] public void uploadfile([來自form]字符串描述,[fromform] dateTime客戶端,iformfile文件)
重要說明:根據ASP.NET核心文檔,您不應該用
[FromForm]
屬性來裝飾IFormFile
參數,因為從類型中自動推斷出綁定源。實際上,推斷的值是BindingSource.FormFile
,如果應用屬性,它將設置為BindingSource.Form
,而代替,它擰緊ApiExplorer
,apiexplorer,apiexplorer,apiexplorer,apiexplorer,apiexplorer,它具有asp.net core的元數據,並由swashbuckle依靠。這裡的一個特殊問題是Swaggerui不會將參數視為文件,因此,如果您錯誤地包含此屬性,則不會顯示文件上傳按鈕。
ApiExplorer
(SwashBuckle所建立的ASP.NET核心元數據組件)不會默認地呈現FileResult
類型,因此您需要用ProducesResponseType
屬性(或在.NET 5或.NET 5或以上Produces
)中明確說明它。
[httpget(“ {filename}”)] [productesResponSeType(typeof(fileStreamResult),statuscodes.status200ok,“ image/jpeg”)] public filestreamresult getfile(String fileName)
為了增強具有人類友好描述的生成的文檔,您可以用XML註釋註釋控制器操作和模型,並配置SwashBuckle,將這些註釋納入輸出的Swagger JSON:
打開項目的“屬性”對話框,單擊“構建”選項卡,並確保檢查“ XML文檔文件”,或將<GenerateDocumentationFile>true</GenerateDocumentationFile>
element添加到.csproj項目文件的<PropertyGroup>
electer。這將產生一個包含所有XML註釋的文件。
此時,未用XML註釋註釋的任何類或方法都會觸發構建警告。為了抑制這一點,請在“屬性對話框”中的“抑制警告”字段中輸入警告代碼“ 1591”,或在.csproj項目文件的<PropertyGroup>
部分中添加<NoWarn>1591</NoWarn>
。
配置swashbuckle以將文件中的XML註釋納入生成的Swagger JSON:
services.AddSwaggergen(C => {C.SwaggerDoc(“ V1”,新的OpenApiInfo {title =“ My Api -V1”,version =“ v1”}); c.includexmlcomments(assembly.getExeceCutingAssembly() c.includexmlComments( typeof(myController).sembly));}
用摘要,備註,參數和響應標籤註釋您的動作:
/// <summary> ///通過唯一ID /// </summary> /// <earlds> awesomeness!</reverns> /// <param name =“ id>“ id” example =“ 123”)檢索特定產品>產品ID </param> /// <響應代碼=“ 200”>檢索的產品</wesponse> // <響應代碼=“ 404”>找不到</wessions> /// <響應代碼= “ 500”>糟糕!無法立即查找您的產品</wession> [httpget(“ {id}”)] ID)
您還可以用摘要和示例標籤註釋類型:
公共類產品{/// <summary> ///產品的名稱/// </summary> /// <example>男士籃球鞋</example> public string name {get;放; } /// <summary> ///庫存中留下的數量/// </summary> /// <example> 10 </example> public int int availablestock {get;放; } /// <summary> ///尺寸該產品可在/// </summary> /// <example>> [“ SMALL”,“ MEDID”,“大型”] </example>公共列表<字符串>尺寸{get;放; }}}
重建您的項目以更新XML註釋文件並導航到Swagger JSON端點。注意如何將描述映射到相應的宣傳場。
注意:您還可以通過用摘要標籤註釋API模型及其屬性來提供Swagger模式描述。如果您有多個XML註釋文件(例如,用於控制器和模型的單獨庫),則可以多次調用IncludexmlComments方法,它們都將合併到輸出的Swagger JSON中。
除了為您生成的“ Pathitems”,“操作”和“響應”外,Swagger還支持全局元數據(請參閱https://swagger.io/specification/#oasobject)。例如,您可以為您的API,服務條款甚至聯繫和許可信息提供完整的描述:
c.swaggerdoc(“ v1”,新的OpenApiInfo {title =“ my api -v1”,version =“ v1”,description =“示例api to demo swashbuckle”,enterofservice = new uri(“ http://tempuri.org ) /enter“),contact = new OpenApiconTact {name =“ Joe Developer”,email =“ [email protected]”},許可證= new OpenApilicense {new openapilicense {name =“ apache 2.0”,url = url = new uri(“ https:” https:“ https:” //www.apache.org/licenses/license-2.0.html“)}});
提示:使用IntelliSense查看其他哪些字段。
通過上述設置,生成器將在單個Swagger文檔中包含所有API操作。但是,如有必要,您可以創建多個文檔。例如,您可能需要為API的每個版本提供一個單獨的文檔。為此,首先在Startup.cs
中定義多個Swagger文檔:
services.AddSwaggergen(C => {C.SwaggerDoc(“ V1”,New OpenApiInfo {title =“ My api -v1”,版本=“ v1”}); c.swaggerdoc(“ v2”,new OpenApiInfo {new Openapiinfo { title =“我的API -V2“,版本=“ V2”});})
請注意Swaggerdoc的第一個論點。它必須是一個對URI友好的名稱,可以獨特地識別該文檔。隨後,它用來構成請求相應的Swagger JSON的路徑。例如,使用默認路由,上述文檔將在“/swagger/v1/swagger.json”和“/swagger/v2/swagger.json”上找到。
接下來,您需要通知每個文檔中要包含哪些操作。儘管可以自定義(請參見下文),但默認情況下,生成器將使用ApiDescription.GroupName
屬性,該屬性是用ASP.NET核心運輸的內置元數據層的一部分,以進行此區別。您可以通過裝飾單個動作或應用廣泛的慣例來設置此設置。
要在特定的Swagger文檔中包含一個操作,請使用ApiExplorerSettingsAttribute
進行裝飾,然後將GroupName
設置為相應的文檔名稱(案例敏感):
[httppost] [apiexplorersettings(groupName =“ v2”)]公共void post([來自Body]產品產品)
要通過慣例進行分組而不是裝飾所有動作,您可以應用自定義控制器或動作慣例。例如,您可以根據控制器名稱空間將以下約定匯合以將操作分配給文檔。
// apiexplorergrouperverversionconconconvention.cspublic類apiexplorergrouperververversionconvention:icontrollerModeLconvention {public void apply(controllerModel Controller){var contrancterNamespace = controller.controllerTyper.controllerType.namespace; //例如“ controlrers.v1” var apiversion = ControllerNamespace.split('。')。last()。tolower(); controller.apiexplorer.groupname = apiversion = apivers;}}}} // startup.cspubl.cspublic void void configureservices(iserviceCollection services){ services.Addmvc(c => c.conventions.Add(new ApiexplorerGrouperverversionConconcention())); ...}
當選擇給定的Swagger文檔的動作時,生成器會針對框架浮出水面的每個ApiDescription
調用DocInclusionPredicate
。默認實現檢查ApiDescription.GroupName
,如果值為null或等於所請求的文檔名稱,則返回true。但是,您還可以提供自定義的包容性謂詞。例如,如果您使用基於屬性的方法來實現API版本(例如Microsoft.aspnetcore.mvc.versioning),則可以配置一個自定義謂詞,該自定義謂詞會利用版本化屬性:
c.docinclusionPredicate(((DocName,apidesc)=> {if(!Apidesc.trygetMethodInfo(Out MethodInfo MethodInfo))返回false; var versions = methodInfo.declaringType.getCustomatTomatTributes(true) > attr.versions);
如果您使用的是SwaggerUI
中間件,則需要指定要曝光的任何其他Swagger端點。有關更多信息,請參見列表多個Swagger文檔。
Swagger規格包括一個deprecated
標誌,以表明操作被棄用,並應避免使用。如果相應的操作用ObsoleteAttribute
裝飾,則Swagger Generator將自動設置此標誌。但是,您可以配置發電機以完全忽略過時的操作,而不是設置標誌:
services.addswaggergen(c => {... c.ignoreobsoleteactions();};
也可以使用類似的方法來省略Swagger輸出中模式的過時性能。也就是說,您可以使用ObsoleteAttribute
裝飾模型屬性,並配置swashbuckle,以省略這些屬性,以生成JSON Schemas:
services.AddSwaggerGen(c => {... c.ignoreObsoleteProperties();};
您可以通過裝飾單個動作或應用廣泛的約定來省略Swagger輸出的操作。
要省略特定的動作,請用ApiExplorerSettingsAttribute
進行裝飾,並設置IgnoreApi
標誌:
[httpget(“ {id}”)] [apiexplorersettings(ignoreapi = true)]公共產品getByid(int id)
為了通過慣例省略行動,而不是單獨裝飾它們,您可以應用自定義行動慣例。例如,您可以將以下約定匯總以獲取操作:
// apiexplorergetsonlyconvention.cspublic類apiexplorergetSonlyConcention:iictionModelConcention {public void applion(actionModel action){action.apiexplorer.isvisible = action = action = action = action.attributes.attributes.oftype <httppetTribute issect in. outrection services){services.addmvc( c => c.conventions.add(new ApiexplorergetSonlyConcention())); ...}
Swagger Spec允許將一個或多個“標籤”分配給操作。 Swagger Generator將把控制器名稱分配為默認標籤。這很重要,需要注意,如果您使用SwaggerUI
中間件,因為它將此值用於組操作。
您可以通過提供按照慣例應用標籤的函數來覆蓋默認標籤。例如,以下配置將通過HTTP方法標記,因此在UI中進行了組操作:
services.AddSwaggergen(c => {... c.tagactionsby(api => api.httpmethod);};};
默認情況下,通過分配的標籤(請參見上文)排序操作,然後將其分組為以路徑為中心的Swagger Spec的嵌套結構。但是,您可以通過自定義排序策略更改操作的默認排序:
services.AddSwaggergen(c => {... c.orderactionsby(((apidesc)=> $” {apidesc.actiondescriptor.routevalues [“ controler”]} _ {apidesc.httpmethod} _} _};};};
注意:這決定了在將動作分組並轉換為誇張格式之前的排序順序。因此,它會影響組的順序(即Swagger“ pathitems”),以及在招搖輸出中的組中的操作排序。
如果生成器遇到復雜的參數或響應類型,它將生成相應的JSON模式,將其添加到全局components/schemas
詞典中,並通過唯一ID從操作描述中引用它。例如,如果您有返回Product
類型的操作,則生成的模式將如下所述:
responses: { 200: { description: "OK", content: { "application/json": { schema: { $ref: "#/components/schemas/Product" } } } } }
但是,如果它遇到具有相同名稱的多種類型,但是不同的名稱空間(例如RequestModels.Product
& ResponseModels.Product
),則Swashbuckle將由於“矛盾的schemaids”而引起例外。在這種情況下,您需要提供一種自定義ID策略,該策略進一步符合名稱:
services.addswaggergen(c => {... c.customschemaids((type)=> type.fullname);};};
有關嵌套類型的支持,請參見#2703。
開箱即用,Swashbuckle在生成JSON模式方面做得不錯,可以準確描述您的請求和響應有效負載。但是,如果您要自定義API中某些類型的序列化行為,則可能需要幫助它。
例如,您可能有一個具有多個屬性的類,您想在JSON中表示為逗號分隔的字符串。為此,您可能會實現自定義JsonConverter
。在這種情況下,Swashbuckle不知道如何實現轉換器,因此您需要為其提供準確描述類型的模式:
// phonenumber.cspublic類PhoneNumber {public String CountryCode {get;放; } public String airscode {get;放; } public String subscriberid {get;放; }} // startup.csservices.addswaggergen(c => {... c.maptype <Phonenumber>(()=> new OpenApeChema {type =“ strign” strign'});};};
Swashbuckle暴露了一條過濾管道,該管道將掛鉤到生成過程中。產生後,單個元數據對象將傳遞到管道中,可以進一步修改它們。您可以連接自定義過濾器,以豐富生成的“操作”,“架構”和“文檔”。
SwashBuckle檢索每個動作的ASP.NET Core的一部分的ApiDescription
,並使用它來生成相應的OpenApiOperation
。生成後,它通過配置的操作過濾器列表將OpenApiOperation
和ApiDescription
傳遞。
在典型的過濾器實現中,您將檢查ApiDescription
是否相關信息(例如路由信息,操作屬性等),然後相應地更新OpenApiOperation
。 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.
配x 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