webapi+swagger ui 文档描述
代码:GitHub
swagger ui在我们的.NET CORE和.NET Framework中的展现形式是不一样的,如果有了解的,在.NET CORE中的是比.NET Framework好的。两张图对比下
.NET Framework中自带的就是这个,样式一般

.NET CORE中:

一对比core中的明显好看,本篇教你怎么在Framework 环境中搭建下面的样式,先看看效果,下面就是在Framework 环境搭建的效果:



环境:Owin
owin了解:https://www.cnblogs.com/neverc/p/4864414.html
注:怎么搭建的可以百度一下Owin,这边主要是介绍要注意的几点,源码在github上。
①下载我们的Swagger ui
地址:https://github.com/swagger-api/swagger-ui
下载dist文件夹的东西

添加到我们的项目中,文件夹为swagger

② nuget Swashbuckle.Core
在App_Start中创建一个DocConfig 类,进行文档配置
using Sealee.Util;
using Swashbuckle.Application;
using Swashbuckle.Swagger;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Http;
using System.Web.Http.Description;
using System.Xml;
using WebApiOwin.App_Start; namespace WebApiOwin
{
public class DocConfig
{
public static void Register(HttpConfiguration config)
{
Assembly _thisAssembly = typeof(DocConfig).Assembly;
string _project = MethodBase.GetCurrentMethod().DeclaringType.Namespace;//项目命名空间 //注释 我们的post提交都会创建Dto来申明,这边添加了注释,前台页面就会显示
string path = System.AppDomain.CurrentDomain.BaseDirectory;
string _xmlPath = string.Format("{0}/bin/{1}.XML", path, _project);
string path2 = path.GetSlnPath();
string _xmlPath2 = Path.Combine(path2, "My.Entity\\bin\\My.Entity.xml"); config.EnableSwagger(c =>
{
c.MultipleApiVersions(
(apiDesc, targetApiVersion) =>
{
//控制器描述
IEnumerable<string> versions = apiDesc.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<MyVersionAttribute>().Select(x => x.Version);
return versions.Any(v => $"{v.ToString()}" == targetApiVersion);
},
(vc) =>
{
//MyVersionAttribute 标识了这个属性的都需要在这里加上 这边会配合index.html页面完成
vc.Version("Token", "");
vc.Version("JwtUser", "");
}); //c.SingleApiVersion("Token", "Super duper API");
//忽略标记为已删除的属性
c.IgnoreObsoleteProperties(); //多文档描述
//文档描述
c.IncludeXmlComments(_xmlPath);
//文档描述
c.IncludeXmlComments(_xmlPath2); c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First()); c.CustomProvider((defaultProvider) =>
{
//获取描述
return new MySwaggerProvider(defaultProvider, _xmlPath);
}); //操作过滤
c.OperationFilter<HttpHeadFilter>();
}); //.EnableSwaggerUi() 重点:这边我们不需要他生成页面,使用我们刚刚下载dist中的页面 }
} /// <summary>
/// 设置SwaggerDocument 显示的数据
/// </summary>
public class MySwaggerProvider : ISwaggerProvider
{
private static ConcurrentDictionary<string, SwaggerDocument> _cache =
new ConcurrentDictionary<string, SwaggerDocument>(); private readonly ISwaggerProvider _swaggerProvider;
private readonly string _xmlPath; public MySwaggerProvider(ISwaggerProvider swaggerProvider, string xmlPath)
{
_swaggerProvider = swaggerProvider;
_xmlPath = xmlPath;
} public SwaggerDocument GetSwagger(string rootUrl, string apiVersion)
{
string cacheKey = string.Format("{0}_{1}", rootUrl, apiVersion);
//只读取一次
if (!_cache.TryGetValue(cacheKey, out SwaggerDocument srcDoc))
{
srcDoc = _swaggerProvider.GetSwagger(rootUrl, apiVersion);
ConcurrentDictionary<string, string> pairs = GetControllerDesc(apiVersion);
//控制器描述
IList<Tag> tagList = new List<Tag>();
foreach (KeyValuePair<string, string> item in pairs)
{
Tag tag = new Tag();
tag.name = item.Key;
tag.description = item.Value;
tagList.Add(tag);
}
srcDoc.tags = tagList; srcDoc.vendorExtensions = new Dictionary<string, object> {
{ "ControllerDesc", pairs }
};
_cache.TryAdd(cacheKey, srcDoc);
}
return srcDoc;
} /// <summary>
/// 从API文档中读取控制器描述
/// </summary>
private ConcurrentDictionary<string, string> GetControllerDesc(string apiVersion)
{
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 = -, cCount = "Controller".Length;
XmlNode summaryNode = null;
foreach (XmlNode node in xmldoc.SelectNodes("//member"))
{
type = node.Attributes["name"].Value;
if (type.StartsWith("T:"))
{
string[] typeName = type.Split(':');
Type t = Type.GetType(typeName[]); //控制器
arrPath = type.Split('.');
length = arrPath.Length;
controllerName = arrPath[length - ];
if (controllerName.EndsWith("Controller"))
{
//如果分组了
if (t.GetCustomAttributes<MyVersionAttribute>().Count() != )
{
string version = t.GetCustomAttribute<MyVersionAttribute>().Version;
//上面tag和下面的需要同步过滤
if (version == apiVersion)
{
//获取控制器注释
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;
}
} public class HttpHeadFilter : IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
// if (operation.parameters == null)
// operation.parameters = new List<Parameter>();
////判断是否添加授权过滤器
// var filterPipeline = apiDescription.ActionDescriptor.GetFilterPipeline();
// var isAuthorized = filterPipeline.Select(fileInfo => fileInfo.Instance).Any(filter => filter is IAuthorizationFilter);
// var allowAnonymous = apiDescription.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any();
// if (isAuthorized&&!allowAnonymous)
// {
// operation.parameters.Add(new Parameter { name = "Authorization", @in = "head", description = "token", required = false, type = "string" }); // } if (operation == null)
{
return;
} if (operation.parameters == null)
{
operation.parameters = new List<Parameter>();
}
if (operation.security == null)
{
operation.security = new List<IDictionary<string, IEnumerable<string>>>();
} Parameter parameter = new Parameter
{
description = "The authorization token",
@in = "header",
name = "Authorization",
required = true,
type = "string"
}; //var parameter = new Parameter
//{
// description = "The authorization token",
// @in = "header",
// name = "Authorization",
// required = true,
// type = "string"
//};
//显示锁标识
if (apiDescription.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any())
{
//parameter.required = false;
}
else
{
Dictionary<string, IEnumerable<string>> oAuthRequirements = new Dictionary<string, IEnumerable<string>> { { "Authorization", new List<string>() } };
operation.security.Add(oAuthRequirements);
}
// operation.parameters.Add(parameter);
}
}
}
MyVersionAttribute 类用来显示我们的版本
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true)]
public class MyVersionAttribute : Attribute
{ public MyVersionAttribute(string _version)
{
this.Version = _version;
} /// <summary>
/// 版本
/// </summary>
public string Version { get; set; }
}
最后在我们的owin中添加DocConfig

接口列子:


③修改我们的Index.html页面
文档配置:https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/configuration.md

附授权,页面上左边的按钮:
得到这两个js,应用到你的项目

这边就是这两个js生成了授权按钮,以及样式,文本,然后把你授权需要的信息传到后台进行获取token。看下这个js你就知道了,这边不详细介绍了.应为项目中的授权不一样这边的代码你也进行相应的修改才行,别直接Copy用。
授权:一般我们的在接口中授权了的需要你携带token信息才能访问。



隐藏接口:
[ApiExplorerSettings(IgnoreApi = true)]

总结:最主要的还是不要使用代码生成的页面,需要我们的自己添加的页面,然后进行配置就好了。
webapi+swagger ui 文档描述的更多相关文章
- MVC WebApi Swagger帮助文档 接口用法
1.WebApi在解决方案Apps.WebApi中 2.将Apps.WebApi设置为启动项目之后,可以直接浏览到Api的帮助文档,并直接进行调试 3.登录接口 4.登录获取的token来访问其他接口 ...
- 使用Swagger实现webapi接口自动化文档生成
这里是实现自动化api稳当的生成,在网上看了很多swagger的文档,可能都是在为实现接口时直接使用的swagger,其实步骤差不多,但是更加详细的我还没看到,又或者说,我看着文档来的时候还是出错啦, ...
- springboot+swagger接口文档企业实践(上)
目录 1.引言 2.swagger简介 2.1 swagger 介绍 2.2 springfox.swagger与springboot 3. 使用springboot+swagger构建接口文档 3. ...
- Swagger API文档
Swagger API文档集中化注册管理 接口文档是前后端开发对接时很重要的一个组件.手动编写接口文档既费时,又存在文档不能随代码及时更新的问题,因此产生了像swagger这样的自动生成接口文档的 ...
- Swagger在线文档使用教程
springboot整合Swagger2 1.首先创建一个springboot工程,在pom文件内导入依赖 <!--swagger依赖--> <!--Swagger2- ...
- .net core的Swagger接口文档使用教程(二):NSwag
上一篇介绍了Swashbuckle ,地址:.net core的Swagger接口文档使用教程(一):Swashbuckle 讲的东西还挺多,怎奈微软还推荐了一个NSwag,那就继续写吧! 但是和Sw ...
- .net core的Swagger接口文档使用教程(一):Swashbuckle
现在的开发大部分都是前后端分离的模式了,后端提供接口,前端调用接口.后端提供了接口,需要对接口进行测试,之前都是使用浏览器开发者工具,或者写单元测试,再或者直接使用Postman,但是现在这些都已经o ...
- Swagger 接口文档
目录 Swagger 介绍 Swagger 依赖 SpringBoot 集成 Swagger 配置类 常用注解 效果示例 Swagger 介绍 Swagger UI 允许任何人(无论是开发团队还是最终 ...
- 使用Swashbuckle.AspNetCore生成.NetCore WEBAPI的接口文档
一.问题 使用Swashbuckle.AspNetCore生成.NetCore WEBAPI的接口文档的方法 二.解决方案 参考文章:https://docs.microsoft.com/zh-cn/ ...
随机推荐
- 实时查看mysql当前连接数
如何实时查看mysql当前连接数? 1.查看当前所有连接的详细资料:./mysqladmin -uadmin -p -h10.140.1.1 processlist 2.只查看当前连接数(Thread ...
- Docker报错“Dockerfile parse error line 1: FROM requires either one or three arguments”
看官方文档Format: 以 '#' 开头一行被视为评论,出现在其他位置视为参数. 也就不难理解报错原因:将写在同一行的注释视为参数了. 原Dockerfile: 改为:
- Linux定时任务crontab命令
linux 系统则是由 cron (crond) 这个系统服务来控制的.Linux 系统上面原本就有非常多的计划性工作,因此这个系统服务是默认启动的.另外, 由于用户自己也可以设置计划任务,所以,Li ...
- 牛客网CSP-S提高组赛前集训营Round4
牛客网CSP-S提高组赛前集训营 标签(空格分隔): 题解 算法 模拟赛 题目 描述 做法 \(BSOJ6377\) 求由\(n\)长度的数组复制\(k\)次的数组里每个连续子序列出现数字种类的和 对 ...
- 使用viper 进行golang 应用的配置管理
viper 是一个强大的golang 配置管理包,支持多种配置格式内容的读取,同时支持读取key/value 存储的数据 而且不只是读取内容 ,同时也包含了,配置的写入操作. 以下是一个简单的demo ...
- P4211 [LNOI2014]LCA LCT
P4211 [LNOI2014]LCA 链接 loj luogu 思路 多次询问\(\sum\limits_{l \leq i \leq r}dep[LCA(i,z)]\) 可以转化成l到r上的点到根 ...
- 洛谷p3398仓鼠找suger题解
我现在爱死树链剖分了 题目 具体分析的话在洛谷blog里 这里只是想放一下改完之后的代码 多了一个son数组少了一个for 少了找size最大的儿子的for #include <cstdio&g ...
- NodeJS代码组织与部署
使用NodeJS编写程序前,为了有个良好的开端,首先需要准备好代码的目录结构和部署方式,就如同修房子要先搭脚手架.本章将介绍与之相关的各种知识. 一.模块路径解析规则 我们已经知道,require函数 ...
- bootstrap 多级联动下拉框
<!DOCTYPE HTML> <html lang="zh-CN"> <head> <meta charset="UTF-8& ...
- 【POJ2676】Sudoku
本题传送门 本题知识点:深度优先搜索 + 回溯 问题就是要让我们解决一个数独问题.如果你懂得怎么玩数独的话,那就很自然想到用暴力搜索去做题.(比如我就不会,所以先WA了一发quq) 数独符合三个条件 ...
