在ABP模板项目中,通过SwaggerUI可以为我们的WebApi生成动态的可交互接口文档页面,从而可以很方便的测试调用我们的WebApi接口。

一、集成Swagger

右键项目YoYo.Web,打开NuGet程序包管理器,添加Swashbuckle。

其中包含了程序和UI,安装后在App_Start文件夹下生成SwaggerConfig.cs。



完成这一步,Swagger已经集成完毕。

可以访问http://localhost:XXXX/swagger/ui/index。



如果出现异常,可以先尝试取消注释SwaggerConfig.cs中的此行代码

c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());

二、增强配置

包括从XML接口文档读取,修改规则,汉化

swaggerconfig.cs修改如下:

using System.Web.Http;
using WebActivatorEx;
using YoYo.Web;
using Swashbuckle.Application;
using System.Linq;
using System.IO; [assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")] namespace YoYo.Web
{
public class SwaggerConfig
{
public static void Register()
{
var thisAssembly = typeof(SwaggerConfig).Assembly; GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.SingleApiVersion("v1", "YoYo");
c.IncludeXmlComments(GetXmlCommentsPath("WebApi"));
c.IncludeXmlComments(GetXmlCommentsPath("Application"));
c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
c.CustomProvider((defaultProvider) => new CachingSwaggerProvider(defaultProvider));
})
.EnableSwaggerUi(c =>
{
string resourceName = thisAssembly.FullName.Substring(0, thisAssembly.FullName.IndexOf(",")) + ".Scripts.swaggerui.swagger_lang.js";
c.InjectJavaScript(thisAssembly, resourceName);
});
}
private static string GetXmlCommentsPath(string subName)
{
return Directory.GetFiles(System.AppDomain.CurrentDomain.BaseDirectory + "bin\\").FirstOrDefault(n => n.ToLower().EndsWith(subName.ToLower() + ".xml"));
}
}
}

在App_Start下新增文件CachingSwaggerProvider.cs

using Microsoft.Ajax.Utilities;
using Swashbuckle.Swagger;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Xml; namespace YoYo.Web
{
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.paths.ForEach(n =>
{
SetOperation(n.Value.delete);
SetOperation(n.Value.get);
SetOperation(n.Value.head);
SetOperation(n.Value.options);
SetOperation(n.Value.patch);
SetOperation(n.Value.post);
SetOperation(n.Value.put);
}); srcDoc.vendorExtensions = new Dictionary<string, object> { { "ControllerDesc", GetControllerDesc() } };
_cache.TryAdd(cacheKey, srcDoc);
}
return srcDoc;
} private void SetOperation(Operation operation)
{
if (operation != null)
{
operation.tags[0] = operation.tags[0].Split('_').Last(); if (operation.parameters == null)
{
operation.parameters = new List<Parameter>();
}
operation.parameters.Insert(0, new Parameter()
{
@in = "header",
name = "authorization",
description = "token",
type = "string"
});
operation.parameters.Insert(0, new Parameter()
{
@in = "header",
name = "X-XSRF-TOKEN",
description = "XSRF-TOKEN",
type = "string"
}); if (operation.operationId.StartsWith("Import"))
{
operation.parameters.Add(new Parameter()
{
@in = "formData",
name = "",
type = "file"
});
if (operation.consumes == null)
{
operation.consumes = new List<string>();
}
operation.consumes.Add("multipart/form-data");
}
}
} /// <summary>
/// 从API文档中读取控制器描述
/// </summary>
/// <returns>所有控制器描述</returns>
public static ConcurrentDictionary<string, string> GetControllerDesc()
{
ConcurrentDictionary<string, string> controllerDescDict = new ConcurrentDictionary<string, string>(); GetControllerDescByProject("WebApi", "Controller", controllerDescDict);
GetControllerDescByProject("Application", "AppService", controllerDescDict); return controllerDescDict;
} private static void GetControllerDescByProject(string subName, string endsWith, ConcurrentDictionary<string, string> controllerDescDict)
{
string xmlpath = Directory.GetFiles(System.AppDomain.CurrentDomain.BaseDirectory + "bin\\").FirstOrDefault(n => n.ToLower().EndsWith(subName.ToLower() + ".xml"));
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 = endsWith.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(endsWith))
{
//获取控制器注释
summaryNode = node.SelectSingleNode("summary");
string key = controllerName.StartsWith("I") ?
controllerName.Substring(1, 1).ToLower() + controllerName.Substring(2, controllerName.Length - 2 - cCount) :
controllerName.Remove(controllerName.Length - cCount, cCount);
if (summaryNode != null && !string.IsNullOrEmpty(summaryNode.InnerText) && !controllerDescDict.ContainsKey(key))
{
controllerDescDict.TryAdd(key, summaryNode.InnerText.Trim());
}
}
}
}
}
}
}
}

swagger_lang.js,需要将文件属性的“生成操作”设置为“嵌入的资源”,代码如下

