一、概述
剛參加工作時,寫個API接口,還要寫API文檔,再使用PostMan測試接口,寫文檔的時間比寫接口還要折騰。后來接觸Swagger,API文檔的工作得到了很大的改善,不但可以自動構建交互式API說明文檔,還能直接調試API接口。今天記錄下Core項目下使用Swagger,最新版的Swagger已經完美支持Open Api規范及JWT Token授權訪問等。使用Swagger的好處總結如下:
- 使用 Swagger 生成精美的API接口文檔
- 使用 Swagger 調試JWT授權接口
- 使用 Swagger 生成各個類庫中視圖模型的描述
二、配置Swagger服務
1、引用Nuget包
新建一個.NET Core 3.1 Web Api 項目,打開Nuget安裝管理器,搜索Swashbuckle.AspNetCore,安裝即可
2、配置服務
我們打開Startup.cs文件,來對Swagger配置進行一些必要的配置,在ConfigureServices方法我們添加一下Swagger配置:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Core.Api", Version = "v1" });
});
}
然后我們在Configure方法里添加swagger中間件:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Core.Api v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
這樣swagger基本配置就完成了,看下效果
3、忽略注釋警告
F5運行項目后發現有很多警告:
原因是是swagger把一些 action 方法都通過xml文件配置了,如果沒有加入相應的注釋就會警告。如果不想每一個方法都加注釋,可以如下配置:選擇項目,右鍵屬性,選擇生成菜單,加入;1591
4、為接口添加注釋
右鍵項目名稱=>屬性=>生成,勾選“輸出”下面的“xml文檔文件”,系統會默認生成一個xml。
此時項目中會生成一個 Core.Api.xml文件,修改該文件屬性,選擇較新則復制。然后修改下startup.cs中的ConfigureServices方法:
public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "Core.Api", Version = "v1" }); // 為 Swagger JSON and UI設置xml文檔注釋路徑 //獲取應用程序所在目錄(絕對,不受工作目錄影響,建議采用此方法獲取路徑) var basePath = AppContext.BaseDirectory; var xmls = Directory.GetFiles(basePath, "*.xml"); foreach (var aXml in xmls) { c.IncludeXmlComments(aXml); } }); }
然后action方法上加入注釋:
/// <summary> /// 獲取數據 /// </summary> /// <returns></returns> [HttpGet] public IEnumerable<WeatherForecast> Get() { var rng = new Random(); return Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = rng.Next(-20, 55), Summary = Summaries[rng.Next(Summaries.Length)] }) .ToArray(); }
看下效果:
5、為Model 添加注釋
新建一個model,加入字段注釋
public class StudentModel
{
/// <summary>
/// 標識
/// </summary>
public int ID { get; set; }
/// <summary>
/// 姓名
/// </summary>
public string Name { get; set; }
}
為model所在的項目也要配置xml,類似於上述第三步
//注入model 的xml
var xmlModelPath = Path.Combine(basePath, "xx.Model.xml");//這個就是Model層的xml文件名 c.IncludeXmlComments(xmlModelPath);
控制器中引用:
/// <summary>
/// 插入學生信息
/// </summary>
/// <param name="studentModel">model實體類參數</param>
/// <returns></returns>
[HttpPost]
public bool Insert([FromQuery] StudentModel studentModel)
{
return true;
}
效果如下:
6、隱藏接口
如果不想顯示某些接口,直接在controller 上,或者action 上,增加特性可隱藏接口
[ApiExplorerSettings(IgnoreApi = true)]
7、Swagger啟用API文檔的JWT授權
目前很多網站都使用了JWT(JSON WEB TOKEN)來作為賬戶系統的認證授權,JWT以它的簡單、高效、分布式優勢很快成為了網站的流行驗證方式。接下來我們為Swagger添加JWT授權認證,依舊打開Startup.cs文件,修改上面ConfigureServices方法中的代碼:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Core.Api", Version = "v1" });
#region 加載xml
// 為 Swagger JSON and UI設置xml文檔注釋路徑
//獲取應用程序所在目錄(絕對,不受工作目錄影響,建議采用此方法獲取路徑)
var basePath = AppContext.BaseDirectory;
var xmls = Directory.GetFiles(basePath, "*.xml");
foreach (var aXml in xmls)
{
c.IncludeXmlComments(aXml);
}
#endregion
#region jwt認證
// 開啟加權小鎖
c.OperationFilter<AddResponseHeadersFilter>();
c.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();
// 在header中添加token,傳遞到后台
c.OperationFilter<SecurityRequirementsOperationFilter>();
// Jwt Bearer 認證
c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
{
Name = "Authorization",//jwt默認的參數名稱
In = ParameterLocation.Header,//jwt默認存放Authorization信息的位置(請求頭中)
Type = SecuritySchemeType.ApiKey,
Description = "Authorization:Bearer {your JWT token},注意兩者之間是一個空格",
});
#endregion
});
}
預覽一下授權設置,發現右側多了一個Authorize綠色的帶鎖按鈕,這個按鈕點開后就可以設置我們的JWT Token信息了,格式是:Bearer 你的Token字符串,注意Bearer於Token之間有個空格。設置好Token后,你請求任意的API接口時,Swagger會自動附帶Token到請求的Header中。
既然swagger中支持了jwt認證,那么我們在startup.cs中啟用jwt認證:如下
public void ConfigureServices(IServiceCollection services) { services.AddControllers(); #region 開啟jwt認證 var symmetricKeyAsBase64 = "!@#123"; var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64); var signingKey = new SymmetricSecurityKey(keyByteArray); services.AddAuthentication(x => { x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(o => { o.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = signingKey, ValidateIssuer = true, ValidIssuer = "asd",//發行人 ValidateAudience = true, ValidAudience = "fdf",//訂閱人 ValidateLifetime = true, ClockSkew = TimeSpan.Zero,//這個是緩沖過期時間,也就是說,即使我們配置了過期時間,這里也要考慮進去,過期時間+緩沖 RequireExpirationTime = true, }; }); #endregion #region 配置swagger文檔 services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "Core.Api", Version = "v1" }); #region 加載xml // 為 Swagger JSON and UI設置xml文檔注釋路徑 //獲取應用程序所在目錄(絕對,不受工作目錄影響,建議采用此方法獲取路徑) var basePath = AppContext.BaseDirectory; var xmls = Directory.GetFiles(basePath, "*.xml"); foreach (var aXml in xmls) { c.IncludeXmlComments(aXml); } #endregion #region jwt認證 // 開啟加權小鎖 c.OperationFilter<AddResponseHeadersFilter>(); c.OperationFilter<AppendAuthorizeToSummaryOperationFilter>(); // 在header中添加token,傳遞到后台 c.OperationFilter<SecurityRequirementsOperationFilter>(); // Jwt Bearer 認證 c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme { Name = "Authorization",//jwt默認的參數名稱 In = ParameterLocation.Header,//jwt默認存放Authorization信息的位置(請求頭中) Type = SecuritySchemeType.ApiKey, Description = "Authorization:Bearer {your JWT token},注意兩者之間是一個空格", }); #endregion }); #endregion }
更詳細關於jwt認證的這里就不細講了
8、默認直接訪問swagger
有時候打開webapi項目,希望直接打開swagger文檔,有兩種方法:
- 方法一:設置launchSettings.json文件中的launchUrl屬性,指定為swagger,如下:
- 方法二我們可以通過RoutePrefix 屬性設置。
app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "Core.Api v1"); c.RoutePrefix = ""; //路徑配置,設置為空,表示直接在根域名訪問swagger文件 });
建議使用方法二。
三、Swagger異常匯總
1、問題一
如果出現如上圖那樣的錯誤,請打開swagger/v1/swagger.json查看具體原因。 常見的原因是action上沒有加入HTTP請求協議,比如[HttpPost]
2、問題二
這是因為接口json文檔定義和調用不是一個,請仔細對比下定義和調用的swagger名稱是否一致。比如定義的時候名稱為“v1”:
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Core.Api", Version = "v1" });
調用的時候也要保證一致:
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Core.Api v1"));
3、問題三
上圖錯誤是路由重載導致的,請確保不要存在多個一樣的路由。