一文精通 Swagger 在 .NET 中的全方位配置与应用

文章目录

      • [第一部分:Swagger 核心概念与基础集成](#第一部分:Swagger 核心概念与基础集成)
        • [什么是 Swagger](#什么是 Swagger)
        • [Swagger 如何帮助实现 API](#Swagger 如何帮助实现 API)
        • [Swagger 帮助实现 API 的方式包括:](#Swagger 帮助实现 API 的方式包括:)
        • [1.1 Swagger 技术栈解析](#1.1 Swagger 技术栈解析)
        • [1.2 项目初始化与配置](#1.2 项目初始化与配置)
        • [1.3 核心配置参数详解](#1.3 核心配置参数详解)
      • 第二部分:文档增强与注释规范
        • [2.1 XML 注释集成](#2.1 XML 注释集成)
        • [2.2 控制器注释规范](#2.2 控制器注释规范)
        • [2.3 枚举与模型增强](#2.3 枚举与模型增强)
      • 第三部分:安全认证集成
        • [3.1 JWT Bearer 认证](#3.1 JWT Bearer 认证)
        • [3.2 OAuth2 集成](#3.2 OAuth2 集成)
        • [3.3 API Key 认证](#3.3 API Key 认证)
      • 第四部分:高级定制与扩展
        • [4.1 多版本 API 管理](#4.1 多版本 API 管理)
        • [4.2 自定义操作过滤器](#4.2 自定义操作过滤器)
        • [4.3 文件上传支持](#4.3 文件上传支持)
        • [4.4 自定义 UI 主题](#4.4 自定义 UI 主题)
      • 第五部分:测试与调试技巧
        • [5.1 高级测试功能](#5.1 高级测试功能)
        • [5.2 预设测试数据](#5.2 预设测试数据)
        • [5.3 自动化测试集成](#5.3 自动化测试集成)
      • 第六部分:生产环境最佳实践
        • [6.1 安全加固方案](#6.1 安全加固方案)
        • [6.2 性能优化策略](#6.2 性能优化策略)
        • [6.3 自动化文档发布](#6.3 自动化文档发布)
      • 第七部分:高级场景与扩展
        • [7.1 GraphQL 集成](#7.1 GraphQL 集成)
        • [7.2 Webhook 文档支持](#7.2 Webhook 文档支持)
        • [7.3 多语言文档支持](#7.3 多语言文档支持)

第一部分:Swagger 核心概念与基础集成

什么是 Swagger

Swagger 是一个开源的 API 设计和文档工具,它可以帮助开发人员更快、更简单地设计、构建、文档化和测试 RESTful API。Swagger 可以自动生成交互式 API 文档、客户端 SDK、服务器 stub 代码等,从而使开发人员更加容易地开发、测试和部署 API。

Swagger 如何帮助实现 API

Swagger 可以帮助开发人员更容易地设计、文档化、测试和部署 RESTful API。Swagger 的自动化工具可以加快 API 的开发速度和测试速度,并且可以减少错误和提高代码的可维护性。因此,Swagger 已成为一个流行的 API 设计和文档工具,被广泛应用于各种 Web 应用程序和云服务中。

Swagger 帮助实现 API 的方式包括:

设计和文档化 API:Swagger 提供了一种简单、易于使用的方式来设计和文档化 RESTful API。开发人员可以使用 Swagger UI 来创建和编辑 API 规范,然后使用 Swagger Editor 生成符合 OpenAPI 规范的 API 文档。Swagger UI 可以生成可交互的 API 文档,使开发人员更容易了解 API 的结构和用法。

自动生成代码:Swagger 可以自动从 OpenAPI 规范中生成客户端 SDK 和服务器 stub 代码。这些代码可以减少开发人员的工作量,加快代码开发速度。

测试 API:Swagger 提供了一个集成的测试工具,可以帮助开发人员测试 API 的功能、性能和可靠性。Swagger UI 中提供了一个测试页面,允许开发人员使用各种 HTTP 请求方法来测试 API 的不同端点。

集成和部署:Swagger 可以与许多流行的开发和部署工具(如 Git、Jenkins、Docker 等)集成,以便更容易地部署和管理 API。Swagger 可以自动生成 Swagger UI,使开发人员可以直接从浏览器访问 API 文档和测试页面。

1.1 Swagger 技术栈解析
组件 作用描述 .NET 实现库
OpenAPI 规范 REST API 的描述标准 Microsoft.OpenApi
Swagger UI 交互式 API 文档界面 Swashbuckle.AspNetCore
Swagger Codegen 客户端 SDK 生成工具 NSwag
Swagger Editor 基于浏览器的 API 设计工具 在线工具
1.2 项目初始化与配置

安装 NuGet 包

bash 复制代码
dotnet add package Swashbuckle.AspNetCore

Program.cs 基础配置

csharp 复制代码
var builder = WebApplication.CreateBuilder(args);

// 添加Swagger服务
builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo 
    { 
        Title = "订单服务 API", 
        Version = "v1",
        Description = "电商平台订单管理系统",
        Contact = new OpenApiContact 
        {
            Name = "技术支持",
            Email = "support@example.com"
        }
    });
});

var app = builder.Build();

// 配置Swagger中间件
app.UseSwagger();
app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "订单服务 v1");
    c.DocumentTitle = "API 文档中心";
    c.DefaultModelsExpandDepth(-1); // 完全展开模型
    c.DisplayRequestDuration();     // 显示请求耗时
});

app.Run();
1.3 核心配置参数详解
csharp 复制代码
app.UseSwaggerUI(c => 
{
    c.RoutePrefix = "api-docs";           // 自定义访问路径
    c.EnableDeepLinking();                // 启用深度链接
    c.ShowExtensions();                   // 显示扩展信息
    c.ConfigObject.DisplayOperationId = true; // 显示操作ID
    c.ConfigObject.DefaultModelRendering = "model"; // 模型渲染方式
    c.ConfigObject.ShowCommonExtensions = true; 
});

第二部分:文档增强与注释规范

2.1 XML 注释集成

项目文件配置

xml 复制代码
<PropertyGroup>
  <GenerateDocumentationFile>true</GenerateDocumentationFile>
  <NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>

Swagger 集成配置

csharp 复制代码
builder.Services.AddSwaggerGen(c =>
{
    var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
    c.IncludeXmlComments(xmlPath, includeControllerXmlComments: true);
});
2.2 控制器注释规范
csharp 复制代码
/// <summary>
/// 用户管理相关接口
/// </summary>
[ApiController]
[Route("api/[controller]")]
[Produces("application/json")]
public class UsersController : ControllerBase
{
    /// <summary>
    /// 根据ID获取用户详情
    /// </summary>
    /// <param name="id">用户唯一标识</param>
    /// <returns>用户详细信息</returns>
    /// <response code="200">返回请求的用户数据</response>
    /// <response code="404">用户不存在</response>
    [HttpGet("{id}")]
    [ProducesResponseType(typeof(UserDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public IActionResult GetUser(int id)
    {
        // ...
    }
}
2.3 枚举与模型增强

枚举显示优化

csharp 复制代码
builder.Services.AddSwaggerGen(c =>
{
    c.SchemaFilter<EnumSchemaFilter>();
});

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 => schema.Enum.Add(new OpenApiString(name)));
            schema.Type = "string";
            schema.Format = null;
        }
    }
}

模型示例值配置

csharp 复制代码
public class Product
{
    /// <example>1001</example>
    public int Id { get; set; }
    
    /// <example>高端游戏笔记本</example>
    [Required]
    public string Name { get; set; }
    
    /// <example>12999.99</example>
    public decimal Price { get; set; }
}

第三部分:安全认证集成

3.1 JWT Bearer 认证
csharp 复制代码
builder.Services.AddSwaggerGen(c =>
{
    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Description = "JWT授权令牌格式: 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" 
                }
            },
            new string[] {}
        }
    });
});
3.2 OAuth2 集成
csharp 复制代码
c.AddSecurityDefinition("OAuth2", new OpenApiSecurityScheme
{
    Type = SecuritySchemeType.OAuth2,
    Flows = new OpenApiOAuthFlows
    {
        AuthorizationCode = new OpenApiOAuthFlow
        {
            AuthorizationUrl = new Uri("https://auth.example.com/authorize"),
            TokenUrl = new Uri("https://auth.example.com/token"),
            Scopes = new Dictionary<string, string>
            {
                { "read", "读取权限" },
                { "write", "写入权限" }
            }
        }
    }
});

// UI配置
app.UseSwaggerUI(c => 
{
    c.OAuthClientId("swagger-ui");
    c.OAuthClientSecret("secret");
    c.OAuthAppName("Swagger UI");
    c.OAuthUsePkce();
});
3.3 API Key 认证
csharp 复制代码
c.AddSecurityDefinition("ApiKey", new OpenApiSecurityScheme
{
    Description = "API Key认证",
    Name = "X-API-KEY",
    In = ParameterLocation.Header,
    Type = SecuritySchemeType.ApiKey
});

c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
    {
        new OpenApiSecurityScheme
        {
            Reference = new OpenApiReference 
            { 
                Type = ReferenceType.SecurityScheme, 
                Id = "ApiKey" 
            }
        },
        Array.Empty<string>()
    }
});

第四部分:高级定制与扩展

4.1 多版本 API 管理
csharp 复制代码
// 版本1配置
c.SwaggerDoc("v1", new OpenApiInfo 
{
    Title = "API v1", 
    Version = "1.0",
    Description = "旧版API"
});

// 版本2配置
c.SwaggerDoc("v2", new OpenApiInfo 
{
    Title = "API v2", 
    Version = "2.0",
    Description = "新版API"
});

// 版本选择器
c.DocInclusionPredicate((docName, apiDesc) =>
{
    if (!apiDesc.TryGetMethodInfo(out MethodInfo methodInfo)) return false;
    
    var versions = methodInfo.DeclaringType?
        .GetCustomAttributes(true)
        .OfType<ApiVersionAttribute>()
        .SelectMany(attr => attr.Versions);
    
    return versions?.Any(v => $"v{v}" == docName) ?? false;
});

// UI配置
app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "v1 文档");
    c.SwaggerEndpoint("/swagger/v2/swagger.json", "v2 文档");
    c.EnableDeepLinking();
    c.DisplayOperationId();
});
4.2 自定义操作过滤器
csharp 复制代码
// 添加请求头参数
c.OperationFilter<AddRequiredHeaderParameter>();

public class AddRequiredHeaderParameter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        if (operation.Parameters == null)
            operation.Parameters = new List<OpenApiParameter>();
        
        operation.Parameters.Add(new OpenApiParameter
        {
            Name = "X-Correlation-ID",
            In = ParameterLocation.Header,
            Description = "请求追踪ID",
            Required = false,
            Schema = new OpenApiSchema { Type = "string" }
        });
    }
}
4.3 文件上传支持
csharp 复制代码
c.OperationFilter<FileUploadOperationFilter>();

public class FileUploadOperationFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        var formFileParams = context.MethodInfo.GetParameters()
            .Where(p => p.ParameterType == typeof(IFormFile))
            .ToArray();
        
        if (formFileParams.Length > 0)
        {
            operation.RequestBody = new OpenApiRequestBody
            {
                Content = 
                {
                    ["multipart/form-data"] = new OpenApiMediaType
                    {
                        Schema = new OpenApiSchema
                        {
                            Type = "object",
                            Properties = 
                            {
                                ["file"] = new OpenApiSchema
                                {
                                    Description = "上传文件",
                                    Type = "string",
                                    Format = "binary"
                                }
                            }
                        }
                    }
                }
            };
        }
    }
}
4.4 自定义 UI 主题
csharp 复制代码
app.UseSwaggerUI(c =>
{
    // 注入自定义CSS
    c.InjectStylesheet("/swagger-ui/custom.css");
    
    // 注入JavaScript扩展
    c.InjectJavascript("/swagger-ui/custom.js");
    
    // 完全自定义首页
    c.IndexStream = () => Assembly.GetExecutingAssembly()
        .GetManifestResourceStream("YourNamespace.CustomIndex.html");
});

示例 custom.css

css 复制代码
.swagger-ui .topbar { 
    background-color: #2c3e50; 
}
.swagger-ui .info h2 {
    color: #3498db;
}

第五部分:测试与调试技巧

5.1 高级测试功能
csharp 复制代码
app.UseSwaggerUI(c =>
{
    // 预设请求头
    c.ConfigObject.PersistAuthorization = true;
    
    // 启用请求拦截器
    c.UseRequestInterceptor("(req) => { req.headers['X-Debug-Mode'] = 'true'; return req; }");
    
    // 启用响应拦截器
    c.UseResponseInterceptor("(res) => console.log('Response:', res); return res;");
});
5.2 预设测试数据
csharp 复制代码
[HttpPost]
public IActionResult CreateProduct(
    [FromBody] ProductCreateDto dto,
    /// <example>false</example>
    [FromQuery] bool isTest = false)
{
    // ...
}
5.3 自动化测试集成
csharp 复制代码
[Fact]
public async Task SwaggerDoc_ShouldBeValid()
{
    // 初始化测试服务
    var factory = new WebApplicationFactory<Program>();
    var client = factory.CreateClient();

    // 获取Swagger JSON
    var response = await client.GetAsync("/swagger/v1/swagger.json");
    var content = await response.Content.ReadAsStringAsync();

    // 验证JSON结构
    var openApiDoc = JsonSerializer.Deserialize<OpenApiDocument>(content);
    openApiDoc.Should().NotBeNull();
    openApiDoc.Paths.Should().ContainKey("/api/products");
    
    // 验证端点定义
    var operation = openApiDoc.Paths["/api/products"].Operations[OperationType.Get];
    operation.Responses.Should().ContainKey("200");
}

第六部分:生产环境最佳实践

6.1 安全加固方案
csharp 复制代码
app.MapWhen(ctx => ctx.Request.Path.StartsWithSegments("/swagger"), app =>
{
    // 基本认证中间件
    app.Use(async (context, next) =>
    {
        if (!context.User.Identity.IsAuthenticated)
        {
            context.Response.Headers["WWW-Authenticate"] = "Basic";
            context.Response.StatusCode = 401;
            return;
        }
        await next();
    });
    
    // IP白名单控制
    app.Use(async (context, next) =>
    {
        var allowedIPs = new[] { "192.168.1.0/24", "10.0.0.1" };
        var remoteIp = context.Connection.RemoteIpAddress.ToString();
        
        if (!allowedIPs.Any(ip => IPAddress.Parse(ip).Equals(remoteIp)))
        {
            context.Response.StatusCode = 403;
            return;
        }
        await next();
    });
    
    // 启用Swagger
    app.UseSwagger();
    app.UseSwaggerUI();
});
6.2 性能优化策略
csharp 复制代码
// 缓存Swagger JSON
app.UseSwagger(c => 
{
    c.PreSerializeFilters.Add((swaggerDoc, httpReq) => 
    {
        httpReq.HttpContext.Response.Headers["Cache-Control"] = "public, max-age=3600";
    });
});

// 按环境启用
if (app.Environment.IsDevelopment() || app.Environment.IsStaging())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}
6.3 自动化文档发布

CI/CD 集成示例 (GitHub Actions)

yaml 复制代码
name: Publish API Docs

on:
  release:
    types: [published]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v3
      
    - name: Setup .NET
      uses: actions/setup-dotnet@v2
      with:
        dotnet-version: '8.0.x'
        
    - name: Generate Swagger
      run: |
        dotnet build
        dotnet swagger tofile --output swagger.json bin/Debug/net8.0/YourApi.dll v1
        
    - name: Deploy to Azure Storage
      uses: azure/CLI@v1
      with:
        inlineScript: |
          az storage blob upload-batch \
            --account-name ${{ secrets.STORAGE_ACCOUNT }} \
            --source ./ \
            --destination '$web/api-docs' \
            --pattern 'swagger.json' \
            --auth-mode login

第七部分:高级场景与扩展

7.1 GraphQL 集成
csharp 复制代码
// 添加GraphQL支持
builder.Services.AddGraphQLServer()
    .AddQueryType<Query>()
    .PublishSchemaDefinition(c => c
        .SetTitle("Products API")
        .PublishToSwagger());

// Swagger配置
c.DocumentFilter<GraphQLDocumentFilter>();

public class GraphQLDocumentFilter : IDocumentFilter
{
    public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
    {
        swaggerDoc.Paths.Add("/graphql", new OpenApiPathItem
        {
            Operations = new Dictionary<OperationType, OpenApiOperation>
            {
                [OperationType.Post] = new OpenApiOperation
                {
                    Summary = "GraphQL 端点",
                    RequestBody = new OpenApiRequestBody
                    {
                        Content = new Dictionary<string, OpenApiMediaType>
                        {
                            ["application/json"] = new OpenApiMediaType
                            {
                                Schema = new OpenApiSchema
                                {
                                    Type = "object",
                                    Properties = new Dictionary<string, OpenApiSchema>
                                    {
                                        ["query"] = new OpenApiSchema { Type = "string" },
                                        ["variables"] = new OpenApiSchema { Type = "object" }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        });
    }
}
7.2 Webhook 文档支持
csharp 复制代码
c.AddWebhookEndpoint("OrderWebhook", new OpenApiWebhook
{
    Description = "订单状态变更通知",
    Post = new OpenApiPathItem
    {
        Summary = "接收订单状态更新",
        Operations = new Dictionary<OperationType, OpenApiOperation>
        {
            [OperationType.Post] = new OpenApiOperation
            {
                RequestBody = new OpenApiRequestBody
                {
                    Content = new Dictionary<string, OpenApiMediaType>
                    {
                        ["application/json"] = new OpenApiMediaType
                        {
                            Schema = new OpenApiSchema
                            {
                                Reference = new OpenApiReference
                                {
                                    Type = ReferenceType.Schema,
                                    Id = nameof(OrderWebhookPayload)
                                }
                            }
                        }
                    }
                },
                Responses = new OpenApiResponses
                {
                    ["200"] = new OpenApiResponse { Description = "成功接收" }
                }
            }
        }
    }
});
7.3 多语言文档支持
csharp 复制代码
// 中文文档
c.SwaggerDoc("zh-CN", new OpenApiInfo
{
    Title = "订单服务 API",
    Version = "v1",
    Description = "电商平台订单管理系统 - 中文版"
});

// 英文文档
c.SwaggerDoc("en-US", new OpenApiInfo
{
    Title = "Order Service API",
    Version = "v1",
    Description = "E-commerce Order Management System"
});

// 基于Accept-Language自动切换
app.Use(async (context, next) =>
{
    var culture = context.Request.GetTypedHeaders()
        .AcceptLanguage?.FirstOrDefault()?.Value.Value ?? "zh-CN";
    
    context.Items["SwaggerDoc"] = culture.Contains("en") ? "en-US" : "zh-CN";
    await next();
});

app.UseSwagger(c => 
{
    c.PreSerializeFilters.Add((doc, req) => 
    {
        var culture = req.HttpContext.Items["SwaggerDoc"] as string ?? "zh-CN";
        doc.Info = new OpenApiInfo
        {
            Title = culture == "en-US" ? "Order Service" : "订单服务",
            Version = "v1",
            Description = culture == "en-US" 
                ? "Order Management System" 
                : "订单管理系统"
        };
    });
});

相关推荐
探索java25 分钟前
Netty Channel详解:从原理到实践
java·后端·netty
追逐时光者35 分钟前
2025 年全面的 C#/.NET/.NET Core 学习路线集合,学习不迷路!
后端·.net
SchuylerEX1 小时前
第六章 JavaScript 互操(2).NET调用JS
前端·c#·.net·blazor·ui框架
★YUI★1 小时前
学习游戏制作记录(制作系统与物品掉落系统)8.16
学习·游戏·ui·unity·c#
ankleless2 小时前
Spring Boot 实战:从项目搭建到部署优化
java·spring boot·后端
用户4822137167752 小时前
C++——静态数组、动态数组
后端
用户4822137167752 小时前
C++—— String 类详解
后端
BothSavage3 小时前
Java获取被nginx代理的emqx客户端真实ip
后端
David爱编程3 小时前
为什么线程不是越多越好?一文讲透上下文切换成本
java·后端