///    <summary>
/// 中文转换
/// </summary>
var SwaggerTranslator = (function () {
//定时执行检测是否转换成中文,最多执行500次 即500*50/1000=25s
var 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(); function setCookie(c_name, value, expiredays) {
var exdate = new Date()
exdate.setDate(exdate.getDate() + expiredays)
document.cookie = c_name + "=" + escape(value) +
((expiredays == null) ? "" : ";expires=" + exdate.toGMTString())
} function getCookie(c_name) {
if (document.cookie.length > 0) {
c_start = document.cookie.indexOf(c_name + "=")
if (c_start != -1) {
c_start = c_start + c_name.length + 1
c_end = document.cookie.indexOf(";", c_start)
if (c_end == -1) c_end = document.cookie.length
return unescape(document.cookie.substring(c_start, c_end))
}
}
return ""
} var token = getCookie("xToken");
if (token) {
$('[name="authorization"]').val(token);
} var XSRFToken = getCookie("XSRF-TOKEN");
if (XSRFToken) {
$('[name="X-XSRF-TOKEN"]').val(XSRFToken);
} var setToken = function () {
var json = $("#resource_Account .response_body.json").text()
if (json) {
var obj = eval('(' + json + ')');
if (obj.result) {
$('[name="authorization"]').val("Bearer " + obj.result);
setCookie("xToken", "Bearer " + obj.result);
}
}
} setInterval(setToken, 5000)

另外,在Application和WebApi的项目属性,生成输出中,勾选“XML文档文件”,如下图

三、最终效果

代码中还为接口自动添加了X-XSRF-TOKEN和authorization两个参数,可以让我们更方便的调用加了权限的接口。

ABP给WebApi添加SwaggerUI,生成可交互接口文档的更多相关文章

  1. Asp.Net Core2.0 WebAPI 使用Swagger生成漂亮的接口文档

    1.引用NuGet: Swashbuckle.AspNetCore.Swagger Swashbuckle.AspNetCore.SwaggerGen 或 <PackageReference I ...

  2. 整合swagger2生成Restful Api接口文档

    整合swagger2生成Restful Api接口文档 swagger Restful文档生成工具 2017-9-30 官方地址:https://swagger.io/docs/specificati ...

  3. Swagger 生成 PHP API 接口文档

    Swagger 生成 PHP API 接口文档 Lumen微服务生成Swagger文档 1.概况 有同学反馈写几十个接口文档需要两天的工作量, 随着多部门之间的协作越来越频繁, 维护成本越来越高, 文 ...

  4. 如何快速方便的生成好看的接口文档(apipost生成文档)

    一键生成文档 我们在"2分钟玩转APIPOST"一讲中,简单介绍了如何生成并分享接口文档: 点击分享文档 复制并打开文档地址就可以看到了完整的接口文档. 本节课主要是讲解一些需要注 ...

  5. 如何使用Swagger-UI在线生成漂亮的接口文档

    一.简单介绍 Swagger是一个实现了OpenAPI(OpenAPI Specification)规范的工具集.OpenAPI是Linux基金会的一个项目,试图通过定义一种用来描述API格式或API ...

  6. Abp中SwaggerUI的多个接口文档配置说明

    对外提供的接口在实际生成过程中,可能是需要一个接口版本的,比如说v1,manage.效果如下:     在swagger中怎么实现呢? 1. 添加SwaggerVersionHelper.cs pub ...

  7. SpringBoot结合swagger2快速生成简单的接口文档

    1. pom.xml中加入依赖 <dependency> <groupId>com.spring4all</groupId> <artifactId>s ...

  8. 自动生成web api接口文档

    然后打开web程序,访问ip:port/Help. 为什么可以直接输入Help就能访问呢,因为这个插件本身已经配置了路径,如下. public class HelpPageAreaRegistrati ...

  9. Java | Spring Boot Swagger2 集成REST ful API 生成接口文档

      Spring Boot Swagger2 集成REST ful API 生成接口文档 原文 简介 由于Spring Boot 的特性,用来开发 REST ful 变得非常容易,并且结合 Swagg ...

随机推荐

  1. Django模板语言初识

    一.Django框架简介 1.MVC框架 MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控 ...

  2. SQLServer 中多行数据合并成一行数据(一个字段)

    需求:有四行数据,如下: 1.苹果 2.橘子 3.桃子 4.波罗 合并成一个字段:苹果,橘子,桃子,波罗: 需求明确之后,先弄点测试数据,上代码: --创建一个临时表 Create table #te ...

  3. 【BZOJ5491】[HNOI2019]多边形(模拟,组合计数)

    [HNOI2019]多边形(模拟,组合计数) 题面 洛谷 题解 突然特别想骂人,本来我考场现切了的,结果WA了几个点,刚刚拿代码一看有个地方忘记取模了. 首先发现终止态一定是所有点都向\(n\)连边( ...

  4. RazorEngine

    目标 使用razorengine编译cshtml页面生静态html 制作一个vs2017的插件,实现右击cshtml文件时,编译该文件. 环境 razorengine4.5 / netframewor ...

  5. Linux-安装Windows字体

    Linux 服务器安装Windows字体 直接上步骤: Windows字体包下载链接:https://pan.baidu.com/s/1ks9a70snHo02CTuqTrQhhg  提取码:7aw5 ...

  6. IIS运行一段时间不响应的解决方法

    查找事件记录,提示为应用程序池 'DefaultAppPool' 提供服务的进程关闭时间超过了限制 解决方案: Internet 信息服务(IIS)管理器->应用程序池->DefaultA ...

  7. 常用js方法整理(个人)

    开头总要有点废话 今天想了下,还是分享下自己平时积累的一些实用性较高的js方法,供大家指点和评价.本想分篇介绍,发现有点画蛇添足.整理了下也没多少拿得出手的方法,自然有一些是网上看到的个人觉得很有实用 ...

  8. 数据库学习之MySQL基础

    数据库基础 一.数据库简介 数据库:存放数据的仓库 sql及其规范 sql是Structured Query Language(结构化查询语言)的缩写.SQL是专为数据库而建立的操作命令集,是一种功能 ...

  9. 金融量化分析【day111】:Matplotib-绘制K线图

    一.绘制k线图 1.使用金融包出错解决 1.错误代码 ImportError: No module named finance 2.解决办法 https://github.com/matplotlib ...

  10. crm 权限设计

    先在项目中创建  app rbac的models.py from django.db import models class Permission(models.Model): "" ...