# 接口文档 (05_Swagger)
最后更新: 2024-09-20
# 📚 概述
DarkM Swagger 模块提供 API 接口文档生成功能,支持 API 分组、版本控制、自定义过滤器等功能。
源代码位置: DarkM/src/Framework/Swagger
# 🏗️ 模块架构
# 完整目录结构
Swagger/
└── Swagger.Core/
├── Filters/
│ ├── LowercaseDocumentFilter.cs # 小写文档过滤器
│ ├── IgnorePropertySchemaFilter.cs # 忽略属性过滤器
│ ├── EnumSchemaFilter.cs # 枚举过滤器
│ └── DescriptionDocumentFilter.cs # 描述文档过滤器
├── Conventions/
│ └── ApiExplorerGroupPerVersionConvention.cs # API 分组约定
├── Extensions/
│ └── ModuleDescriptorExtensions.cs # 模块描述符扩展
├── ServiceCollectionExtensions.cs # 服务注册
└── ApplicationBuilderExtensions.cs # 应用构建
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 💡 配置说明
# appsettings.json 配置
{
"Host": {
// 是否启用 Swagger
"Swagger": true
}
}
1
2
3
4
5
6
2
3
4
5
6
说明: 开发模式下会自动启用,生产环境需手动开启。
# 🔧 核心功能
# 1. API 分组约定
文件位置: Swagger.Core/Conventions/ApiExplorerGroupPerVersionConvention.cs
public class ApiExplorerGroupPerVersionConvention : IControllerModelConvention
{
public void Apply(ControllerModel controller)
{
var controllerVersion = controller.Selectors
.FirstOrDefault()?
.AttributeRouteModel?
.Template?
.Split('/')?
.FirstOrDefault()?
.Replace("v", "");
if (int.TryParse(controllerVersion, out var version))
{
controller.GroupName = $"v{version}";
}
else
{
controller.GroupName = "v1";
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
功能: 自动根据 Controller 路由中的版本号进行分组。
# 2. 自定义过滤器
# LowercaseDocumentFilter(小写文档)
文件位置: Swagger.Core/Filters/LowercaseDocumentFilter.cs
public class LowercaseDocumentFilter : IDocumentFilter
{
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
{
var paths = new OpenApiPaths();
foreach (var (key, value) in swaggerDoc.Paths)
{
paths.Add(key.ToLower(), value);
}
swaggerDoc.Paths = paths;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
功能: 将所有 API 路径转换为小写。
# IgnorePropertySchemaFilter(忽略属性过滤器)
文件位置: Swagger.Core/Filters/IgnorePropertySchemaFilter.cs
public class IgnorePropertySchemaFilter : ISchemaFilter
{
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
// 忽略特定属性
var propertiesToIgnore = new[] { "password", "secret" };
foreach (var prop in propertiesToIgnore)
{
schema.Properties?.Remove(prop);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
功能: 忽略敏感属性,不在文档中显示。
# EnumSchemaFilter(枚举过滤器)
文件位置: Swagger.Core/Filters/EnumSchemaFilter.cs
public class EnumSchemaFilter : ISchemaFilter
{
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
if (context.Type.IsEnum)
{
schema.Enum.Clear();
foreach (var enumName in Enum.GetNames(context.Type))
{
var enumValue = Enum.Parse(context.Type, enumName);
var description = enumName;
var field = context.Type.GetField(enumName);
var descAttr = field.GetCustomAttribute<DescriptionAttribute>();
if (descAttr != null)
{
description = descAttr.Description;
}
schema.Enum.Add(new OpenApiString($"{(int)enumValue} - {description}"));
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
功能: 在 Swagger 文档中显示枚举的描述和值。
# DescriptionDocumentFilter(描述文档过滤器)
文件位置: Swagger.Core/Filters/DescriptionDocumentFilter.cs
功能: 为 API 文档添加详细描述。
# 🏗️ 依赖注入
# ServiceCollectionExtensions
文件位置: Swagger.Core/ServiceCollectionExtensions.cs
public static class ServiceCollectionExtensions
{
/// <summary>
/// 添加 Swagger
/// </summary>
public static void AddSwagger(
this IServiceCollection services,
IModuleCollection modules)
{
services.AddSwaggerGen(c =>
{
// API 版本
c.SwaggerDoc("v1", new OpenApiInfo
{
Title = "DarkM API V1",
Version = "v1",
Description = "DarkM 框架 API 文档"
});
// 自定义过滤器
c.DocumentFilter<LowercaseDocumentFilter>();
c.DocumentFilter<DescriptionDocumentFilter>();
c.SchemaFilter<EnumSchemaFilter>();
c.SchemaFilter<IgnorePropertySchemaFilter>();
// 包含 XML 注释
var xmlFiles = Directory.GetFiles(AppContext.BaseDirectory, "*.xml");
foreach (var xmlFile in xmlFiles)
{
c.IncludeXmlComments(xmlFile);
}
});
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 💡 使用示例
# 1. 启用 Swagger
appsettings.json:
{
"Host": {
"Swagger": true
}
}
1
2
3
4
5
2
3
4
5
访问地址: http://localhost:6220/swagger/index.html
# 2. Controller 注释
using System.ComponentModel;
using Microsoft.AspNetCore.Mvc;
/// <summary>
/// 用户管理
/// </summary>
[Description("用户管理")]
[ApiController]
[Route("api/[controller]")]
[ApiVersion("1.0")]
public class UsersController : ControllerBase
{
private readonly IUserService _userService;
public UsersController(IUserService userService)
{
_userService = userService;
}
/// <summary>
/// 获取用户详情
/// </summary>
/// <param name="id">用户 ID</param>
/// <returns>用户信息</returns>
/// <response code="200">返回用户信息</response>
/// <response code="404">用户不存在</response>
[HttpGet("{id}")]
[Description("获取用户详情")]
[ProducesResponseType(typeof(UserDto), 200)]
[ProducesResponseType(404)]
public IResultModel<UserDto> Get(int id)
{
return ResultModel.Success(_userService.GetById(id));
}
/// <summary>
/// 添加用户
/// </summary>
/// <param name="model">用户信息</param>
/// <returns>操作结果</returns>
/// <response code="200">添加成功</response>
/// <response code="400">参数错误</response>
[HttpPost]
[Description("添加用户")]
[ProducesResponseType(200)]
[ProducesResponseType(400)]
public async Task<IResultModel> Add([FromBody] UserAddModel model)
{
return await _userService.AddAsync(model);
}
/// <summary>
/// 删除用户
/// </summary>
/// <param name="id">用户 ID</param>
/// <returns>操作结果</returns>
[HttpDelete("{id}")]
[Description("删除用户")]
[ProducesResponseType(200)]
public async Task<IResultModel> Delete([BindRequired] int id)
{
return await _userService.DeleteAsync(id);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# 3. 模型注释
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
/// <summary>
/// 用户添加模型
/// </summary>
public class UserAddModel
{
/// <summary>
/// 用户名
/// </summary>
[Required(ErrorMessage = "用户名不能为空")]
[StringLength(50, ErrorMessage = "用户名长度不能超过 50 个字符")]
[Description("用户名")]
public string UserName { get; set; }
/// <summary>
/// 邮箱
/// </summary>
[EmailAddress(ErrorMessage = "邮箱格式不正确")]
[Description("邮箱")]
public string Email { get; set; }
/// <summary>
/// 状态
/// </summary>
[Description("状态")]
public Status Status { get; set; } = Status.Enabled;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 🔧 权限编码
Swagger 中的权限编码格式:Area_Controller_Action_HttpMethod
| 接口 | 权限编码 | 说明 |
|---|---|---|
| GET /api/user | Admin_User_Query_Get | 查询用户 |
| POST /api/user | Admin_User_Add_Post | 添加用户 |
| DELETE /api/user/{id} | Admin_User_Delete_Delete | 删除用户 |
| PUT /api/user/{id} | Admin_User_Update_Put | 更新用户 |
# 🔍 常见问题
# Q1: Swagger 页面空白?
检查清单:
- ✅ 确认
appsettings.json中Swagger设置为true - ✅ 确认项目已生成 XML 文档
- ✅ 确认 XML 文件路径正确
解决方案:
<!-- .csproj 文件 -->
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
1
2
3
4
5
2
3
4
5
# Q2: 如何配置多版本 API?
解决方案:
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo
{
Title = "DarkM API V1",
Version = "v1",
Description = "DarkM 框架 API 文档 V1"
});
c.SwaggerDoc("v2", new OpenApiInfo
{
Title = "DarkM API V2",
Version = "v2",
Description = "DarkM 框架 API 文档 V2"
});
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Q3: 如何隐藏某些接口?
解决方案:
- 使用
[ApiExplorerSettings(IgnoreApi = true)]:
[ApiExplorerSettings(IgnoreApi = true)]
[HttpGet("internal")]
public IActionResult InternalApi()
{
// 内部接口,不在 Swagger 中显示
}
1
2
3
4
5
6
2
3
4
5
6
- 使用
[ExcludeFromDocumentation]:
[ExcludeFromDocumentation]
[HttpGet("health")]
public IActionResult HealthCheck()
{
// 健康检查接口,不在 Swagger 中显示
}
1
2
3
4
5
6
2
3
4
5
6
# Q4: 如何配置 JWT 认证?
解决方案:
services.AddSwaggerGen(c =>
{
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer"
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
Array.Empty<string>()
}
});
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Q5: 如何自定义 Swagger UI?
解决方案:
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "DarkM API V1");
c.RoutePrefix = string.Empty; // 设置为根路径
c.DocumentTitle = "DarkM API 文档";
c.DefaultModelsExpandDepth(2);
c.DefaultModelExpandDepth(2);
});
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 📚 相关文档
# 🔗 参考链接
- 源代码 (opens new window) -
src/Framework/Swagger - Swagger 官方文档 (opens new window)
- OpenAPI 规范 (opens new window)
- Swashbuckle GitHub (opens new window)
最后更新: 2024-09-20