日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

webapi文档描述-swagger

發布時間:2023/12/10 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 webapi文档描述-swagger 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  最近做的項目使用mvc+webapi,采取前后端分離的方式,后臺提供API接口給前端開發人員。這個過程中遇到一個問題后臺開發人員怎么提供接口說明文檔給前端開發人員,最初打算使用word文檔方式進行交流,實際操作中卻很少動手去寫。為了解決這個問題,特意在博客園中搜索了一下api接口文檔生成的文章,引起我注意的有兩種方案。1.微軟自帶的Microsoft.AspNet.WebApi.HelpPage ?2.swagger(我比較喜歡戲稱為“絲襪哥”)

? ? ? 最先嘗試的是微軟自帶的方案,由于項目對webapi了一定改造導致使用該方案時一直報錯,于是轉向了第二種方案,經過大半天大搗鼓,最終效果如下

1.列出所有API控制器和控制器描述

2.列出action和描述

3.直觀的接口測試

達到這幾點目標,已經滿足項目使用。

閱讀目錄

  • 使用swagger
  • 漢化及問題解決
  • ApiExplorer思路拓展
  • 總結
回到頂部

使用swagger

  1.創建webapi項目解決方案

  2.引用swagger nuget包

  Swashbuckle和Swagger.Net.UI兩個包

  3.卸載重復包Swagger.Net

  引用Swagger.Net.UI時會引用Swagger.Net這個包,但是Swagger.Net的功能和Swashbuckle重復了。所以我采取了卸載Swagger.Net

?刪除多余的SwaggerUI文件夾

刪除多余的配置類SwaggerNet

?4.添加接口注釋

完成上面三部運行項目,可以看到接口描述已經生成,瀏覽地址http://xxx/Swagger。但是沒有接口的注釋,下面添加接口注釋

?項目屬性->勾選生成xml文檔文件

修改SwaggerConfig文件

//c.IncludeXmlComments(GetXmlCommentsPath());//設置接口描述xml路徑地址c.IncludeXmlComments(string.Format("{0}/bin/SwaggerDemo.XML", System.AppDomain.CurrentDomain.BaseDirectory)); 給接口添加注釋,即可看到參數及方法描述了 回到頂部

漢化及問題解決

經過上面的操作,已經完成了所需功能。但是還有幾點問題需要完善

? ? ?1.界面的說明都是英文的需要進行漢化

? ? ?2.控制器沒有描述

? ? ?3.接口過多每次生成速度比較慢

1.漢化步驟

在SwaggerConfig配置文件中有這么一段代碼

.EnableSwaggerUi(c =>{
//c.InjectJavaScript(thisAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testScript1.js")
});

這段代碼的作用是向頁面輸出引用Swashbuckle.Dummy.SwaggerExtensions.testScript1.js文件,或許會疑問js文件路徑為什么這么奇怪。那是因為Swagger將資源文件都嵌入到dll中了,我們常用的資源文件都是以內容的方式放在項目中的,我們也可以以嵌入的資源方式引入到項目中

這也是上面我將SwaggerUI文件夾刪除,頁面也能正常出來的原因。資源文件都被打包到dll中了,為了驗證這個說法,使用反編譯工具reflector。來反編譯一下Swashbuckle.Core.dll

