本文3.0版本文章

https://mp.weixin.qq.com/s/SHNNQoYF-t8i2j85E1oSYA

前言

如果想直接在域名的根目录直接加载 swagger 比如访问:localhost:8001 就能访问,可以这样设置:

app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "ApiHelp V1");
c.RoutePrefix = "";//路径配置,设置为空,表示直接访问该文件,
//路径配置,设置为空,表示直接在根域名(localhost:8001)访问该文件,注意localhost:8001/swagger是访问不到的,
//这个时候去launchSettings.json中把"launchUrl": "swagger/index.html"去掉, 然后直接访问localhost:8001/index.html即可

});

书接上文《从零开始搭建自己的前后端分离【 .NET Core2.0 Api + Vue 2.0 】框架之三 || Swagger的使用 3.1》,上文中只是简单的对如何使用Swagger作了介绍,而且最后也提出了几个问题,这里再重温下那几个问题:

为何直接 F5 运行,首页还是无法加载?

接口虽有,但是却没有相应的文字说明?

项目开发中的实体类是如何在Swagger中展示的?

对于接口是如何加权限验证的?

一、swagger的一般用法

0、设置swagger页面为首页——开发环境

在上一回中我们提到,我们直接F5运行项目,出现了系统默认页,

虽然可以在输入/swagger后,顺利的访问swagger ui页,但是我们发现每次运行项目,都会默认访问api/values这个接口,我想要将启动页设为swagger(或者是任意一个页面),你就需要用到了

**设置文件launchSettings.json **了:

然后你再一次F5 运行,就会发现不一样了,其他的配置,以及以后部署中的设置,我们会在以后的文章中都有提到。

1、设置默认直接首页访问 —— 生产环境

上边的方法很正常,直接这么运行,就可以了,但是如果我们部署到服务器,就会发现,上边的那种默认启动首页无效了,还是需要我们每次手动在域名后边输入 /swagger ,麻烦!

别慌,swagger 给我们提供了这个扩展,我们可以指定一个空字符,作为 swagger 的地址,在Configure中配置中间件:

 app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint($"/swagger/v1/swagger.json", $"Blog.Core v1");// 将swagger设置成首页
c.RoutePrefix = ""; //路径配置,设置为空,表示直接在根域名(localhost:8001)访问该文件,注意localhost:8001/swagger是访问不到的,去launchSettings.json把launchUrl去掉
});

然后再把我们上边的项目文件 launchSettings.json 的 launchUrl 给去掉就行了,这样我们无论是本地开发环境,还是生产环境,都可以默认首页加载了。

比如我的在线地址 :apk.neters.club/

2、为接口添加注释

接下来,我们就需要解决第二个问题,如何增加文字说明,就是传说中的注释,我们只需要在需要的api接口方法上,连点三次 / 即可:

添加好了注释,那我们接下来就需要把注释信息导入到swagger里,需要用到xml文档,右键web 项目名称=>属性=>生成,勾选“输出”下面的“xml文档文件”,系统会默认生成一个,当然老规矩,你也可以自己起一个名字:

这里我用的是相对路径,可以直接生成到 api 层的 bin文件夹下:

 

有了注释和文档,那接下来就是导入了,也是很简单,只需要一行即可:

 var basePath = AppContext.BaseDirectory;
var xmlPath = Path.Combine(basePath, "Blog.Core.xml");//这个就是刚刚配置的xml文件名
c.IncludeXmlComments(xmlPath);

运行查看,没问题!

3、忽略注释警告

这个时候,我们看看有没有错误,一看,咦~~~果然,虽然是警告,可以强迫症呀,一看还挺多

别慌!一看,哦!原来是swagger把一些 action 方法都通过xml文件配置了,如果你不想每一个方法都这么加注释,可以这么配置(对当前项目进行配置,可以忽略警告,记得在后边加上分号 ;1591):

这时候你可以看看,所有的警告都已经消失不见了。

4、给控制器也添加注释

