Webapi documentation description-swagger, webapi documentation-swagger

Source: Internet
Author: User

Webapi documentation description-swagger, webapi documentation-swagger

Recently, mvc + webapi is used to separate the front and back ends. APIs are provided to front-end developers in the background. In this process, a problem occurs: How does the background developer provide the interface instruction document to the front-end developer? At first, the developer intends to use the word document for communication, but seldom writes it in actual operations. To solve this problem, I specifically searched for the articles generated by the api documentation in the blog. There are two solutions that caught my attention.1. Microsoft. AspNet. WebApi. HelpPage 2. swagger ")

The first attempt was Microsoft's own solution. Due to the transformation of the project to the webapi, this solution always reported an error, so I switched to the second solution. After more than half of the day, the final effect was as follows:

1. List all API controllers and controller descriptions

2. List actions and descriptions

3. intuitive interface Testing

These goals have been met by the project.

Reading directory

  • Use swagger
  • Localization and problem solving
  • ApiExplorer
  • Summary
Go back to the top and use swagger

1. Create a webapi project Solution

2. reference the swagger nuget package

Swashbuckle and Swagger. Net. UI packages

3. Uninstall the duplicate package Swagger. Net

When Swagger. Net. UI is referenced, the Swagger. Net package is referenced, but the functions of Swagger. Net and Swashbuckle are repeated. So I took the uninstallSwagger. Net

Delete unnecessary SwaggerUI folders

Delete redundant configuration classes SwaggerNet

 4. Add interface comments

After completing the preceding three running projects, you can see that the interface description has been generated. The browsing address is http: // xxx/Swagger. But there is no interface comment. Add the interface comment below

Project properties-> select generate xml document file

Modify the SwaggerConfig File

// C. includeXmlComments (GetXmlCommentsPath (); // sets the xml Path address for the interface description c. includeXmlComments (string. format ("{0}/bin/SwaggerDemo. XML ", System. appDomain. currentDomain. baseDirectory ));
Add comments to the interface. You can see that the parameters and method descriptions go back to the top of the menu and solve the problem.

After the above operations, the required functions have been completed. However, there are several issues that need to be improved.

1. The description on the interface is in Chinese.

2. The controller is not described.

3. Too many interfaces are generated slowly each time

1. Chinese steps

There is such a piece of code in the SwaggerConfig configuration file.

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

The purpose of this Code is to reference the Swashbuckle. Dummy. SwaggerExtensions. testScript1.js file to the page output. You may wonder why the js file path is so strange. That's because Swagger has embedded all the resource files into the dll, and our common resource files are put in the project in the way of content. We can also introduce them to the project as embedded resources.

This is also the reason why I deleted the SwaggerUI folder above, and the page can also be normally displayed. All resource files are packaged into the dll. To verify this statement, use the decompilation tool reflector. To decompile Swashbuckle. Core. dll.

After clarifying the implementation principle, we can now implement localization. Add your own Chinese Language Pack, and convert js. For the implementation logic, see swagger source code.

// C. injectJavaScript (thisAssembly, "Swashbuckle. dummy. swaggerExtensions. testScript1.js "); // path rule, project namespace. folder name. js file name c. injectJavaScript (thisAssembly, "SwaggerDemo. scripts. swaggerui. swagger_lang.js ");
/// <Summary> /// Chinese conversion /// </summary> var SwaggerTranslator = (function () {// periodically checks whether the conversion is made to Chinese, run a maximum of 500 times, that is, 500*50/1000 = 25 s var iexcute = 0, // Chinese Language Pack _ words = {"Warning: Deprecated": "Warning: expired ", "Implementation Notes": "Implementation Notes", "Response Class": "Response Class", "Status": "Status", "Parameters": "Parameter", "Parameter ": "Parameter", "Value": "Value", "Description": "Description", "Parameter Type": "Parameter Type", "Data Type": "Data Type ", "Response Messages ":" Response Message "," HTTP Status Code ":" HTTP Status Code "," Reason ":" Reason "," Response Model ":" Response Model "," Request URL ": "request URL", "Response Body": "Response Body", "Response Code": "Response Code", "Response Headers": "Response Header", "Hide Response ": "Hide response", "Headers": "Header", "Try it out! ":" Give it a try! "," Show/Hide ":" Show/Hide "," List Operations ":" Show Operations "," Expand Operations ":" Show Operations "," Raw ": "original", "can't parse JSON. raw result ":" JSON cannot be parsed. original result "," Model Schema ":" Model architecture "," Model ":" Model "," apply ":" application "," Username ":" Username ", "Password": "Password", "Terms of service": "Terms of service", "Created by": "creator", "See more": "view more: "," Contact the developer ":" Contact developer "," api version ":" api version "," Response Content Type ":" Response Content Type "," fetching resource ":" retrieving resources "," fetching resource list ":" retrieving resource list "," Browse ", "Show Swagger Petstore Example Apis": "Show Swagger Petstore Example Apis", "Can't read from server. it may not have the appropriate access-control-origin settings. ":" cannot be read from the server. Access-control-origin may not be set correctly. "," Please specify the protocol for ":" specify the protocol: "," Can't read swagger JSON from ":" unable to read swagger JSON on ", "Finished Loading Resource Information. rendering Swagger UI ":" loaded resource information. Rendering Swagger UI "," Unable to read api ":" Unable to read api "," from path ":" from path "," Click to set as parameter value ": "Click set parameter", "server returned": "server return"}, // periodically execute conversion _ translator2Cn = function () {if ($ ("# resources_container. resource "). length> 0) {_ tryTranslate ();} if ($ ("# using e "). text () = "Explore" & iexcute <500) {iexcute ++; setTimeout (_ translator2Cn, 50) ;}}, // Set Controller annotation_setcontrollersummary = fun Ction () {$. 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 ). chi Ldren (". heading "). children (". options "). prepend ('<li class = "controller-summary" title = "' + strSummary + '">' + strSummary + '</li> ');}}});} });}, // try to convert English to Chinese _ tryTranslate = function () {$ ('[data-sw-translate]'). each (function () {detail (this).html(_getlangdesc(detail (this).html (); $ (this ). val (_ getLangDesc ($ (this ). val (); $ (this ). attr ('title', _ getLangDesc ($ (this ). attr ('title') ;}}, _ getLangDe SC = function (word) {return _ words [$. trim (word)]! = Undefined? _ Words [$. trim (word)]: word;}; return {Translator: function () {document. title = "API description"; $ ('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 ("interface description "). attr ("href", "/Home/Index"); // Set Controller description _ setControllerSummary (); _ translator2Cn ();}}})(); // execute SwaggerTranslator. translator ();

