AI智能
改变未来

.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

太丑了,又不够直观,想找个接口还得一个个收缩展开,总之就是很难用。

  1. 不够直观
  2. 不方便查找

有了上面的两点需求何不自己实现一套

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");});

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » .NET Core基础篇之:集成Swagger文档与自定义Swagger UI