在.NET?Core?Web?API中完美配置Swagger文檔的方法
新建項目
打開visual studio創(chuàng)建新項目,這里我們選擇.net core web api模板,然后輸入項目名稱及其解決方案創(chuàng)建新項目
這里使用配置一些其他信息,根據(jù)自己情況進行選擇:
創(chuàng)建好項目之后我們可以看到 web api 模板運行的項目,相比于MVC模式開發(fā)的項目,初始文件是保留原有的控制器文件但是刪除了模型和視圖文件,而且還加上了兩個文件,文件的作用相當于測試用例一一可以模擬發(fā)起請求,如下所示:
我們直接運行該項目,可以看到我們打開了一個Swagger文件,對于后端小白來說可能不太熟悉這個文件的作用,但是對于前端開發(fā)者來講可謂是非常熟悉的東西,前端開發(fā)調用接口就需要經(jīng)常和這個文件打交道,如下所示:
我們除了可以在Swagger上測試接口,也可以在本地代碼的測試用例處點擊發(fā)起請求進行測試:
這里做一個演示,比如說我們想在Swagger文檔中新增一組接口的話,我們可以在控制器文件中設置一下get、post、delete、put請求操作,如下我們將原本的文件復制一份然后命名為First,然后設置一下接口類型,如下所示:
重新運行我們的項目然后打開Swagger,可以看到我們創(chuàng)建的一組接口成功出現(xiàn)了,這里接口的組名可以看到是 FirstController.cs 文件中Controller的前綴,非常好識別:
RestFul
背景:近些年來隨著移動互聯(lián)網(wǎng)的發(fā)展,前端設備層出不窮(手機、平板、桌面電腦、其他專用設備..),因此必須有一組統(tǒng)一的機制方便不同的前端設備與后端進行通信,于是RestFul誕生了,它可以通過一套統(tǒng)一的接口為Web,iOS和Android等各種各樣的終端提供服務。
特點:RestFul把控制器作為維度當成一塊資源,對于這個資源會進行增刪改查等各種當作,這些動作必須都得有唯一的URL地址來匹配請求的Method的類型(get、post、put、delete),本質上就是用URL定位資源,用HTTP(get、post、put、delete)描述操作。說白了就是一種軟件架構設計風格而不是標準,只是提供了一組設計原則和約束條件,主要用于客戶端和服務器交互類的軟件,基于這個風格設計的軟件可以更簡潔有層次,更易于實現(xiàn)緩存等機制。
比如上文我們在控制器文件中設置了一組接口,如果我們再在文件中添加比如說一個get接口請求,運行項目其實是會報錯的,為什么?就是因為這兩個get請求的地址都是一樣的,編輯器沒法識別到底哪個get請求是你想要的,為了區(qū)分我們必須設置唯一的URL地址來避免報錯,如下:
重新運行項目,可以看到我們在First組當中又新增了一個新的get請求,且兩個get請求的URL路徑是不一致的,如下所示:
對于路由約束的類型我們可以參考如下表格,這些都可以作為接口傳參的一個類型限定:
限制 | 示例 | 匹配示例 | 說明 |
---|---|---|---|
int | {id: int} | 123456789, -123456789 | 匹配任何整數(shù) |
bool | {active: bool} | true, false | 匹配true或false,忽略大小寫 |
datetime | {dob: datetime} | 2024-12-11,2024-12-12 7:32pm | 匹配滿足datetime類型的值 |
decimal | {price: decimal} | 49.99, -1,000.01 | 匹配滿足decimal類型的值 |
double | {height: double} | 1234, -1001.01e8 | 匹配滿足double類型的值 |
float | {height: float} | 1234, -1001.01e8 | 匹配滿足float類型的值 |
long | {ticks: long} | 123456789, -123456789 | 匹配滿足long類型的值 |
minlength(value) | {usename: minlength(4)} | KOBE | 字符串長度不能小于4個字符 |
maxlength(value) | {filename: maxlength(8)} | CURRY | 字符串長度不能超過8個字符 |
length(value) | {filename: length(12)} | somefile.txt | 字符串長度必須是12個字符 |
length(min,max) | {filename: length(8,16)} | somefile.txt | 字符串長度必須介于8和16之間 |
min(value) | {age: min(18)} | 20 | 整數(shù)值必須大于18 |
max(value) | {age: max(120)} | 119 | 整數(shù)值必須小于120 |
range(min, max) | {age: range(18, 120)} | 100 | 整數(shù)值必須介于18和120之間 |
alpha | {name: alpha} | Rick | 字符串必須由一或多a-z字母組成 |
regex(expression) | {ssn:regex(^\d{3})} | 3 | 字符串必須匹配指定的正則 |
required |
Swagger配置
雖然上面我設置了Swagger并成功運行了,但是設想一個場景,如果你是后端你寫的代碼你當然看的懂,生成的Swagger接口也是知道是什么意思,但是你把這個Swaager丟給前端,前端是否看的懂呢?如果看不懂是不是還要找后端溝通,這樣就增加了時間成本。所以后端不僅僅要不接口寫對,還要把Swagger文檔寫好,這里我們就需要對其進行相應配置,爭取讓其他人看懂自己寫的接口,這才是真正意義上一名后端應該做的事情,如下所示:
注釋展示
注釋是很重要的,當我們寫完一個接口之后我們就需要對這個接口的作用進行注釋,用來告訴前端后端給的這個接口作用和意義是什么,如何設置Swagger注釋展示呢?請往下看:
如下我們給接口代碼寫下注釋,注釋的快捷鍵是///,也就是三個斜杠即可生成,然后右鍵項目點擊屬性,勾選文檔文件這個復選框:
我們右鍵項目重新生成解決方案然后打開我們的項目資源管理目錄,可以看到在我們項目的obj目錄下的最里層有生成了一個xml文件,右鍵選擇文本打開可以看到我們的注釋就在里面:
接下來如果說我們想把注釋展示到Swagger文檔中的話,我們需要來到入口文件Program.cs對我們的Swagger進行一個配置,給原本的AddSwaggerGen添加一個配置對象,代碼如下:
builder.Services.AddSwaggerGen(option => { #region 注釋展示 { // 獲取應用程序所在目錄(絕對,不受工作目錄影響,建議采用此方法獲取路徑) string basePath = AppContext.BaseDirectory; string xmlPath = Path.Combine(basePath, "netCoreWebApi.xml"); option.IncludeXmlComments(xmlPath); } #endregion });
回到Swagger文檔中可以看到我們的注釋已經(jīng)成功的被渲染出來了,方便前端的理解:
版本控制
隨著項目不斷升級和開發(fā)的過程中,我們還可能需要去對項目進行開發(fā)多個版本,但是版本之間的Swagger是不同的,不會放置在同一個Swagger文檔下面,我們打開Swagger文檔也能看到右上角有個下拉框,其就是支持不同的版本的切換的,如何做?請往下看:
為了方便不同版本的切換,這里我們直接在解決方案中新建項目設置一個獨立的文件夾出來,因為待會我們還要對其作一個擴展,所以這里我們選擇一個類庫即可,如下:
生成的文件我們重命名為 ApiVersionInfo ,然后設置靜態(tài)成員V1到V5表明版本有5個,如下所示:
我們來到入口文件Program.cs文件處,這里我們開始設置支持Swagger版本控制的代碼,這里我們借助 System.Reflection 中的FieldInfo反射機制中的類型,來獲取類型ApiVersionInfo中的所有字段信息,然后通過OpenApiInfo來描述Swagger文檔的元數(shù)據(jù)及包含了有關API的關鍵信息,比如標題、版本、描述等,如下所示:
builder.Services.AddSwaggerGen(option => { #region 注釋展示 { // 獲取應用程序所在目錄(絕對,不受工作目錄影響,建議采用此方法獲取路徑) string basePath = AppContext.BaseDirectory; string xmlPath = Path.Combine(basePath, "netCoreWebApi.xml"); option.IncludeXmlComments(xmlPath); } #endregion #region 支持Swagger版本控制 { foreach (FieldInfo filed in typeof(ApiVersionInfo).GetFields()) { option.SwaggerDoc(filed.Name, new OpenApiInfo() { Title = $"netCoreWebApi API {filed.Name}", Version = filed.Name, Description = $"netCoreWebApi API {filed.Name} 版本" }); } } #endregion });
接下來配置Swagger UI使得每個API版本都有一個對應的Swagger UI頁面,具體來說它會為每個API版本動態(tài)創(chuàng)建一個Swagger UI的入口從而允許用戶查看不同版本的API文檔,如下:
接下來我們來到編寫接口代碼的控制器文件,給不同版本設置如下代碼,作用是將特定的API控制器或者方法標記為屬于某個版本組,從而使得Swagger等工具能夠按版本組織和展示API文檔:
最終呈現(xiàn)的效果如下所示:
Token傳值
如果項目的接口需要授權才能被訪問的話,這里我們就需要通過token傳值的方式來進行鑒權才能調試接口,如何做呢?請往下看:
這里我們?nèi)匀辉赟wagger配置函數(shù)中設置token傳值以及添加對應的安全要求,如下所示:
#region 支持token傳值 { option.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme() { Description = "JWT授權(數(shù)據(jù)將在請求頭中進行傳輸) 參數(shù)結構: \"Authorization: Bearer {token}\"", // 描述 Name = "Authorization", // 授權名稱 In = ParameterLocation.Header, // 授權位置,放在頭信息進行傳值 Type = SecuritySchemeType.ApiKey, // 授權類型 BearerFormat = "JWT", // 格式是JWT Scheme = "Bearer" }); // 添加安全要求 option.AddSecurityRequirement(new OpenApiSecurityRequirement() { { new OpenApiSecurityScheme { Reference = new OpenApiReference() { Id = "Bearer", // 必須和上面一致 Type = ReferenceType.SecurityScheme } }, new string[] { } } }); } #endregion
運行項目來到Swagger文檔中,可以看到我們已經(jīng)成功添加了身份驗證,這里我們輸入對應的JWT格式即可,如下所示我們輸入token之后發(fā)起請求,如下已經(jīng)帶上了我們設置的token:
方法封裝
根據(jù)上面對Swagger的配置,可以看到我們對Swagger的配置基本上都寫在了入口Program.cs文件當中,這樣就顯得非常的冗余,入口文件代碼量太多了,這里我們可以將對Swagger的配置抽離到我們創(chuàng)建的類庫當中,新建一個文件夾用于專門存放Swagger配置的東西,如下所示:
這里設置一個函數(shù)然后把IServiceCollection設置為Service的類型,該類型用于配置依賴注入容器的接口,通常為Swagger配置服務,我們直接把入口文件當中配置Swagger的代碼直接粘貼過來:
using System.Reflection; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.OpenApi.Models; namespace netCoreWebApi.WebCore.SwaggerExt { public static class SwaggerExtension { public static void AddSwaggerExtension(this IServiceCollection Service) { Service.AddEndpointsApiExplorer(); Service.AddSwaggerGen(option => { #region 注釋展示 { // 獲取應用程序所在目錄(絕對,不受工作目錄影響,建議采用此方法獲取路徑) string basePath = AppContext.BaseDirectory; string xmlPath = Path.Combine(basePath, "netCoreWebApi.xml"); option.IncludeXmlComments(xmlPath); } #endregion #region 支持Swagger版本控制 { foreach (FieldInfo filed in typeof(ApiVersionInfo).GetFields()) { option.SwaggerDoc(filed.Name, new OpenApiInfo() { Title = $"netCoreWebApi API {filed.Name}", Version = filed.Name, Description = $"netCoreWebApi API {filed.Name} 版本" }); } } #endregion #region 支持token傳值 { option.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme() { Description = "JWT授權(數(shù)據(jù)將在請求頭中進行傳輸) 參數(shù)結構: \"Authorization: Bearer {token}\"", // 描述 Name = "Authorization", // 授權名稱 In = ParameterLocation.Header, // 授權位置,放在頭信息進行傳值 Type = SecuritySchemeType.ApiKey, // 授權類型 BearerFormat = "JWT", // 格式是JWT Scheme = "Bearer" }); // 添加安全要求 option.AddSecurityRequirement(new OpenApiSecurityRequirement() { { new OpenApiSecurityScheme { Reference = new OpenApiReference() { Id = "Bearer", // 必須和上面一致 Type = ReferenceType.SecurityScheme } }, new string[] { } } }); } #endregion }); } public static void UseSwaggerExtension(this WebApplication app) { app.UseSwagger(); app.UseSwaggerUI(option => { foreach (FieldInfo filed in typeof(ApiVersionInfo).GetFields()) { option.SwaggerEndpoint($"/swagger/{filed.Name}/swagger.json", filed.Name); } }); } } }
這里還需要在類庫中安裝一下主程序當中包,這里注意意義名稱和版本號:
因為this修飾靜態(tài)類中的靜態(tài)方法,上面創(chuàng)建的兩個方法都是靜態(tài)類中的靜態(tài)方法同時第一個參數(shù)還用this進行修飾,這種擴展方法可以把傳參提到前面當成實例方法來進行調用,接下來我們就在入口文件中調用這兩個方法:
最后我們重新運行項目,如下可以看到我們的Swagger也可以被重新運行:
到此這篇關于如何在.NET Core Web API中完美配置Swagger文檔的文章就介紹到這了,更多相關.NET Core Web API 配置Swagger文檔內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Could not load file or assembly "App_Licenses.dll"
Could not load file or assembly "App_Licenses.dll"的問題2010-03-03淺析Repeater控件的使用 (原樣導出和動態(tài)顯示/隱藏Repeater中的列)
本文主要介紹了淺析Repeater控件的使用 (原樣導出和動態(tài)顯示/隱藏Repeater中的列)的具體方法,需要的朋友可以看下2016-12-12.net Core 3.0 WebApi 創(chuàng)建Linux守護進程的方法
這篇文章主要介紹了.net Core 3.0 WebApi 創(chuàng)建Linux守護進程的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-03-03