2. Controller description and interface document Cache

Public class Identifier: ISwaggerProvider {private static ConcurrentDictionary <string, SwaggerDocument> _ cache = new ConcurrentDictionary <string, SwaggerDocument> (); private readonly ISwaggerProvider _ swaggerProvider; public identifier (ISwaggerProvider swaggerProvider) {_ swaggerProvider = swaggerProvider;} public SwaggerDocument GetSwagger (string rootUrl, string apiVersi On) {var cacheKey = string. Format ("{0} _ {1}", rootUrl, apiVersion); SwaggerDocument srcDoc = null; // read 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> /// read the Controller description from the API documentation /// </summary> /// <returns> description of all controllers </returns> public static ConcurrentDictionary <string, string> GetControlle RDesc () {string xmlpath = string. format ("{0}/bin/SwaggerDemo. XML ", System. appDomain. currentDomain. baseDirectory); ConcurrentDictionary <string, string> controllerded8ict = 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 [] arrP Ath; 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:") {// controller arrPath = type. split ('. '); length = arrPath. length; controllerName = arrPath [length-1]; if (controllerName. endsWith ("Controller") {// get the Controller annotation summaryNode = node. selectSingleNode ("summar Y "); string key = controllerName. Remove (controllerName. Length-cCount, cCount); if (summaryNode! = Null &&! String. IsNullOrEmpty (summaryNode. InnerText )&&! Controllerdestcict. ContainsKey (key) {controllerdestcict. TryAdd (key, summaryNode. InnerText. Trim () ;}}} return controllerdestcict ;}}View Code
 c.CustomProvider((defaultProvider) => new CachingSwaggerProvider(defaultProvider)); 

Methods In the js of the Chinese version above_ SetControllerSummaryThe Controller description is set by reading the ControllerDesc attribute, so that the project can use the Interface Description document without any worries.

3. Solution to interface duplication caused by MEF

For the code, seeSwaggerConfig _ solve the MEF repetition problem. csFile

Back to Top ApiExplorer

This article can end here. Some readers want to learn more about Swagger implementation. Here we will give you some simple guidance.

Swagger reads all controllers and actionsIApiExplorerInterface MethodGetApiExplorer, WhereIApiExplorerInSystem. Web. Http.

If you are interested, take a look at the source code of ApiExplorer. cs and useGlobalConfiguration. Configuration. Services. GetApiExplorer (). ApiDescriptionsYou can view information about all the Api interfaces. Swagger exports all the interface information by using this method, and adds the corresponding comments to the interface Description document in combination with the xml document.

We can replace the system-provided ApiExploer service in Global. asax. cs Application_Start and use our own custom service.

   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)); 
If the interface has special services, you can consider implementing custom ApiExplorer, or implement it in GetSwagge of CachingSwaggerProvider. Back to Top Summary

With this convenient interface Description document and Interface Test tool, the frontend and backend separation development is easier to communicate and implement. The test can also be independent of the interface independent test interface, it can be used if necessary. Sample Code used in this article: SwaggerDemo, refer to resource:

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

 

If you believe that reading this blog has some benefits, click 【Recommendation] Button.
If you want to discover my new blog more easily, click "green. Color channel 【Follow me].

If you want to give me more encouragement, please

Because my enthusiasm for writing is inseparable from your support.

Thank you for reading this article. If you are interested in the content of my blog, continue to follow up on my blog.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.