.NET 9.0 与 Swagger 的集成实践:一步步构建Api文档

引言

在现代API开发中,良好的文档是确保API易用性和可维护性的关键。Swagger(现在也称为OpenAPI)是一个强大的工具,可以自动生成、可视化和测试API文档。本文将详细介绍如何在.NET 9.0项目中集成Swagger,构建专业的API文档。

一、准备工作

1. 创建项目并安装Swashbuckle.AspNetCore包

在.NET 9.0中,我们需要安装以下Swagger相关包:

bash 复制代码
dotnet add package Swashbuckle.AspNetCore

二、基本Swagger配置

1. 配置Swagger服务

在.NET 9.0中,我们可以在Program.cs文件中配置Swagger服务。以下是基本配置:

csharp 复制代码
// Program.cs
if (env.IsDevelopment() || appConfig.Swagger.Enable)
{
    // 注册Swagger生成器和端点资源管理器
    services.AddEndpointsApiExplorer();
    services.AddSwaggerGen(options =>
    {
        // 配置Swagger文档
        options.SwaggerDoc("v1", new OpenApiInfo
        {
            Title = "API文档",
            Version = "v1",
            Description = "这是一个.NET 9.0 Web API项目"
        });
    });
}
2. 配置Swagger中间件

接下来,我们需要在请求管道中添加Swagger中间件:

csharp 复制代码
// Program.cs
if (env.IsDevelopment() || appConfig.Swagger.Enable)
{
    app.UseSwagger();
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "API文档 v1");
        c.DocumentTitle = "接口文档";
    });
}

三、高级Swagger配置

1. Swagger分组配置

为了更好地组织API文档,我们可以使用Swagger分组功能。首先,创建一个扩展方法来配置Swagger分组:

csharp 复制代码
// SwaggeServiceExtension.cs
public static void AddSaggerGroup(this SwaggerGenOptions options)
{
    // 配置接口阐述文档
    options.SwaggerDoc("PrefaceGroup", new OpenApiInfo
    {
        Title = "接口阐述",
        Description = "详细的API使用说明",
        Version = "V1"
    });
    
    // 从程序集中扫描SwaggeGroupAttribute属性,自动生成API分组
    GetSwaggerGroupInfo().ForEach(f =>
    {
        options.SwaggerDoc(f.GroupName, new OpenApiInfo
        {
            Title = f.Title,
            Version = f.Version,
            Description = f.Description
        });
    });
    
    // 配置文档包含规则
    options.DocInclusionPredicate((docName, apiDescription) =>
    {
        if (docName == "NoGroup")
        {
            // 当分组为NoGroup时,只要没加特性的都属于这个组
            return string.IsNullOrEmpty(apiDescription.GroupName);
        }
        else
        {
            return apiDescription.GroupName == docName;
        }
    });
}
2. 配置Swagger UI分组

接下来,创建一个扩展方法来配置Swagger UI分组:

csharp 复制代码
// SwaggeServiceExtension.cs
public static void UseGroupSagger(this IApplicationBuilder app)
{
    app.UseSwaggerUI(c =>
    {
        c.DocumentTitle = "接口文档";
        c.SwaggerEndpoint("/swagger/PrefaceGroup/swagger.json", "接口阐述");
        
        // 添加自动生成的API分组端点
        GetSwaggerGroupInfo().ForEach(f =>
        {
            c.SwaggerEndpoint($"/swagger/{f.GroupName}/swagger.json", f.Title ?? f.GroupName);
        });
        
        // 配置文档折叠方式
        c.DocExpansion(DocExpansion.None);
    });
}
3. 使用Swagger分组属性

创建一个SwaggeGroupAttribute属性,用于标记控制器所属的分组:

csharp 复制代码
// SwaggeGroupAttribute.cs
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class SwaggeGroupAttribute : Attribute, IApiDescriptionGroupNameProvider
{
    public string GroupName { get; set; }
    public string Title { get; set; }
    public string Version { get; set; }
    public string Description { get; set; }
    
    public SwaggeGroupAttribute(string groupName, string title, string version, string description = "")
    {
        GroupName = groupName;
        Title = title;
        Version = version;
        Description = description;
    }
}

然后,在控制器上使用该属性:

csharp 复制代码
[ApiController]
[Route("[controller]")]
[SwaggeGroup("UserGroup", "用户管理", "v1", "用户相关API")]
public class UserController : ControllerBase
{
    // API方法
}
4. Swagger过滤器

Swagger提供了多种过滤器,可以自定义API文档的生成。以下是一些常用的过滤器:

4.1 枚举架构过滤器

增强枚举类型的描述:

csharp 复制代码
// EnumSchemaFilter.cs
public class EnumSchemaFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        if (context.Type.IsEnum)
        {
            schema.Enum.Clear();
            Enum.GetNames(context.Type).ToList().ForEach(name =>
            {
                var enumMember = context.Type.GetMember(name).First();
                var descriptionAttribute = enumMember.GetCustomAttribute<DescriptionAttribute>();
                var enumValue = Enum.Parse(context.Type, name);
                
                schema.Enum.Add(new OpenApiString($"{enumValue} - {descriptionAttribute?.Description ?? name}"));
            });
        }
    }
}
4.2 路径驼峰命名过滤器

