.NET Core基础篇之:集成Swagger文档与自定义Swagger UI
Swagger大家都不陌生,Swagger (OpenAPI) 是一个与编程语言无关的接口规范,用于描述项目中的 REST API。它的出现主要是节约了开发人员编写接口文档的时间,可以根据项目中的注释生成对应的可视化接口文档。
OpenAPI 规范 (openapi.json)
OpenAPI 规范是描述 API 功能的文档。该文档基于控制器和模型中的 XML和属性注释。它是 OpenAPI 流的核心部分,用于驱动诸如 SwaggerUI 之类的工具。

.NET 平台下的两个主要实现Swagger的包是 Swashbuckle 和 NSwag。今天我们从 Swashbuckle 开始了解。
基础功能
1、在包管理器搜索Swashbuckle.AspNetCore并安装。

2、在Startup.cs文件内的ConfigureServices方法内添加代码。
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSwaggerGen();
}
3、在Startup.cs文件内的Configure方法内添加代码。
app.UseSwagger();
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "v1");
options.RoutePrefix = string.Empty;
});
4、修改项目的launchSettings.json文件,将launchUrl的值改为:index.html
5、准备接口
[ApiController]
public class HomeController : ControllerBase
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
/// <summary>
/// 获取用户信息
/// </summary>
/// <returns></returns>
[HttpGet("home/getuser")]
public string GetUser()
{
return "my name is dotnetboy";
}
/// <summary>
/// 登录成功
/// </summary>
/// <returns></returns>
[HttpPost("home/login")]
public string Login()
{
return "login success";
}
/// <summary>
/// 删除用户
/// </summary>
[HttpDelete("home/{id}")]
public string DeleteUser(string id)
{
return $"delete success,id={id}";
}
}
6、开启xml文档输出然后启动项目


扩展功能
项目描述
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo
{
Title = "测试接口文档",
Version = "v1",
Description = "测试 webapi"
});
});
接口分组
在实际开发中,如果所有接口都展示在一起非常不利于相关人员查找,我们可以根据业务逻辑对相关接口进行分组,比如:登录、用户、订单、商品等等。
1、准备分组信息特性
/// <summary>
/// 分组信息特性
/// </summary>
public class GroupInfoAttribute : Attribute
{
/// <summary>
/// 标题
/// </summary>
public string Title { get; set; }
/// <summary>
/// 版本
/// </summary>
public string Version { get; set; }
/// <summary>
/// 描述
/// </summary>
public string Description { get; set; }
}
2、准备分组枚举
/// <summary>
/// 接口分组枚举
/// </summary>
public enum ApiGroupNames
{
[GroupInfo(Title = "登录认证", Description = "登录相关接口", Version = "v1")]
Login,
[GroupInfo(Title = "User", Description = "用户相关接口")]
User,
[GroupInfo(Title = "User", Description = "订单相关接口")]
Order
}
3、准备接口特性
/// <summary>
/// 分组接口特性
/// </summary>
public class ApiGroupAttribute : Attribute, IApiDescriptionGroupNameProvider
{
/// <summary>
///
/// </summary>
/// <param name="name"></param>
public ApiGroupAttribute(ApiGroupNames name)
{
GroupName = name.ToString();
}
/// <summary>
/// 分组名称
/// </summary>
public string GroupName { get; set; }
}
4、给不同接口加上特性
[ApiController]
public class HomeController : ControllerBase
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
/// <summary>
/// 获取用户信息
/// </summary>
/// <returns></returns>
[HttpGet("home/getuser")]
[ApiGroup(ApiGroupNames.User)]
public string GetUser()
{
return "my name is dotnetboy";
}
/// <summary>
/// 登录成功
/// </summary>
/// <returns></returns>
[HttpPost("home/login")]
[ApiGroup(ApiGroupNames.Login)]
public string Login()
{
return "login success";
}
/// <summary>
/// 删除订单
/// </summary>
[HttpDelete("home/{id}")]
[ApiGroup(ApiGroupNames.Order)]
public string DeleteOrder(string id)
{
return $"delete success,id={id}";
}
/// <summary>
/// 留言
/// </summary>
[HttpDelete("home/message")]
public string DeleteUser(string msg)
{
return $"message:{msg}";
}
}
5、修改 ConfigureServices 方法的 AddSwaggerGen
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo
{
Title = "接口文档",
Version = "v1",
Description = "测试 webapi"
});
// 遍历ApiGroupNames所有枚举值生成接口文档,Skip(1)是因为Enum第一个FieldInfo是内置的一个Int值
typeof(ApiGroupNames).GetFields().Skip(1).ToList().ForEach(f =>
{
//获取枚举值上的特性
var info = f.GetCustomAttributes(typeof(GroupInfoAttribute), false).OfType<GroupInfoAttribute>().FirstOrDefault();
options.SwaggerDoc(f.Name, new OpenApiInfo
{
Title = info?.Title,
Version = info?.Version,
Description = info?.Description
});
});
// 没有特性的接口分到NoGroup上
options.SwaggerDoc("NoGroup", new OpenApiInfo
{
Title = "无分组"
});
// 判断接口归于哪个分组
options.DocInclusionPredicate((docName, apiDescription) =>
{
if (docName == "NoGroup")
{
// 当分组为NoGroup时,只要没加特性的接口都属于这个组
return string.IsNullOrEmpty(apiDescription.GroupName);
}
else
{
return apiDescription.GroupName == docName;
}
});
});
6、修改 Configure 方法的 UseSwaggerUI
app.UseSwaggerUI(options =>
{
// 遍历ApiGroupNames所有枚举值生成接口文档
typeof(ApiGroupNames).GetFields().Skip(1).ToList().ForEach(f =>
{
//获取枚举值上的特性
var info = f.GetCustomAttributes(typeof(GroupInfoAttribute), false).OfType<GroupInfoAttribute>().FirstOrDefault();
options.SwaggerEndpoint($"/swagger/{f.Name}/swagger.json", info != null ? info.Title : f.Name);
});
options.SwaggerEndpoint("/swagger/NoGroup/swagger.json", "无分组");
options.RoutePrefix = string.Empty;
});

