系列目錄
三. 集成輕量級ORM框架——SqlSugar
前一章我們在項目中初步集成了swagger插件,但是還有一些問題需要解決,所以這一章要做的,就是完善swagger的相關設置。
1. 設置swagger ui頁面為啟動頁
在前一章的末尾,我們通過在域名后面輸入/swagger后,成功訪問到swagger ui頁,但是我們發現每次運行項目,都會默認訪問api/values這個接口,我想要將啟動頁設為swagger(或者是你畫好的任一個html頁),那應該怎么設置呢?
位置就在Properties下的launchSettings.json文件里,只要將profiles下的launchUrl改成你需要的地址就可以
當然,文件里還有其他一些基本設置,比如端口設置,就不一一說了。
2. 注釋問題
swagger很重要的一個功能,就是將我們接口的注釋信息和參數(包括實體類)的注釋信息顯示到頁面上。
現在我們分別將控制器、函數和參數添加相應的注釋(添加方式是在類或函數的上一行敲三下“/”)
F5運行,發現swagger ui上並沒有將它們顯示出來。那是因為還缺少兩步
2.1項目生成xml注釋文件
右鍵項目名稱=>屬性=>生成
勾選“輸出”下面的“生成xml文檔文件”,后面填寫保存該文檔的地址(xml文件的名字可以修改,但是不建議修改保存的路徑,然后記住這個地址,待會會用到)
操作完之后,我們會發現錯誤列表會多出很多黃色的警告,提示“缺少XML注釋”。
這時只需要像之前那樣,在類或函數的上面一行添加注釋即可。(當然,如果沒有強迫症的話,裝作沒看到也是不影響的~)
如果我們按照剛才記住的地址去文件夾查看,也能看到對應xml文件。
2.2啟動類中添加swagger服務來讀取這個xml文件
重新編輯Startup.cs,修改ConfigureServices函數:
/// <summary> /// This method gets called by the runtime. Use this method to add services to the container. /// </summary> /// <param name="services"></param> public void ConfigureServices(IServiceCollection services) { services.AddMvc(); #region Swagger services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new Info { Version = "v1.1.0", Title = "Ray WebAPI", Description = "框架集合", TermsOfService = "None", Contact = new Swashbuckle.AspNetCore.Swagger.Contact { Name = "RayWang", Email = "2271272653@qq.com", Url = "http://www.cnblogs.com/RayWang" } }); //添加讀取注釋服務 var basePath = PlatformServices.Default.Application.ApplicationBasePath; var xmlPath = Path.Combine(basePath, "APIHelp.xml"); c.IncludeXmlComments(xmlPath); }); #endregion }
以上兩步完成之后,F5運行調試:
我們之前添加的注釋就全部都出來了。
現在是不是突然覺得swagger很有用處了?
其實到這兒,細心的人都會發現,有一個地方還是沒有顯示注釋,就是控制器的名稱(在這個例子里就是values),我們之前在代碼里明明也添加了注釋,這里卻沒有顯示出來,為什么?
好,接下來要放我個人私藏的大招了~
解決辦法是:在項目中添加一個文件夾“SwaggerHelp”,在該文件加下添加類“SwaggerDocTag”,這個類的作用是根據控制器的名稱向swagger ui額外附加注釋,代碼如下:
using Swashbuckle.AspNetCore.Swagger; using Swashbuckle.AspNetCore.SwaggerGen; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace CKPI.SwaggerHelp { /// <summary>
/// Swagger注釋幫助類 /// </summary>
public class SwaggerDocTag : IDocumentFilter { /// <summary>
/// 添加附加注釋 /// </summary>
/// <param name="swaggerDoc"></param>
/// <param name="context"></param>
public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context) { swaggerDoc.Tags = new List<Tag> { //添加對應的控制器描述 這個是我好不容易在issues里面翻到的
new Tag { Name = "Values", Description = "測試模塊" }, }; } } }
接下來要去Startup.cs添加相應的服務:
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using CKPI.SwaggerHelp; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.Extensions.PlatformAbstractions; using Swashbuckle.AspNetCore.Swagger; namespace RayPI { /// <summary>
///
/// </summary>
public class Startup { /// <summary>
///
/// </summary>
/// <param name="configuration"></param>
public Startup(IConfiguration configuration) { Configuration = configuration; } /// <summary>
///
/// </summary>
public IConfiguration Configuration { get; } /// <summary>
/// This method gets called by the runtime. Use this method to add services to the container. /// </summary>
/// <param name="services"></param>
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); #region Swagger services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new Info { Version = "v1.1.0", Title = "Ray WebAPI", Description = "框架集合", TermsOfService = "None", Contact = new Swashbuckle.AspNetCore.Swagger.Contact { Name = "RayWang", Email = "2271272653@qq.com", Url = "http://www.cnblogs.com/RayWang" } }); //添加注釋服務
var basePath = PlatformServices.Default.Application.ApplicationBasePath; var xmlPath = Path.Combine(basePath, "APIHelp.xml"); c.IncludeXmlComments(xmlPath); //添加對控制器的標簽(描述)
c.DocumentFilter<SwaggerDocTag>(); }); #endregion } /// <summary>
/// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. /// </summary>
/// <param name="app"></param>
/// <param name="env"></param>
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseMvc(); #region Swagger app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "ApiHelp V1"); }); #endregion } } }
現在再次運行調試,你會發現,控制器的注釋就可以顯示了
這兒的“測試模塊”的注釋,其實是從SwaggerDocTag類中讀取出來的,並不是控制器本身的注釋。
然后,這只是我個人目前為止發現的最好好用的方法,如果有人有什么其他更好的解決辦法,歡迎大家指教,互相學習~
BTW,這里提一下可能會遇到的問題:如果項目發布之后,或是上線服務器之后,發現注釋又沒了,十有八九是生成的xml文件路徑的問題。可以按照之前的步驟,依次排查,重新修改路徑就可以了。
【20180705】更新顯示控制器注釋方法:
經@陸韋里同學私信指教,現提供另一種swagger展示控制器注釋的方法,思路如下:
其實我們對控制器添加的注釋,已經生成在xml注釋文檔里了(APIHelp.xml),打開xml文檔,如下:
仔細觀察下,其實就能找到它的規律:我們需要的主要數據都在二級節點<members>里,三級節點<member>有一個name屬性,這個name的值凡是以“T:”開頭的表示的都是類,凡是以“M:”開頭的表示的都是函數,其中類里面凡是控制器必然會以“Controller”結尾。
所以我們要寫一個讀取xml的函數,根據這個規則,將注釋提取出來,就可以了。
Stratup.cs里以前地配置不需要改變,只需要重新編輯SwaggerHelp下面的SwaggerDocTag.cs,添加一個GetControllerDesc函數,SwaggerDocTag.cs的完整代碼如下:

