http://www.68idc.cn/help/makewebs/qitaasks/20160621620667.html
两种方案 一、Swagger 配置 web Api 接口文档美化 二、通过NodeJS 发布Swagger UI 配置api 文档 先说一下简单的 Swagger 配置 web Api Swagger-UI 本身只提供在线测试功能,要集成它还需要告诉它本项目提供的各种服务和参数信息。
两种方案
一、Swagger 配置 web Api 接口文档美化
二、通过NodeJS 发布Swagger UI 配置api 文档
先说一下简单的 Swagger 配置 web Api
Swagger-UI本身只提供在线测试功能,要集成它还需要告诉它本项目提供的各种服务和参数信息。这里就需要一些工作量了,不过好在许多第三方库已经给我们完成了这一工作。我这里用的是Swashbuckle,使用它也比较简单,直接使用Nuget添加其程序包即可:
1、初始化包 PM> Install-Package Swashbuckle
增加该程序包时,它本身会把自己相应的一些注册的代码添加到项目中,虽然我们可以不太关心这些操作,但有的时候还是需要修改一些相关的配置的。
2、初始化包后App_Start会添加 ,SwaggerConfig 代码如下:
using System.Web.Http; using WebActivatorEx; using WebApp; using Swashbuckle.Application; [assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")] namespace WebApp { public class SwaggerConfig { public static void Register() { var thisAssembly = typeof(SwaggerConfig).Assembly; GlobalConfiguration.Configuration .EnableSwagger(c => { c.SingleApiVersion("v1", "WebApp"); }) .EnableSwaggerUi(c => { GetXmlCommentsPath(); }); } private static string GetXmlCommentsPath() { return $@"{System.AppDomain.CurrentDomain.BaseDirectory}inWebApi.XML"; } } }
3、集成XML注释
api 应用 ->右键->属性->生成->输出-配置XML
4、运行程序 地址栏请求:http://localhost:5746/swagger/ 逼格很高啊
到此第一种方法完成
开始改造第一种方法 删除SwaggerConfig ,修改Startup 代码如下:
public partial class Startup { public void Configuration(IAppBuilder app) { ConfigureAuth(app); HttpConfiguration config = new HttpConfiguration(); WebApiConfig.Register(config); config.EnableSwagger(c => { c.SingleApiVersion("v1", "WebAPI"); c.IncludeXmlComments(GetXmlCommentsPath()); c.ResolveConflictingActions(x => x.First()); }).EnableSwaggerUi(); app.UseWebApi(config); } private static string GetXmlCommentsPath() { return $@"{System.AppDomain.CurrentDomain.BaseDirectory}inWebApi.XML"; }
会有这个问题 :
解决方法如下:
you will need to import the Microsoft ASP.NET Web API 2 OWIN Self-Host Nuget package.
第一种方法改造完成,下面学习SwaggerUI 及Swagger Edit ,需要用到NodeJS ,下面是在网上找的配置方案,真的感谢
交流成本
前言
- swagger ui是一个API在线文档生成和测试的利器,目前发现最好用的。
- 为什么好用?Demo 传送门
- 支持API自动生成同步的在线文档
- 这些文档可用于项目内部API审核
- 方便测试人员了解API
- 这些文档可作为客户产品文档的一部分进行发布
- 支持API规范生成代码,生成的客户端和服务器端骨架代码可以加速开发和测试速度
- 支持API自动生成同步的在线文档
总结一句话就是好用,逼格高。下面我将总结一下如何快速在本地搭建一个基于Node和Swagger UI的 API 的文档工具
环境搭建
- 下载Swagger UI(也可以直接下载 zip 文件)
git clone https://github.com/swagger-api/swagger-ui.git
- 安装 express
- 创建一个空文件夹node_app
mkdir node_app
- 初始化 node ,创建package.json文件()
? ~ ? >cd node_ap ? ~/node_app ? >npm init // 下面的看你心情填写 name: (node_app) node_app version: (1.0.0) description: entry point: (index.js) test command: git repository: keywords: author: license: (ISC)
- 安装 express
? ~/node_app git:(master) ? >npm install express --save
- 创建 index.js ,手动创建就可以 vim不起作用 ,具体没理解啊
~/node_app git:(master) ? >vim index.js
- 把下面代码贴如 index.js 中
var express = require('express'); var app = express(); app.get('/', function (req, res) { res.send('Hello World!'); }); app.listen(3000, function () { console.log('Example app listening on port 3000!'); });
- 在 node_app 中创建空目录 public
? ~/node_app git:(master) ? >mkdir public ? ~/node_app git:(master) ? >cd public
修改路由
? ~/node_app/public git:(master) ? >vim ../index.js //在文件第三行插入下面这句话 app.use('/static', express.static('public'));
把下载好的Swagger UI 文件中dist 目录下的文件全部复制到 public 文件夹下。
开启
node
<span style="font-size:18px;color:#cc0000;"> ~/node_app git:(master) ? >node index.js</span>
- 打开浏览器,输入http://localhost:3000/static/index.html
到此为止,你已经把官方的 demo 在本地配置好了。当然你也可以吧这个搭建在服务器上
编写文档并发布
- 使用Swagger Editor编写 API 文档
- Swagger Editor 上的是基于 yaml 的语法,但是不用害怕,看着官方的 demo 看个10分钟就会了。
- 导出 test.json 文档
- 把 test.json 放到 node_app/public 目录下。
- 利用编辑器修改
url = "http://petstore.swagger.io/v2/swagger.json";
为url = "/static/test.json";
- 重启 node 服务,浏览器中打开
http://localhost:3000/static/index.html
就是你自己写的 api 文档了
效果图
到此效果出来了,还没有完 ,我配置的是 Web Api 和MVC
test.json 代码如下:做一下概要的说明
{ "swagger": "2.0", "info": { "title": "Uber API", "description": "Move your app forward with the Uber API", "version": "1.0.0" }, "host": "115.29.161.201:8077/", "schemes": [ "http" ], "basePath": "/api", "produces": [ "application/json" ], "paths": { "/products": { "get": { "summary": "Product Types", "description": "The Products endpoint returns information about the *Uber* products offered at a given location. The response includes the display name and other details about each product, and lists the products in the proper display order. ", "parameters": [ { "name": "latitude", "in": "query", "description": "Latitude component of location.", "required": true, "type": "number", "format": "double" }, { "name": "longitude", "in": "query", "description": "Longitude component of location.", "required": true, "type": "number", "format": "double" } ], "tags": [ "Products" ], "responses": { "200": { "description": "An array of products", "schema": { "type": "array", "items": { "$ref": "#/definitions/Product" } } }, "default": { "description": "Unexpected error", "schema": { "$ref": "#/definitions/Error" } } } } }, "/estimates/price": { "get": { "summary": "Price Estimates", "description": "The Price Estimates endpoint returns an estimated price range for each product offered at a given location. The price estimate is provided as a formatted string with the full price range and the localized currency symbol.<br><br>The response also includes low and high estimates, and the [ISO 4217](http://en.wikipedia.org/wiki/ISO_4217) currency code for situations requiring currency conversion. When surge is active for a particular product, its surge_multiplier will be greater than 1, but the price estimate already factors in this multiplier. ", "parameters": [ { "name": "start_latitude", "in": "query", "description": "Latitude component of start location.", "required": true, "type": "number", "format": "double" }, { "name": "start_longitude", "in": "query", "description": "Longitude component of start location.", "required": true, "type": "number", "format": "double" }, { "name": "end_latitude", "in": "query", "description": "Latitude component of end location.", "required": true, "type": "number", "format": "double" }, { "name": "end_longitude", "in": "query", "description": "Longitude component of end location.", "required": true, "type": "number", "format": "double" } ], "tags": [ "Estimates" ], "responses": { "200": { "description": "An array of price estimates by product", "schema": { "type": "array", "items": { "$ref": "#/definitions/PriceEstimate" } } }, "default": { "description": "Unexpected error", "schema": { "$ref": "#/definitions/Error" } } } } }, "/estimates/time": { "get": { "summary": "Time Estimates", "description": "The Time Estimates endpoint returns ETAs for all products offered at a given location, with the responses expressed as integers in seconds. We recommend that this endpoint be called every minute to provide the most accurate, up-to-date ETAs.", "parameters": [ { "name": "start_latitude", "in": "query", "description": "Latitude component of start location.", "required": true, "type": "number", "format": "double" }, { "name": "start_longitude", "in": "query", "description": "Longitude component of start location.", "required": true, "type": "number", "format": "double" }, { "name": "customer_uuid", "in": "query", "type": "string", "format": "uuid", "description": "Unique customer identifier to be used for experience customization." }, { "name": "product_id", "in": "query", "type": "string", "description": "Unique identifier representing a specific product for a given latitude & longitude." } ], "tags": [ "Estimates" ], "responses": { "200": { "description": "An array of products", "schema": { "type": "array", "items": { "$ref": "#/definitions/Product" } } }, "default": { "description": "Unexpected error", "schema": { "$ref": "#/definitions/Error" } } } } }, "/me": { "get": { "summary": "User Profile", "description": "The User Profile endpoint returns information about the Uber user that has authorized with the application.", "tags": [ "User" ], "responses": { "200": { "description": "Profile information for a user", "schema": { "$ref": "#/definitions/Profile" } }, "default": { "description": "Unexpected error", "schema": { "$ref": "#/definitions/Error" } } } } }, "/Values/Get/": { "get": { "summary": "Values Profile", "description": "自己测试", "parameters": [ { "name": "id", "in": "query", "description": "Latitude component of start location.", "required": true, "type": "number", "format": "int32" }], "tags": [ "Values" ], "responses": { "200": { "description": "值得概要信息", "schema": { "$ref": "#/definitions/valuesget" } }, "default": { "description": "意外错误", "schema": { "$ref": "#/definitions/Error" } } } } }, "/history": { "get": { "summary": "User Activity", "description": "The User Activity endpoint returns data about a user's lifetime activity with Uber. The response will include pickup locations and times, dropoff locations and times, the distance of past requests, and information about which products were requested.<br><br>The history array in the response will have a maximum length based on the limit parameter. The response value count may exceed limit, therefore subsequent API requests may be necessary.", "parameters": [ { "name": "offset", "in": "query", "type": "integer", "format": "int32", "description": "Offset the list of returned results by this amount. Default is zero." }, { "name": "limit", "in": "query", "type": "integer", "format": "int32", "description": "Number of items to retrieve. Default is 5, maximum is 100." } ], "tags": [ "User" ], "responses": { "200": { "description": "History information for the given user", "schema": { "$ref": "#/definitions/Activities" } }, "default": { "description": "Unexpected error", "schema": { "$ref": "#/definitions/Error" } } } } } }, "definitions": { "Product": { "type": "object", "properties": { "product_id": { "type": "string", "description": "Unique identifier representing a specific product for a given latitude & longitude. For example, uberX in San Francisco will have a different product_id than uberX in Los Angeles." }, "description": { "type": "string", "description": "Description of product." }, "display_name": { "type": "string", "description": "Display name of product." }, "capacity": { "type": "string", "description": "Capacity of product. For example, 4 people." }, "image": { "type": "string", "description": "Image URL representing the product." } } }, "PriceEstimate": { "type": "object", "properties": { "product_id": { "type": "string", "description": "Unique identifier representing a specific product for a given latitude & longitude. For example, uberX in San Francisco will have a different product_id than uberX in Los Angeles" }, "currency_code": { "type": "string", "description": "[ISO 4217](http://en.wikipedia.org/wiki/ISO_4217) currency code." }, "display_name": { "type": "string", "description": "Display name of product." }, "estimate": { "type": "string", "description": "Formatted string of estimate in local currency of the start location. Estimate could be a range, a single number (flat rate) or "Metered" for TAXI." }, "low_estimate": { "type": "number", "description": "Lower bound of the estimated price." }, "high_estimate": { "type": "number", "description": "Upper bound of the estimated price." }, "surge_multiplier": { "type": "number", "description": "Expected surge multiplier. Surge is active if surge_multiplier is greater than 1. Price estimate already factors in the surge multiplier." } } }, "Profile": { "type": "object", "properties": { "first_name": { "type": "string", "description": "First name of the Uber user." }, "last_name": { "type": "string", "description": "Last name of the Uber user." }, "email": { "type": "string", "description": "Email address of the Uber user" }, "picture": { "type": "string", "description": "Image URL of the Uber user." }, "promo_code": { "type": "string", "description": "Promo code of the Uber user." } } }, "Activity": { "type": "object", "properties": { "uuid": { "type": "string", "description": "Unique identifier for the activity" } } }, "valuesget": { "type": "object", "properties": { "Vanme": { "type": "string", "description": "名字" } } }, "Activities": { "type": "object", "properties": { "offset": { "type": "integer", "format": "int32", "description": "Position in pagination." }, "limit": { "type": "integer", "format": "int32", "description": "Number of items to retrieve (100 max)." }, "count": { "type": "integer", "format": "int32", "description": "Total number of items available." }, "history": { "type": "array", "items": { "$ref": "#/definitions/Activity" } } } }, "Error": { "type": "object", "properties": { "code": { "type": "integer", "format": "int32" }, "message": { "type": "string" }, "fields": { "type": "string" } } } } }
host:配置程序发布地址
schemes :请求方式 http 或者https
tags:页签名称
其他的看个10分钟作用的基本就明白了
我请求web api 遇到了一个跨域的问题 ,永远显示 no content ,没有response
F12 看了一下
解决办法修改web.config
<system.webServer> <httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origin" value="*" /> <add name="Access-Control-Allow-Headers" value="Content-Type" /> <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" /> </customHeaders> </httpProtocol> <handlers> <remove name="ExtensionlessUrlHandler-Integrated-4.0" /> <remove name="OPTIONSVerbHandler" /> <remove name="TRACEVerbHandler" /> <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /> </handlers> </system.webServer>
还不行的话检查一下api 是否有设置了特性 ,网上查了一下,还要在api文件中添加如下方法
//public string Options() //{ // return null; // HTTP 200 response with empty body //}
我没有添加也成功了