弄清楚了實現原理,現在來實現漢化。添加自己的中文語言包,和轉換js,實現邏輯參考swagger源碼。

  //c.InjectJavaScript(thisAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testScript1.js");   //路徑規則,項目命名空間.文件夾名稱.js文件名稱c.InjectJavaScript(thisAssembly, "SwaggerDemo.Scripts.swaggerui.swagger_lang.js"); /// <summary> /// 中文轉換 /// </summary> var SwaggerTranslator = (function () {//定時執行檢測是否轉換成中文,最多執行500次 即500*50/1000=25svar iexcute = 0,//中文語言包_words = {"Warning: Deprecated": "警告:已過時","Implementation Notes": "實現備注","Response Class": "響應類","Status": "狀態","Parameters": "參數","Parameter": "參數","Value": "值","Description": "描述","Parameter Type": "參數類型","Data Type": "數據類型","Response Messages": "響應消息","HTTP Status Code": "HTTP狀態碼","Reason": "原因","Response Model": "響應模型","Request URL": "請求URL","Response Body": "響應體","Response Code": "響應碼","Response Headers": "響應頭","Hide Response": "隱藏響應","Headers": "頭","Try it out!": "試一下!","Show/Hide": "顯示/隱藏","List Operations": "顯示操作","Expand Operations": "展開操作","Raw": "原始","can't parse JSON. Raw result": "無法解析JSON. 原始結果","Model Schema": "模型架構","Model": "模型","apply": "應用","Username": "用戶名","Password": "密碼","Terms of service": "服務條款","Created by": "創建者","See more at": "查看更多:","Contact the developer": "聯系開發者","api version": "api版本","Response Content Type": "響應Content Type","fetching resource": "正在獲取資源","fetching resource list": "正在獲取資源列表","Explore": "瀏覽","Show Swagger Petstore Example Apis": "顯示 Swagger Petstore 示例 Apis","Can't read from server. It may not have the appropriate access-control-origin settings.": "無法從服務器讀取。可能沒有正確設置access-control-origin。","Please specify the protocol for": "請指定協議:","Can't read swagger JSON from": "無法讀取swagger JSON于","Finished Loading Resource Information. Rendering Swagger UI": "已加載資源信息。正在渲染Swagger UI","Unable to read api": "無法讀取api","from path": "從路徑","Click to set as parameter value": "點擊設置參數","server returned": "服務器返回"},//定時執行轉換_translator2Cn = function () {if ($("#resources_container .resource").length > 0) {_tryTranslate();}if ($("#explore").text() == "Explore" && iexcute < 500) {iexcute++;setTimeout(_translator2Cn, 50);}},//設置控制器注釋_setControllerSummary = function () {$.ajax({type: "get",async: true,url: $("#input_baseUrl").val(),dataType: "json",success: function (data) {var summaryDict = data.ControllerDesc;var id, controllerName, strSummary;$("#resources_container .resource").each(function (i, item) {id = $(item).attr("id");if (id) {controllerName = id.substring(9);strSummary = summaryDict[controllerName];if (strSummary) { $(item).children(".heading").children(".options").prepend('<li class="controller-summary" title="' + strSummary + '">' + strSummary + '</li>');}}});}});},//嘗試將英文轉換成中文_tryTranslate = function () {$('[data-sw-translate]').each(function () {$(this).html(_getLangDesc($(this).html()));$(this).val(_getLangDesc($(this).val()));$(this).attr('title', _getLangDesc($(this).attr('title')));});},_getLangDesc = function (word) {return _words[$.trim(word)] !== undefined ? _words[$.trim(word)] : word;};return {Translator: function () {document.title = "API描述文檔";$('body').append('<style type="text/css">.controller-summary{color:#10a54a !important;word-break:keep-all;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:250px;text-align:right;cursor:default;} </style>');$("#logo").html("接口描述").attr("href", "/Home/Index");//設置控制器描述 _setControllerSummary();_translator2Cn(); }} })(); //執行轉換 SwaggerTranslator.Translator();

2.控制器描述和接口文檔緩存