自定义UI
前几天,前端同事和我吐槽,Swagger的原生UI太丑了,又不够直观,想找个接口还得一个个收缩展开,总之就是很难用。
- 不够直观
- 不方便查找
有了上面的两点需求何不自己实现一套UI呢?(最终还是用了第三方现成的)
文章最开始有提到OpenAPI 对应的 json 内容,大家也可以在浏览器的控制台看看,swagger ui 的数据源都来自于一个叫 swagger.json 的文件,数据源都有了,根据数据源再做一套 UI 也就不是什么难事了。

1、准备一个美观的单页面(网上找的)

2、将单页面相关内容放到项目内(记得开启静态文件读取)
app.UseStaticFiles();

3、将单页面指定为 UI 页面。
app.UseSwaggerUI(options =>
{
options.IndexStream = () => GetType().Assembly.GetManifestResourceStream("h.swagger.Swagger.index.html");
});
4、在单页面内处理 swagger.json 数据源。
5、最终效果


Swagger UI的功能还是比较多的,比如:详情、调试。如果想自己实现一套UI要做的工作还很多。所以,拿来主义永不过时,最终我还是选择了第三方开源的项目:Knife4j。
使用起来也是非常简单,先引用包:IGeekFan.AspNetCore.Knife4jUI,然后在Startup.Configure中将 app.UseSwaggerUI 替换为:

app.UseKnife4UI(c =>
{
c.RoutePrefix = string.Empty;
c.SwaggerEndpoint($"/swagger/v1/swagger.json", "h.swagger.webapi v1");
});