刚刚可能你没太注意,我们上边只是给方法加了注释,但是控制器还没有加上,那怎么办呢,有一个复杂的方法,就是添加一个过滤器  c.DocumentFilter<ControllerDescriptionFilter>(); ,然后自己添加一个 .Tags ,但是这个麻烦!不多说,官方已经考虑到了这个问题了,很简单:

首先我们在控制器上加上注释:

然后配置swagger的 xml 文档导入方法:

当当当,出来了:

5、对 Model 也添加注释说明

接下来开始第三个问题:添加实体类说明注释

新建一个.net core 类库Blog.Core.Model,注意是 .net core的类库,或者使用标准库也是可以的!(标准库可以在 NetCore 和 Framework 两个项目都可以跑)

 
新建一个Love的实体类
    /// <summary>
/// 这是爱
/// </summary>
public class Love
{
/// <summary>
/// id
/// </summary>
public int Id { get; set; }
/// <summary>
/// 姓名
/// </summary>
public string Name { get; set; }
/// <summary>
/// 年龄
/// </summary>
public int Age { get; set; }
}
 
这里现在有两个情况,或者说是两个操作方案:
 
1、当前 api 层直接引用了 Blog.Core.Model 层;

这个时候,我们只需要配置仿照上边 api 层配置的xml文档那样,在 Blog.Core.Model 层的 XML 输出到 API 层就行了:

2、API 层没有直接引用 Model 层,而是通过级联的形式;

就比如我的 Github 上的代码那样:

效果和上边是一样的,也算是引用 Model 层了。

 

6、导入model.xml到swagger,然后api添加参数

配置xml文档

 public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); #region Swagger
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info
{
Version = "v0.1.0",
Title = "Blog.Core API",
Description = "框架说明文档",
TermsOfService = "None",
Contact = new Swashbuckle.AspNetCore.Swagger.Contact { Name = "Blog.Core", Email = "Blog.Core@xxx.com", Url = "https://www.jianshu.com/u/94102b59cc2a" }
}); //就是这里
var basePath = Microsoft.DotNet.PlatformAbstractions.ApplicationEnvironment.ApplicationBasePath;
var basePath2 = AppContext.BaseDirectory;// 这种写法也是可以的
    
//就是这里
var xmlPath = Path.Combine(basePath, "Blog.Core.xml");//这个就是刚刚配置的xml文件名
c.IncludeXmlComments(xmlPath, true);//默认的第二个参数是false,这个是controller的注释,记得修改 var xmlModelPath = Path.Combine(basePath, "Blog.Core.Model.xml");//这个就是Model层的xml文件名
c.IncludeXmlComments(xmlModelPath); }); #endregion }

接口添加注释

     /// <summary>
/// post
/// </summary>
/// <param name="love">model实体类参数</param>
[HttpPost]
public void Post(Love love)
{
}

dang dang dang,就出来了

 
 

7、去掉Swagger警告提示

在Model层中,我们建立了很多实体,如果你没有为每一个实体都添加注释的话,可能会出现这样的警告:

如果有的小伙伴,不想添加注释,而又不想看到这个强迫症的警告提示,那就可以这么做,

右键项目 属性 -》 Errors and warnings 配置 1591:

8、隐藏某些接口

如果不想显示某些接口,直接在controller 上,或者action 上,增加特性

[ApiExplorerSettings(IgnoreApi = true)]

9、自定义 Swagger Index 静态页模板

有时候我们为了在页面上增加一些小东西,比如说一个图片或者说,修改部分css样式,甚至更改 js 事件,那我们就必须修改 index.html 页面,很简单:

1、首先我们在 api 根目录下边创建一个 index.html 页面,