public class CachingSwaggerProvider : ISwaggerProvider{private static ConcurrentDictionary<string, SwaggerDocument> _cache =new ConcurrentDictionary<string, SwaggerDocument>();private readonly ISwaggerProvider _swaggerProvider;public CachingSwaggerProvider(ISwaggerProvider swaggerProvider){_swaggerProvider = swaggerProvider;}public SwaggerDocument GetSwagger(string rootUrl, string apiVersion){var cacheKey = string.Format("{0}_{1}", rootUrl, apiVersion);SwaggerDocument srcDoc = null;//只讀取一次if (!_cache.TryGetValue(cacheKey, out srcDoc)){srcDoc = _swaggerProvider.GetSwagger(rootUrl, apiVersion);srcDoc.vendorExtensions = new Dictionary<string, object> { { "ControllerDesc", GetControllerDesc() } };_cache.TryAdd(cacheKey, srcDoc);}return srcDoc;}/// <summary>/// 從API文檔中讀取控制器描述/// </summary>/// <returns>所有控制器描述</returns>public static ConcurrentDictionary<string, string> GetControllerDesc(){string xmlpath = string.Format("{0}/bin/SwaggerDemo.XML", System.AppDomain.CurrentDomain.BaseDirectory);ConcurrentDictionary<string, string> controllerDescDict = new ConcurrentDictionary<string, string>();if (File.Exists(xmlpath)){XmlDocument xmldoc = new XmlDocument();xmldoc.Load(xmlpath);string type = string.Empty, path = string.Empty, controllerName = string.Empty;string[] arrPath;int length = -1, cCount = "Controller".Length;XmlNode summaryNode = null;foreach (XmlNode node in xmldoc.SelectNodes("//member")){type = node.Attributes["name"].Value;if (type.StartsWith("T:")){//控制器arrPath = type.Split('.');length = arrPath.Length;controllerName = arrPath[length - 1];if (controllerName.EndsWith("Controller")){//獲取控制器注釋summaryNode = node.SelectSingleNode("summary");string key = controllerName.Remove(controllerName.Length - cCount, cCount);if (summaryNode != null && !string.IsNullOrEmpty(summaryNode.InnerText) && !controllerDescDict.ContainsKey(key)){controllerDescDict.TryAdd(key, summaryNode.InnerText.Trim());}}}}}return controllerDescDict;}} View Code c.CustomProvider((defaultProvider) => new CachingSwaggerProvider(defaultProvider));?

上面漢化的js中的方法_setControllerSummary通過讀取ControllerDesc屬性設置了控制器的描述,至此項目可以無憂使用接口描述文檔。

3.使用了MEF導致接口重復問題解決方案

代碼請參照項目中的SwaggerConfig_解決MEF重復問題.cs文件

回到頂部

ApiExplorer思路拓展

該篇到這里可以結束了,考慮到有的讀者想了解更多Swagger的實現內幕,這里再做一下簡單的思路引導。

Swagger的讀取所有Controller和Action借助于IApiExplorer接口的方法GetApiExplorer,其中IApiExplorerSystem.Web.Http中。

有興趣的可以看一下ApiExplorer.cs源碼,使用GlobalConfiguration.Configuration.Services.GetApiExplorer().ApiDescriptions 即可查看所有Api接口地址相關信息,Swagger正是借助于該方法導出所有接口信息,在結合xml文檔添加相應注釋文成接口描述文檔的。

我們可以在Global.asax.cs ?Application_Start中替換掉系統自帶的ApiExploer服務,使用我們自己自定義的服務。

  public class CustomApiExplorer : ApiExplorer{public CustomApiExplorer(HttpConfiguration configuration) : base(configuration){}public override bool ShouldExploreAction(string actionVariableValue, HttpActionDescriptor actionDescriptor, IHttpRoute route){return base.ShouldExploreAction(actionVariableValue, actionDescriptor, route);}public override bool ShouldExploreController(string controllerVariableValue, HttpControllerDescriptor controllerDescriptor, IHttpRoute route){return base.ShouldExploreController(controllerVariableValue, controllerDescriptor, route);}} GlobalConfiguration.Configuration.Services.Replace(typeof(IApiExplorer), new CustomApiExplorer(GlobalConfiguration.Configuration));? 接口有特有業務的可以考慮自定義ApiExplorer進行實現,或者在CachingSwaggerProvider中GetSwagge中進行實現。 回到頂部

總結

  有了這么方便的接口描述文檔和接口測試工具,讓前后端分離開發更加便于溝通和落地了,測試也可以不依賴于界面單獨測試接口,有需要的可以使用起來。本篇所使用示例代碼下載地址:SwaggerDemo,參考資源:

? ? ? Swashbuckle:https://github.com/domaindrivendev/Swashbuckle

?

如果,您認為閱讀這篇博客讓您有些收獲,不妨點擊一下右下角的【推薦】按鈕。
如果,您希望更容易地發現我的新博客,不妨點擊一下綠。色通道的【關注我】。

如果,想給予我更多的鼓勵,求打

因為,我的寫作熱情也離不開您的肯定支持。

感謝您的閱讀,如果您對我的博客所講述的內容有興趣,請繼續關注我的后續博客,我是焰尾迭 。

轉載于:https://www.cnblogs.com/yanweidie/p/5709113.html

總結

以上是生活随笔為你收集整理的webapi文档描述-swagger的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。