.NET Core基础篇之:集成Swagger文档与自定义Swagger UI的更多相关文章
- 利用typescript生成Swagger文档
项目地址:https://github.com/wz2cool/swagger-ts-doc demo代码地址:https://github.com/wz2cool/swagger-ts-doc-de ...
- Core + Vue 后台管理基础框架8——Swagger文档
1.前言 作为前后端分离的项目,或者说但凡涉及到对外服务的后端,一个自描述,跟代码实时同步的文档是极其重要的.说到这儿,想起了几年前在XX速运,每天写完代码,还要给APP团队更新文档的惨痛经历.给人家 ...
- SpringBoot系列:六、集成Swagger文档
本篇开始介绍Api文档Swagger的集成 一.引入maven依赖 <dependency> <groupId>io.springfox</groupId> < ...
- asp.net core web api 生成 swagger 文档
asp.net core web api 生成 swagger 文档 Intro 在前后端分离的开发模式下,文档就显得比较重要,哪个接口要传哪些参数,如果一两个接口还好,口头上直接沟通好就可以了,如果 ...
- Asp.Net Core基础篇之:白话管道中间件
在Asp.Net Core中,管道往往伴随着请求一起出现.客户端发起Http请求,服务端去响应这个请求,之间的过程都在管道内进行. 举一个生活中比较常见的例子:旅游景区. 我们都知道,有些景区大门离景 ...
- asp.net core 2.1 生成swagger文档
新建asp.netcore2.1 api项目 “WebApplication1” 在nuget管理器中添加对Swashbuckle.AspNetCore 3.0.0.Microsoft.AspNetC ...
- 使用.NET 6开发TodoList应用(27)——实现API的Swagger文档化
系列导航及源代码 使用.NET 6开发TodoList应用文章索引 需求 在日常开发中,我们需要给前端提供文档化的API接口定义,甚至需要模拟架设一个fake服务用来调试接口字段.或者对于后端开发人员 ...
- 使用 Swagger 文档化和定义 RESTful API
大部分 Web 应用程序都支持 RESTful API,但不同于 SOAP API——REST API 依赖于 HTTP 方法,缺少与 Web 服务描述语言(Web Services Descript ...
- Springboot 系列(十六)你真的了解 Swagger 文档吗?
前言 目前来说,在 Java 领域使用 Springboot 构建微服务是比较流行的,在构建微服务时,我们大多数会选择暴漏一个 REST API 以供调用.又或者公司采用前后端分离的开发模式,让前端和 ...
随机推荐
- JAVA笔记3__字符串String类/对象一对一关联
import java.lang.String; import java.util.Scanner; public class Main { public static void main(Strin ...
- KMP算法,看这篇就够了!
普通的模式匹配算法(BF算法) 子串的定位操作通常称为模式匹配算法 假设有一个需求,需要我们从串"a b a b c a b c a c b a b"中,寻找内容为"a ...
- 痞子衡嵌入式:实测i.MXRT1010上的普通GPIO与高速GPIO极限翻转频率
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1010上的普通GPIO与高速GPIO极限翻转频率. 上一篇文章 <聊聊i.MXRT1xxx上的普通GPIO与高速GP ...
- 2021中国能源网络信息安全大赛wp
FROM TEAM BINX Web ezphp CODE 将base64解了之后得到: $O0O000="rFqQmguebyiVTBwlWAJYRhsHXfpojxEndNGkZICDL ...
- DASCTF 安恒七月赛wp
web Ezfileinclude 首页一张图片,看src就可以看出文件包含 验证了时间戳 尝试用php://filter 读源码读不到,以为只能读.jpg,然后用../路径穿越有waf 最后居然一直 ...
- celery kill task
from celery.task.control import revokerevoke(task_id, terminate=True) https://stackoverflow.com/ques ...
- jQuery css()选择器使用说明
css选择器只是jquery中的一个功能罢了,下面我来给各位朋友详细介绍jQuery css()选择器使用方法与说明详解,有需要了解学习的同学可参考. CSS操作有一个重要的方法:CSS() CSS( ...
- 编解码再进化:Ali266 与下一代视频技术
过去的一年见证了人类百年不遇的大事记,也见证了多种视频应用的厚积薄发.而因此所带来的视频数据量的爆发式增长更加加剧了对高效编解码这样的底层硬核技术的急迫需求. 新视频编解码标准 VVC 定稿不久之后, ...
- ECharts + jsp 图表
... <%@ page language="java" pageEncoding="UTF-8"%> <%@page import=&quo ...
- 菜鸡的Java笔记 国际化程序实现原理
国际化程序实现原理 Lnternationalization 1. Locale 类的使用 2.国家化程序的实现,资源读取 所谓的国际化的程序 ...