<!--<script async="async" id="mini-profiler" src="/profiler/includes.min.js?v=4.1.0+c940f0f28d"
data-version="4.1.0+c940f0f28d" data-path="/profiler/"
data-current-id="" data-ids="" data-position="Left"
data-authorized="true" data-max-traces="" data-toggle-shortcut="Alt+P"
data-trivial-milliseconds="2.0" data-ignored-duplicate-execute-types="Open,OpenAsync,Close,CloseAsync">
</script>--> <!--、版本号要与nuget包一致;、id不能为空-->
<script async="async" id="mini-profiler" src="/profiler/includes.min.js?v=4.1.0+c940f0f28d"
data-version="4.1.0+c940f0f28d" data-path="/profiler/"
data-current-id="4ec7c742-49d4-4eaf-8281-3c1e0efa8888" data-ids="4ec7c742-49d4-4eaf-8281-3c1e0efa8888"
data-position="Left"
data-authorized="true" data-max-traces="" data-toggle-shortcut="Alt+P"
data-trivial-milliseconds="2.0" data-ignored-duplicate-execute-types="Open,OpenAsync,Close,CloseAsync">
</script> <!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>%(DocumentTitle)</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="./swagger-ui.css">
<link rel="icon" type="image/png" href="./logo/favicon-32x32.png" sizes="32x32" />
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<style> html {
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
} *,
*:before,
*:after {
box-sizing: inherit;
} body {
margin: ;
background: #fafafa;
} .qqgroup {
float: right;
} .info {
float: left;
} .download-contents {
display: none;
}
</style>
%(HeadContent)
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position:absolute;width:0;height:0">
<defs>
<symbol viewBox="0 0 20 20" id="unlocked">
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path>
</symbol>
<symbol viewBox="0 0 20 20" id="locked">
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z" />
</symbol>
<symbol viewBox="0 0 20 20" id="close">
<path d="M14.348 14.849c-.469.469-1.229.469-1.697 0L10 11.819l-2.651 3.029c-.469.469-1.229.469-1.697 0-.469-.469-.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-.469-.469-.469-1.228 0-1.697.469-.469 1.228-.469 1.697 0L10 8.183l2.651-3.031c.469-.469 1.228-.469 1.697 0 .469.469.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c.469.469.469 1.229 0 1.698z" />
</symbol>
<symbol viewBox="0 0 20 20" id="large-arrow">
<path d="M13.25 10L6.109 2.58c-.268-.27-.268-.707 0-.979.268-.27.701-.27.969 0l7.83 7.908c.268.271.268.709 0 .979l-7.83 7.908c-.268.271-.701.27-.969 0-.268-.269-.268-.707 0-.979L13.25 10z" />
</symbol>
<symbol viewBox="0 0 20 20" id="large-arrow-down">
<path d="M17.418 6.109c.272-.268.709-.268.979 0s.271.701 0 .969l-7.908 7.83c-.27.268-.707.268-.979 0l-7.908-7.83c-.27-.268-.27-.701 0-.969.271-.268.709-.268.979 0L10 13.25l7.418-7.141z" />
</symbol> <symbol viewBox="0 0 24 24" id="jump-to">
<path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z" />
</symbol>
<symbol viewBox="0 0 24 24" id="expand">
<path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z" />
</symbol>
</defs>
</svg>
<div id="swagger-ui"></div>
<!-- Workaround for https://github.com/swagger-api/swagger-editor/issues/1371 -->
<script>
if (window.navigator.userAgent.indexOf("Edge") > -) {
console.log("Removing native Edge fetch in favor of swagger-ui's polyfill")
window.fetch = undefined;
}
</script>
<script src="./swagger-ui-bundle.js"></script>
<script src="./swagger-ui-standalone-preset.js"></script>
<script>
var int = null;
window.onload = function () {
var configObject = JSON.parse('%(ConfigObject)');
var oauthConfigObject = JSON.parse('%(OAuthConfigObject)'); // Apply mandatory parameters
configObject.dom_id = "#swagger-ui";
configObject.presets = [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset];
configObject.layout = "StandaloneLayout"; // If oauth2RedirectUrl isn't specified, use the built-in default
if (!configObject.hasOwnProperty("oauth2RedirectUrl"))
configObject.oauth2RedirectUrl = window.location.href.replace("index.html", "oauth2-redirect.html"); // Build a system
const ui = SwaggerUIBundle(configObject); // Apply OAuth config
ui.initOAuth(oauthConfigObject); int = setInterval(function () {
getData();
}, );
$("img").attr("src", "./logo/favicon-32x32.png");
}
function getData() { console.log();
if ($(".qqgroup").length <= ) {
$('.info').after("<div class='qqgroup'><img src='http://123.206.33.109:26898/QQGroup.png' alt='QQ二维码' style='width: 200px;'></div><div style='clear: both;'></div>");
console.log();
clearInterval(int);
} } </script>
</body>
</html>