using Microsoft.Extensions.PlatformAbstractions; using Swashbuckle.AspNetCore.Swagger; using Swashbuckle.AspNetCore.SwaggerGen; using System.Collections.Generic; using System.IO; using System.Xml; namespace RayPI.SwaggerHelp { /// <summary> /// Swagger注釋幫助類 /// </summary> public class SwaggerDocTag : IDocumentFilter { /// <summary> /// 添加附加注釋 /// </summary> /// <param name="swaggerDoc"></param> /// <param name="context"></param> public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context) { /* swaggerDoc.Tags = new List<Tag> { //添加對應的控制器描述 這個是我好不容易在issues里面翻到的 new Tag { Name = "Admin", Description = "后台" }, new Tag { Name = "Client", Description = "客戶端" }, new Tag { Name = "System", Description = "系統" } }; */ swaggerDoc.Tags = GetControllerDesc(); } /// <summary> /// 從xml注釋中讀取控制器注釋 /// </summary> /// <returns></returns> private List<Tag> GetControllerDesc() { List<Tag> tagList = new List<Tag>(); var basePath = PlatformServices.Default.Application.ApplicationBasePath; var xmlpath = Path.Combine(basePath, "APIHelp.xml"); if (!File.Exists(xmlpath))//檢查xml注釋文件是否存在 return tagList; XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(xmlpath); string memberName = string.Empty;//xml三級節點的name屬性值 string controllerName = string.Empty;//控制器完整名稱 string key = string.Empty;//控制器去Controller名稱 string value = string.Empty;//控制器注釋 foreach (XmlNode node in xmlDoc.SelectNodes("//member"))//循環三級節點member { memberName = node.Attributes["name"].Value; if (memberName.StartsWith("T:"))//T:開頭的代表類 { string[] arrPath = memberName.Split('.'); controllerName = arrPath[arrPath.Length - 1]; if (controllerName.EndsWith("Controller"))//Controller結尾的代表控制器 { XmlNode summaryNode = node.SelectSingleNode("summary");//注釋節點 key = controllerName.Remove(controllerName.Length - "Controller".Length, "Controller".Length); if (summaryNode != null && !string.IsNullOrEmpty(summaryNode.InnerText) && !tagList.Contains(new Tag { Name = key })) { value = summaryNode.InnerText.Trim(); tagList.Add(new Tag { Name = key, Description = value }); } } } } return tagList; } } }
點擊F5運行,控制器的注釋就顯示出來了。
【20180705】再次更新顯示控制器注釋方法:
這次應該是終極解決辦法了,而且這個方法其實swagger已經幫我們集成好了~
其中給swagger添加xml注釋文件的函數叫“IncludeXmlComments”,F12跳轉到定義,摘要是這樣的:
// // 摘要: // Inject human-friendly descriptions for Operations, Parameters and Schemas based // on XML Comment files // // 參數: // filePath: // An abolsute path to the file that contains XML Comments // // includeControllerXmlComments: // Flag to indicate if controller XML comments (i.e. summary) should be used to // assign Tag descriptions. Don't set this flag if you're customizing the default // tag for operations via TagActionsBy. public void IncludeXmlComments(string filePath, bool includeControllerXmlComments = false);
可以看到,函數其實十有兩個參數的,只是第二個參數默認設置了false,而這個參數就是設置是否顯示顯示控制器注釋的。。。
所以只需要更改Startup.cs下ConfigureServices函數中的swagger配置就行了:
c.IncludeXmlComments(apiXmlPath, true);//添加控制器層注釋(true表示顯示控制器注釋)
20180703更新:添加headers授權驗證
3. 為Swagger添加頭部授權驗證功能
當接口添加了授權驗證之后,我們是不能直接調用該接口,一般需要在發起的http請求的headers中添加“令牌"進行驗證。用過Postman的應該知道,Postman是可以手動在headers中添加字段的,下面就要實現swagger添加headers的功能。
這里以JWT授權驗證為例,如果需要了解JWT授權驗證的,可以去該系列的第四篇【從零開始搭建自己的.NET Core Api框架】(四)實戰!帶你半個小時實現JWT授權驗證,有專門介紹。
打開Startup.cs,我們需要在ConfigService函數中添加如下服務:
services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new Info { Version = "v1.1.0", Title = "Ray WebAPI", Description = "框架集合", TermsOfService = "None", Contact = new Swashbuckle.AspNetCore.Swagger.Contact { Name = "RayWang", Email = "2271272653@qq.com", Url = "http://www.cnblogs.com/RayWang" } }); //添加注釋服務
var basePath = PlatformServices.Default.Application.ApplicationBasePath; var xmlPath = Path.Combine(basePath, "APIHelp.xml"); c.IncludeXmlComments(xmlPath); //添加對控制器的標簽(描述)
c.DocumentFilter<SwaggerDocTag>(); //手動高亮 //添加header驗證信息 //c.OperationFilter<SwaggerHeader>();
var security = new Dictionary<string, IEnumerable<string>> { { "Bearer", new string[] { } }, }; c.AddSecurityRequirement(security);//添加一個必須的全局安全信息,和AddSecurityDefinition方法指定的方案名稱要一致,這里是Bearer。
c.AddSecurityDefinition("Bearer", new ApiKeyScheme { Description = "JWT授權(數據將在請求頭中進行傳輸) 參數結構: \"Authorization: Bearer {token}\"", Name = "Authorization",//jwt默認的參數名稱
In = "header",//jwt默認存放Authorization信息的位置(請求頭中)
Type = "apiKey" }); });
完成之后,F5運行,swagger ui頁面就會多出一個按鈕"Authorize",點擊可以跳出token填寫頁面,作用可以去看第四章,這里就不講了
【20180714】更新:設置swagger顯示實體類信息(swagger讀取多個xml注釋文件)
4. 顯示實體類注釋
我們的WebApi接口大部分都是以實體類作為對象來傳輸的,但是swagger如果不設置的話是看不到這些實體類的注釋的。
比如,實體類Student如下:
“添加學生”接口,需要接收一個“Student”類:
這里swagger只是把該實體類的字段一一列出來供測試填寫數據,但是卻看不到注釋。
再比如,“獲取單個學生”接口,調用 后會返回一個學生實體,但是Responses信息中卻只顯示了一個200的狀態碼,而沒有顯示該返回的實體類的信息:
下面,就來解決這個問題:
1)項目生成xml注釋文件
這一步和之前一樣,只是項目要選擇實體類所在項目,而不是控制器層的項目:
這里注意點是,XML文檔文件的路徑最好選擇到控制器層XML注釋文件相同的路徑下,如果生成成功,打開文件夾可以看到生成的xml文件:
2)設置swagger讀取該xml注釋文件
完整的ConfigureServices下swagger配置如下:
services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new Info { Version = "v1.1.0", Title = "Ray WebAPI", Description = "框架集合", TermsOfService = "None", Contact = new Swashbuckle.AspNetCore.Swagger.Contact { Name = "RayWang", Email = "2271272653@qq.com", Url = "http://www.cnblogs.com/RayWang" } }); //添加注釋服務 var basePath = PlatformServices.Default.Application.ApplicationBasePath; var apiXmlPath = Path.Combine(basePath, "APIHelp.xml"); var entityXmlPath = Path.Combine(basePath, "EntityHelp.xml"); c.IncludeXmlComments(apiXmlPath, true);//控制器層注釋(true表示顯示控制器注釋) c.IncludeXmlComments(entityXmlPath); //添加控制器注釋 //c.DocumentFilter<SwaggerDocTag>(); //添加header驗證信息 //c.OperationFilter<SwaggerHeader>(); var security = new Dictionary<string, IEnumerable<string>> { { "Bearer", new string[] { } }, }; c.AddSecurityRequirement(security);//添加一個必須的全局安全信息,和AddSecurityDefinition方法指定的方案名稱要一致,這里是Bearer。 c.AddSecurityDefinition("Bearer", new ApiKeyScheme { Description = "JWT授權(數據將在請求頭中進行傳輸) 參數結構: \"Authorization: Bearer {token}\"", Name = "Authorization",//jwt默認的參數名稱 In = "header",//jwt默認存放Authorization信息的位置(請求頭中) Type = "apiKey" }); });
到這,第一個問題,接受實體類就可以顯示注釋了:
3)控制器的接口函數頭設置標簽
在接口的頭部添加標簽:
[ProducesResponseType(typeof(Student),200)]
表明該接口返回實體類類型。如下圖例:
再次運行項目,查看獲取單個學生接口:
點擊黑框上面“Model”字樣,還可以查看該類的注釋~
另外,swagger還在接口的下方很貼心的生成了一個用於顯示實體Model模塊:
到這,我們的第一章的內容“搭建項目和集成sawgger”就結束了,如果有問題,歡迎留言一起討論,互相學習。
本來想着代碼比較簡單,就不放源碼,但是考慮之后,還是決定上傳一下。正好也定個規矩,這個系列后面每完成一個大的章節之后,都上傳一份源碼。這樣也是給自己一個交代吧。
源碼下載:點擊查看下載地址
下一章的內容是項目架構的搭建和集成SqlSugar