将API路径转换为驼峰命名格式:

csharp 复制代码
// PathCamelCasenFilter.cs
public class PathCamelCasenFilter : IDocumentFilter
{
    public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
    {
        var paths = swaggerDoc.Paths.ToDictionary(entry => entry.Key, entry => entry.Value);
        swaggerDoc.Paths.Clear();
        
        foreach (var path in paths)
        {
            var newPath = string.Join("/", path.Key.Split('/').Select(segment =>
            {
                if (segment.StartsWith("{") && segment.EndsWith("}"))
                {
                    var paramName = segment.Substring(1, segment.Length - 2);
                    return "{" + char.ToLower(paramName[0]) + paramName.Substring(1) + "}";
                }
                return segment;
            }));
            
            swaggerDoc.Paths[newPath] = path.Value;
        }
    }
}
4.3 Swagger忽略属性

用于标记不需要在文档中显示的属性:

csharp 复制代码
// SwaggerIgnoreAttribute.cs
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class SwaggerIgnoreAttribute : Attribute
{
}
5. 注册Swagger过滤器

Program.cs中注册这些过滤器:

csharp 复制代码
// Program.cs
services.AddSwaggerGen(options =>
{
    // 添加Swagger分组
    options.AddSaggerGroup();
    
    // 注册过滤器
    options.OperationFilter<SwaggerIgnoreFilter>();
    options.OperationFilter<AddHeaderParameterOperationFilter>();
    options.SchemaFilter<EnumSchemaFilter>();
    options.OperationFilter<ValidateRequiredOperationFilter>();
    options.DocumentFilter<PathCamelCasenFilter>();
    
    // 配置自定义操作ID
    options.CustomOperationIds(apiDesc =>
    {
        var controllerAction = apiDesc.ActionDescriptor as ControllerActionDescriptor;
        return controllerAction!.ControllerName + "-" + controllerAction.ActionName;
    });
    
    // 包含XML注释
    string[] xmlFiles = Directory.GetFiles(AppContext.BaseDirectory, "*.xml");
    if (xmlFiles.Length > 0)
    {
        foreach (var xmlFile in xmlFiles)
        {
            options.IncludeXmlComments(xmlFile, true);
        }
    }
    
    // 配置参数驼峰命名
    options.DescribeAllParametersInCamelCase();
});

四、条件启用Swagger

在实际项目中,我们可能只希望在特定环境或特定条件下启用Swagger。可以通过以下方式实现:

csharp 复制代码
// Program.cs
// 仅在开发环境或配置文件中启用Swagger时启用
if (env.IsDevelopment() || appConfig.Swagger.Enable)
{
    // 配置Swagger服务
    services.AddSwaggerGen(options =>
    {
        // Swagger配置
    });
    
    // 配置Swagger中间件
    app.UseSwagger();
    app.UseGroupSagger();
}

五、配置文件管理

为了更好地管理Swagger配置,我们可以将Swagger配置添加到appsettings.json文件中:

json 复制代码
// appsettings.json
{
  "Swagger": {
    "Enable": true,
    "Title": "API文档",
    "Version": "v1"
  }
}

然后,创建一个配置类来映射这些配置:

csharp 复制代码
// AppConfig.cs
public class AppConfig
{
    public SwaggerConfig Swagger { get; set; } = new SwaggerConfig();
}

public class SwaggerConfig
{
    public bool Enable { get; set; } = false;
    public string Title { get; set; } = "API文档";
    public string Version { get; set; } = "v1";
}

六、测试和验证

配置完成后,我们可以运行项目并访问Swagger UI界面。默认情况下,Swagger UI的地址是http://localhost:5000/swagger

在Swagger UI中,我们可以:

  1. 查看API文档的分组结构
  2. 查看每个API的详细信息,包括请求参数、响应参数等
  3. 直接在界面上测试API
相关推荐
追逐时光者1 天前
一个 WPF 开源、免费的 SVG 图像查看控件
后端·.net
时光追逐者1 天前
一个基于 .NET 开源、功能强大的分布式微服务开发框架
分布式·微服务·开源·c#·.net·.net core
步步为营DotNet1 天前
深入探究.NET中依赖注入(DI)的生命周期管理:构建稳健且高效的应用
.net
步步为营DotNet1 天前
深度解析.NET中LINQ查询的延迟执行与缓存机制:优化数据查询性能
缓存·.net·linq
我是唐青枫2 天前
C#.NET ref struct 深度解析:语义、限制与最佳实践
c#·.net
武藤一雄2 天前
[奇淫巧技] WPF篇 (长期更新)
windows·microsoft·c#·.net·wpf
寰天柚子2 天前
DotNetBar全面解析:.NET WinForms开发的高效UI控件库
ui·.net
追逐时光者2 天前
精选 8 个 .NET 开发实用的类库,效率提升利器!
后端·.net