我们可以在里边简单的修改 css 样式,或者js 事件,但是注意,如果个人能力不是很高的话,建议不要修改。

2、然后我们修改中间件,替换掉 swagger 的默认首页

 app.UseSwaggerUI(c =>
{
//根据版本名称倒序 遍历展示
var ApiName = "Blog.Core";//这里你可以从appsettings.json中获取,比如我封装了一个类Appsettings.cs,具体查看我的源代码
var version = "v1";
c.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"{ApiName} {version}"); // 将swagger首页,设置成我们自定义的页面,记得这个字符串的写法:解决方案名.index.html
c.IndexStream = () => GetType().GetTypeInfo().Assembly.GetManifestResourceStream("Blog.Core.index.html");//这里是配合MiniProfiler进行性能监控的,《文章:完美基于AOP的接口性能分析》,如果你不需要,可以暂时先注释掉,不影响大局。
c.RoutePrefix = ""; //路径配置,设置为空,表示直接在根域名(localhost:8001)访问该文件,注意localhost:8001/swagger是访问不到的,去launchSettings.json把launchUrl去掉,如果你想换一个路径,直接写名字即可,比如直接写c.RoutePrefix = "doc";
});

完成,就是这么简单。

二、结语

对于接口是如何加权限验证的?

让我们带着这些问题,继续浏览下一篇吧,Swagger 3.3 JWT 权限,必看篇。

三、Github && Gitee

https://github.com/anjoy8/Blog.Core.git

https://gitee.com/laozhangIsPhi/Blog.Core

从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之四 || Swagger的使用 3.2的更多相关文章

  1. 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之七 || API项目整体搭建 6.2 轻量级ORM

    更新 1.在使用的时候,特别是更新数据的时候,如果不知道哪里有问题,可以查看数据库 和 实体类 的字段,是否大小写一致,比如 name 和 Name 2.在使用Sqlsugar 的 CodeFirst ...

  2. 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之十 || AOP面向切面编程浅解析:简单日志记录 + 服务切面缓存

    代码已上传Github+Gitee,文末有地址 上回<从壹开始前后端分离[ .NET Core2.0 Api + Vue 2.0 + AOP + 分布式]框架之九 || 依赖注入IoC学习 + ...

  3. 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之十一 || AOP自定义筛选,Redis入门 11.1

    代码已上传Github+Gitee,文末有地址 书说上文<从壹开始前后端分离[ .NET Core2.0 Api + Vue 2.0 + AOP + 分布式]框架之十 || AOP面向切面编程浅 ...

  4. 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之十二 || 三种跨域方式比较,DTOs(数据传输对象)初探

    更新反馈 1.博友@落幕残情童鞋说到了,Nginx反向代理实现跨域,因为我目前还没有使用到,给忽略了,这次记录下,为下次补充.此坑已填 2.提示:跨域的姊妹篇——<三十三║ ⅖ 种方法实现完美跨 ...

  5. 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 十五 ║Vue基础:JS面向对象&字面量& this字

    缘起 书接上文<从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 十四 ║ VUE 计划书 & 我的前后端开发简史>,昨天咱们说到了以我的经历说明的web开发经历的 ...

  6. 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 十六 ║Vue基础:ES6初体验 & 模块化编程

    缘起 昨天说到了<从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 十五 ║ Vue前篇:JS对象&字面量&this>,通过总体来看,好像大家对这一块不是很 ...

  7. 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 十八║Vue基础: 指令(下)+计算属性+watch

    回顾 今天来晚辣,给公司做了一个小项目,一个瀑布流+动态视频控制的DEMO,有需要的可以联系我,公司的项目就不对外展示了(一个后端程序员真的要干前端了哈哈哈). 书接上文,昨天正式的开始了Vue的代码 ...

  8. 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 二十三║Vue实战:Vuex 其实很简单

    前言 哈喽大家周五好,马上又是一个周末了,下周就是中秋了,下下周就是国庆啦,这里先祝福大家一个比一个假日嗨皮啦~~转眼我们的专题已经写了第 23 篇了,好几次都坚持不下去想要中断,不过每当看到群里的交 ...

  9. Z从壹开始前后端分离【 .NET Core2.0/3.0 +Vue2.0 】框架之十 || AOP面向切面编程浅解析:简单日志记录 + 服务切面缓存

    本文梯子 本文3.0版本文章 代码已上传Github+Gitee,文末有地址 大神反馈: 零.今天完成的深红色部分 一.AOP 之 实现日志记录(服务层) 1.定义服务接口与实现类 2.在API层中添 ...

  10. Z从壹开始前后端分离【 .NET Core2.2/3.0 +Vue2.0 】框架之七 || API项目整体搭建 6.2 轻量级ORM

    本文梯子 本文3.0版本文章 前言 零.今天完成的蓝色部分 0.创建实体模型与数据库 1.实体模型 2.创建数据库 一.在 IRepository 层设计接口 二.在 Repository 层实现相应 ...

