
在前后端分离开发中,作为后端如何给前端提供有效直观的接口文档呢?
没错,就是使用swagger 俗称“丝袜哥”
教程:
一、首先我们建立一个webapi项目,然后引用需要包。swagger需引用下面这2个包
卸载重复包(提示:这里直接卸载是卸载不掉的,这个包是依赖于Swagger.Net.UI这个包的,所以我们要勾选中强制删除,然后再删):
swaggUI这个文件夹也没用,删掉
二、写一个测试用的接口:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net;
- using System.Net.Http;
- using System.Web.Http;
-
- namespace webApiTest.Areas.Test.Controllers
- {
- ///<summary>
- ///测试接口
- ///</summary
- public class TestController : ApiController
- {
- ///<summary>
- ///测试接口
- ///</summary>
- ///<param name="name">姓名</param>
- ///<returns>返回问候语</returns>
- [Route("v1.0/SendVer"), HttpGet]
- public string SayHello(string name)
- {
- return "Hello," + name;
- }
-
- }
- }
默认的路由地址是:http://xxx/Swagger 访问一下已可以到接口描述:
三、现在已经有了接口描述,为了更加直观可视,我们还需重写下路由和进行汉化处理
1、首先加载汉化包:可以到我的百度网盘去下:
链接:https://pan.baidu.com/s/1nCBGIQ1_OWi6Ly8Ta84IzQ
提取码:epxz
下载完成后放到项目Scripts文件夹中去:
有了汉化文件,我们就来加载到项目中去,重写 swaggerConfig.cs文件,打开后发现一堆英文注释,看不球懂,自己翻译了整理下(
只翻译了部分我用到的,看实际情况食用):
- using System.Web.Http;
- using WebActivatorEx;
- using webApiTest;
- using Swashbuckle.Application;
- using System;
- using Swashbuckle.Swagger;
- using System.Xml;
- using System.Collections.Concurrent;
- using System.IO;
- using System.Collections.Generic;
-
- [assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")]
-
- namespace webApiTest
- {
- public class SwaggerConfig
- {
- public static void Register()
- {
- var thisAssembly = typeof(SwaggerConfig).Assembly;
-
- GlobalConfiguration.Configuration
- .EnableSwagger(c =>
- {
- //默认情况下,服务根url推断从请求用于访问文档。然而,可能存在的情况下(如代理和负载均衡环境),这确实notresolve正确。
- //你可以解决这个通过提供您自己的代码来确定根URL。
- //c.RootUrl(req => GetRootUrlFromAppConfig());
-
- //如果Swagger2.0提供的文档不明确,然后计划用于访问文档作为默认值。
- //如果您的API支持多个计划和你想要明确的,您可以使用“方案”选项如下所示。
- //c.Schemes(new[] { "http", "https" });
-
- //使用“SingleApiVersion”来描述一个版本的API。Swagger2.0包含一个“信息”对象持有额外的元数据API。
- //版本和标题是必需的,但是您还可以提供额外的字段SingleApiVersion链接方法。
- c.SingleApiVersion("v1", "");
-
- //如果希望输出Swagger文档正确缩进,请启用“PrettyPrint”选项。
- //c.PrettyPrint();
-
- //如果您的API有多个版本,使用“MultipleApiVersions”而不是“SingleApiVersion”。
- //在这种情况下,您必须提供一个告诉Swagger的行为应该被包括在给定API版本的文档。
- //像“SingleApiVersion”,每次调用“版本”返回一个“信息”构建器可以提供额外的元数据API版本
- //c.MultipleApiVersions(
- // (apiDesc, targetApiVersion) => ResolveVersionSupportByRouteConstraint(apiDesc, targetApiVersion),
- // (vc) =>
- // {
- // vc.Version("v2", "Swashbuckle Dummy API V2");
- // vc.Version("v1", "Swashbuckle Dummy API V1");
- // });
-
- //您可以使用“BasicAuth”、“ApiKey”或“OAuth2”选项来描述API的安全方案。
- //详细信息,请参阅https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md。
- //注意:这些只定义相对应的方案,需要加上一个“安全”属性的文档或操作水平,表明该方案所需的操作。
- //要做到这一点,你需要实现一个自定义IDocumentFilter和/或IOperationFilter根据您特定的授权设置这些属性实现
- //c.BasicAuth("basic")
- // .Description("Basic HTTP Authentication");
- //
- //注意:您还必须在SwaggerUI部分下面配置“EnableApiKeySupport”
- //c.ApiKey("apiKey")
- // .Description("API Key Authentication")
- // .Name("apiKey")
- // .In("header");
- //
- //c.OAuth2("oauth2")
- // .Description("OAuth2 Implicit Grant")
- // .Flow("implicit")
- // .AuthorizationUrl("http://petstore.swagger.wordnik.com/api/oauth/dialog")
- // .TokenUrl("https://tempuri.org/token")
- // .Scopes(scopes =>
- // {
- // scopes.Add("read", "Read access to protected resources");
- // scopes.Add("write", "Write access to protected resources");
- // });
- //这个标志设置为省略过时的属性描述的任何行动
- //c.IgnoreObsoleteActions();
-
- //每个操作被分配一个或多个标签,然后用消费者出于各种原因。例如,swagger-ui组操作根据每个操作的第一个标记。
- //默认情况下,这将是控制器的名字,但您可以使用“GroupActionsBy”选项与任何值覆盖。
- //c.GroupActionsBy(apiDesc => apiDesc.HttpMethod.ToString());
-
- //你也可以指定一个自定义的排序顺序组(定义为“GroupActionsBy”)规定的顺序列出操作。
- //例如,如果默认分组(控制器名称)和您指定一个下行字母排序,然后从aProductsController行动将从CustomersController上市之前。
- //这是通常用于定制swagger -ui分组的顺序。
- //c.OrderActionGroupsBy(new DescendingAlphabeticComparer());
-
- //如果您用它来注释控制器和API类型
- //Xml注释(http://msdn.microsoft.com/en-us/library/b2s063f7(v=vs.110).aspx),可以合并
- //将这些注释添加到生成的文档和UI中。您可以通过提供到one或更多的Xml注释文件。
- //c.IncludeXmlComments(GetXmlCommentsPath());
-
- //Swashbuckle尽力为各种类型生成与Swagger兼容的JSON模式在您的API中公开。然而,有时可能需要对输出进行更多的控制。
- //这是通过“MapType”和“SchemaFilter”选项支持的:使用“MapType”选项覆盖特定类型的模式生成。
- //需要注意的是,对于任何适用的操作,生成的模式都将放在“内联”位置。
- //虽然Swagger 2.0支持“所有”模式类型的内联定义,但是Swagger -ui工具不支持。
- //它期望“复杂”模式被单独定义和引用。出于这个原因,你只应该当得到的模式是基本类型或数组类型时,
- //使用“MapType”选项。如果你需要改变复杂模式,使用模式过滤器。
- //c.MapType<ProductType>(() => new Schema { type = "integer", format = "int32" });
-
- //这个是webApiTest接口这个项目的XML文档
- c.IncludeXmlComments(string.Format("{0}/bin/webApiTest.XML", AppDomain.CurrentDomain.BaseDirectory));
- //这个是实体类的XML文档,因为在实际中我们需要调用实体类库,我这里只是个简单的例子,所以没有使用到这个
- //c.IncludeXmlComments(string.Format("{0}/bin/Model.XML", AppDomain.CurrentDomain.BaseDirectory));
-
- c.CustomProvider((defaultProvider) => new CachingSwaggerProvider(defaultProvider));
- })
- //重新定义路径及汉化文件
- .EnableSwaggerUi("apis/{*assetPath}", c =>
- {
- //这里代表你汉化文件的存放路径,这里有一个坑,当解决方案有'.'这种字符的时候会给识别为路径,且没办法转义,
- //这个坑的我好惨,比如解决方案改为webapi.test 就要出事了
- //路径规则,项目命名空间.文件夹名称.js文件名称
- c.InjectStylesheet(thisAssembly, "webApiTest.Scripts.custom.css");
- c.InjectJavaScript(thisAssembly, "webApiTest.Scripts.swagger_lang.js");
- //c.CustomAsset("index", thisAssembly, "NineTeam.API.Swagger.index.html");
- });
- }
-
- ///<summary>
- ///Swagger汉化
- ///</summary>
- 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\webApiTest.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;
- }
- }
- }
- }
2、认真看了代码的童鞋可能已经发现,swagger的原理实际上就是读取你在编写代码时编写的注释,所以你的注释得详细,那么如何生成XML文件?
右键项目属性》生成》:
重新生成下项目,可以看到bin文件夹下已生成xml文件,打开看一下是什么东西:
可以到在末尾有我们刚才接口的注释。嗯~感觉是搭建的差不多了,跑一下:
汉化怎么没成???但是文档的注释是加载进来了。重新检查下路径发现也是对的?
怎么办呢,别急,只需要改下这两个文件的生产操作:
右键这两个文件》属性》生成操作》改为嵌入式:
OK!再试一下:
嗯~这就美观多了。
总结:实践是检验真理的唯一标准!


饰心
WebApiTestClient也是一种方式,http://www.cnblogs.com/landeanfen/p/5210356.html
剑轩
mark,后面看![[给力]](http://www.tnblog.net/content/static/layui/images/face/63.gif)