本文章主要参考文章.net8系列-03图文并茂手把手教你配置Swagger以及实现接口版本控制 - 糖~豆豆 - 博客园
部分功能根据 DeepSeek 和另外一些文章提供,太乱了就没整理出来
在默认生成的程序中,只会显示最基础的接口文档
出现多个接口就会搞不清楚,所以对 Swagger 文档要做一些配置
需要的 NuGet 包:
Microsoft.Extensions.DependencyInjection
Swashbuckle.AspNetCore
显示接口名称
这个比较简单,把控制器的 "Route" 特性改一下就可以了,主要是加上 "[action]",剩下的格式根据实际需要自行添加
[Route("api/[controller]/[action]")]
解决之后的样式
显示注释
为了显示控制器、参数、接口注释,需要进行配置一下。
首先,在项目下新建一个 XML 文档
然后右键项目 -> 属性 -> 生成 -> 输出,选中 "文档文件"。
然后还在 "输出",找到 "取消显示警告",加上 1591,防止由于没有给注释显示警告信息
重新生成一下解决方案,它会自动在 "obj\Debug\net8.0\" 这个目录下面生成一个 XML 文档。
修改一下 AddSwaggerGen() 方法
Program.cs 文件中引用一下
效果
枚举注释
上述办法只能是简单的注释,枚举注释还需要在配置一下
建立一个类,继承 ISchemaFilter
using System.ComponentModel;
using System.Reflection;
using System.Text;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace MyProject.Extension.Swaggers
{
/// <summary>
/// XML 美剧扩展
/// </summary>
public static class XMLEnumExtensions
{
/// <summary>
/// XML 枚举架构过滤器
/// </summary>
public class XMLEnumSchemaFilter : ISchemaFilter
{
/// <summary>
/// 实现 ISchemaFilter 接口,显示 Swagger 文档中的枚举注释
/// </summary>
/// <param name="schema"></param>
/// <param name="context"></param>
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
if (context.Type.IsEnum)
{
var stringBuilder = new StringBuilder();
var enumType = context.Type;
// 如果已经有描述,保留原描述并换行
if (!string.IsNullOrEmpty(schema.Description))
{
stringBuilder.AppendLine(schema.Description);
stringBuilder.AppendLine();
}
foreach (var name in Enum.GetNames(enumType))
{
var enumValue = Enum.Parse(enumType, name);
var numericValue = Convert.ToInt64(enumValue);
// 获取枚举值的Description特性
var fieldInfo = enumType.GetField(name);
var description = fieldInfo?.GetCustomAttribute<DescriptionAttribute>()?.Description;
stringBuilder.AppendLine($"{name} = {numericValue}{(string.IsNullOrEmpty(description) ? "" : $" ({description})")}");
}
schema.Description = stringBuilder.ToString();
}
}
}
}
}
然后在 AddSwaggerGen() 中调用一下
using Microsoft.Extensions.DependencyInjection;
using static MyProject.Extension.Swaggers.XMLEnumExtensions;
namespace MyProject.Extension.Swaggers
{
/// <summary>
/// Swagger 配置
/// </summary>
public static class SwaggerSetup
{
public static void AddSwaggerSetup(this IServiceCollection services)
{
// 程序根目录
string basePath = AppContext.BaseDirectory;
services.AddEndpointsApiExplorer();
services.AddSwaggerGen(c =>
{
// 文档注释
string xmlPath = Path.Combine(basePath, "MyProject.Api.xml");
c.IncludeXmlComments(xmlPath, true);
c.SchemaFilter<XMLEnumSchemaFilter>(); // 显示枚举注释,需要对枚举值使用 Description 特性
});
}
}
}
这时候枚举注释就出来了
Swagger 分组
为了方便灵活配置,我们先建立一个版本类,里面定义我们需要分组的名称
namespace MyProject.Extension.Swaggers
{
/// <summary>
/// Swagger 版本类,用于对接口进行分类
/// </summary>
public class SwaggerVersion
{
/// <summary>
/// Swagger 版本 1
/// </summary>
public const string V1 = "业务应用";
/// <summary>
/// Swagger 版本 2
/// </summary>
public const string V2 = "系统应用";
}
}
现在修改一下 "AddSwaggerGen"
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using static MyProject.Extension.Swaggers.XMLEnumExtensions;
namespace MyProject.Extension.Swaggers
{
/// <summary>
/// Swagger 配置
/// </summary>
public static class SwaggerSetup
{
public static void AddSwaggerSetup(this IServiceCollection services)
{
// 程序根目录
string basePath = AppContext.BaseDirectory;
services.AddEndpointsApiExplorer();
services.AddSwaggerGen(c =>
{
// 文档注释
string xmlPath = Path.Combine(basePath, "MyProject.Api.xml");
c.IncludeXmlComments(xmlPath, true);
c.SchemaFilter<XMLEnumSchemaFilter>(); // 显示枚举注释,需要对枚举值使用 Description 特性
// Swagger 版本
foreach (FieldInfo field in typeof(SwaggerVersion).GetFields())
{
c.SwaggerDoc(field.Name, new OpenApiInfo()
{
Title = field.GetValue(null)?.ToString(),
Version = field.Name
});
}
});
}
}
}
再修改一下 "UseSwaggerUI"
app.UseSwaggerUI(option =>
{
foreach (FieldInfo field in typeof(SwaggerVersion).GetFields())
{
option.SwaggerEndpoint($"/swagger/{field.Name}/swagger.json", $"{field.GetValue(null)?.ToString()}");
}
});
使用的时候,在控制器上加上特性 "ApiExplorerSettings",如果不加,那么这个控制器属于任意一个分组
[ApiExplorerSettings(GroupName = nameof(SwaggerVersion.V1))]
看下效果
如果分组没有生效,清除一下浏览器缓存再试试