随机推荐

  1. ORA-12737: Instant Client Light: unsupported server character set CHS16GBK

    当使用Navicat Premiun 英文版连接oracl时可能会报ORA-12737: Instant Client Light: unsupported server character set ...

  2. 跟我学ASP.NET MVC之五:SportsStrore开始

    摘要: 这篇文章将介绍一个ASP.NET应用程序SportsStore的开发过程. 开始 创建解决方案 创建工程 在New ASP.NET Project - SportsStore窗口中,选择Emp ...

  3. segmenter_worker.go

    package; ; i < engine.initOptions.NumShards; i++ {                 if i == shard {                ...

  4. create_volume.go

    package api import (     "net/http"     "io/ioutil"     "errors"     & ...

  5. BZOJ_3993_[SDOI2015]星际战争_二分+网络流

    BZOJ_3993_[SDOI2015]星际战争_二分+网络流 Description 3333年,在银河系的某星球上,X军团和Y军团正在激烈地作战.在战斗的某一阶段,Y军团一共派遣了N个巨型机器人进 ...

  6. B20J_2836_魔法树_树链剖分+线段树

    B20J_2836_魔法树_树链剖分+线段树 题意: 果树共有N个节点,其中节点0是根节点,每个节点u的父亲记为fa[u].初始时,这个果树的每个节点上都没有果子(即0个果子). Add u v d ...

  7. Django中用户权限模块

    Django中用户权限模块 1 auth模块 auth模块是Django提供的标准权限管理系统,可以提供用户身份认证, 用户组和权限管理. auth可以和admin模块配合使用, 快速建立网站的管理系 ...

  8. 从字节码和JVM的角度解析Java核心类String的不可变特性

    1. 前言 最近看到几个有趣的关于Java核心类String的问题. String类是如何实现其不可变的特性的,设计成不可变的好处在哪里. 为什么不推荐使用+号的方式去形成新的字符串,推荐使用Stri ...

  9. (5)STM32使用HAL库实现串口通讯——实战操作

    功能需求: (1)对接收的字符串原样返回(每10个字符一次). (2)发送一个字符串完成后改变LED的状态. 1.创建工程 使用的是F407Discovery,4个LED对应PD12-PD14. (1 ...

  10. Postman-----将 A 请求中 response Body 中的参数值传入到下一个请求 B 的 request body 中作为参数发送请求

    问题:将A接口中response body的"id"传入到B接口的request body中. 解决办法: 1.在A接口的test中设置环境变量. 代码:var data = JS ...