You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 8 Lambda Annotations集成NSwag生成Swagger文档求助

.NET 8 + Lambda Annotations 生成适配Redoc/NSwag的Swagger文档方案

Lambda Annotations依赖LambdaFunctionAttribute定义路由和HTTP方法,而非传统的HttpGet/HttpPost特性,导致常规NSwag自动扫描的方式失效,以下是两种可行的解决方案:

方案一:手动构建OpenAPI规范

直接基于OpenAPI标准手动定义API的路由、请求响应模型,再序列化为JSON/YML格式供Redoc/NSwag使用:

  1. 引入Swashbuckle相关NuGet包(用于OpenAPI对象模型和序列化):

    Install-Package Swashbuckle.AspNetCore.Swagger
    Install-Package Swashbuckle.AspNetCore.SwaggerGen
    
  2. 编写代码生成OpenAPI文档:

    using Microsoft.OpenApi.Models;
    using Newtonsoft.Json;
    
    public OpenApiDocument BuildSwaggerDocument()
    {
        var doc = new OpenApiDocument
        {
            Info = new OpenApiInfo 
            { 
                Title = "Lambda Annotations API", 
                Version = "v1",
                Description = "基于.NET 8 Lambda Annotations构建的API文档"
            },
            Paths = new OpenApiPaths
            {
                ["/api/users/{id}"] = new OpenApiPathItem
                {
                    Get = new OpenApiOperation
                    {
                        Summary = "根据ID获取用户详情",
                        Parameters = new List<OpenApiParameter>
                        {
                            new OpenApiParameter
                            {
                                Name = "id",
                                In = ParameterLocation.Path,
                                Required = true,
                                Schema = new OpenApiSchema { Type = "string" }
                            }
                        },
                        Responses = new OpenApiResponses
                        {
                            ["200"] = new OpenApiResponse 
                            { 
                                Description = "成功返回用户信息",
                                Content = new Dictionary<string, OpenApiMediaType>
                                {
                                    ["application/json"] = new OpenApiMediaType
                                    {
                                        Schema = new OpenApiSchema { Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "User" } }
                                    }
                                }
                            },
                            ["404"] = new OpenApiResponse { Description = "用户不存在" }
                        }
                    }
                }
            },
            Components = new OpenApiComponents
            {
                Schemas = new Dictionary<string, OpenApiSchema>
                {
                    ["User"] = new OpenApiSchema
                    {
                        Type = "object",
                        Properties = new Dictionary<string, OpenApiSchema>
                        {
                            ["Id"] = new OpenApiSchema { Type = "string" },
                            ["UserName"] = new OpenApiSchema { Type = "string" },
                            ["Email"] = new OpenApiSchema { Type = "string", Format = "email" }
                        },
                        Required = new List<string> { "Id", "UserName" }
                    }
                }
            }
        };
    
        return doc;
    }
    
    // 序列化为JSON
    public string GetSwaggerJson()
    {
        var doc = BuildSwaggerDocument();
        return JsonConvert.SerializeObject(doc, Formatting.Indented);
    }
    
  3. 添加Lambda函数暴露Swagger文档端点:

    using Amazon.Lambda.Annotations;
    using Amazon.Lambda.Annotations.APIGateway;
    
    [LambdaFunction(Route = "swagger/json", Method = "GET")]
    public IHttpResult ReturnSwaggerJson()
    {
        var swaggerJson = GetSwaggerJson();
        return HttpResults.Ok(swaggerJson).WithContentType("application/json");
    }
    

方案二:反射自动生成规范

通过反射扫描项目中所有LambdaFunctionAttribute标记的方法,自动提取路由、HTTP方法、参数和返回类型,结合Swashbuckle的SchemaGenerator生成完整的OpenAPI文档:

  1. 同样先引入Swashbuckle相关NuGet包,然后编写反射扫描逻辑:

    using System.Reflection;
    using Amazon.Lambda.Annotations;
    using Microsoft.OpenApi.Models;
    using Swashbuckle.AspNetCore.SwaggerGen;
    
    public OpenApiDocument GenerateSwaggerFromLambdaAnnotations()
    {
        var doc = new OpenApiDocument
        {
            Info = new OpenApiInfo { Title = "Auto-Generated Lambda API", Version = "v1" },
            Paths = new OpenApiPaths(),
            Components = new OpenApiComponents { Schemas = new Dictionary<string, OpenApiSchema>() }
        };
    
        var schemaGenerator = new SchemaGenerator(new SchemaGeneratorOptions());
        var schemaRepo = new SchemaRepository();
    
        // 扫描当前程序集中所有带LambdaFunctionAttribute的方法
        var lambdaMethods = Assembly.GetExecutingAssembly().GetTypes()
            .SelectMany(t => t.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static))
            .Where(m => m.GetCustomAttribute<LambdaFunctionAttribute>() != null);
    
        foreach (var method in lambdaMethods)
        {
            var lambdaAttr = method.GetCustomAttribute<LambdaFunctionAttribute>();
            var route = lambdaAttr.Route ?? $"/{method.Name}";
            var httpMethod = lambdaAttr.Method?.ToUpper() ?? "POST";
    
            // 初始化PathItem
            if (!doc.Paths.ContainsKey(route))
            {
                doc.Paths[route] = new OpenApiPathItem();
            }
    
            // 创建OpenApiOperation
            var operation = new OpenApiOperation { Summary = $"执行{method.Name}方法" };
    
            // 处理方法参数(作为查询参数或请求体)
            foreach (var param in method.GetParameters())
            {
                if (param.ParameterType.IsPrimitive || param.ParameterType == typeof(string))
                {
                    // 简单类型作为查询参数
                    operation.Parameters.Add(new OpenApiParameter
                    {
                        Name = param.Name,
                        In = ParameterLocation.Query,
                        Required = !param.IsOptional,
                        Schema = schemaGenerator.GenerateSchema(param.ParameterType, schemaRepo)
                    });
                }
                else
                {
                    // 复杂类型作为请求体
                    operation.RequestBody = new OpenApiRequestBody
                    {
                        Content = new Dictionary<string, OpenApiMediaType>
                        {
                            ["application/json"] = new OpenApiMediaType
                            {
                                Schema = schemaGenerator.GenerateSchema(param.ParameterType, schemaRepo)
                            }
                        }
                    };
                }
            }
    
            // 处理返回类型
            var returnType = method.ReturnType;
            if (returnType != typeof(void))
            {
                // 处理Task<T>的情况
                if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>))
                {
                    returnType = returnType.GetGenericArguments()[0];
                }
    
                operation.Responses["200"] = new OpenApiResponse
                {
                    Description = "请求成功",
                    Content = new Dictionary<string, OpenApiMediaType>
                    {
                        ["application/json"] = new OpenApiMediaType
                        {
                            Schema = schemaGenerator.GenerateSchema(returnType, schemaRepo)
                        }
                    }
                };
            }
    
            // 将Operation绑定到对应的HTTP方法
            switch (httpMethod)
            {
                case "GET": doc.Paths[route].Get = operation; break;
                case "POST": doc.Paths[route].Post = operation; break;
                case "PUT": doc.Paths[route].Put = operation; break;
                case "DELETE": doc.Paths[route].Delete = operation; break;
            }
    
            // 将生成的Schema添加到Components中
            foreach (var schema in schemaRepo.Schemas)
            {
                if (!doc.Components.Schemas.ContainsKey(schema.Key))
                {
                    doc.Components.Schemas.Add(schema.Key, schema.Value);
                }
            }
        }
    
        return doc;
    }
    
  2. 同样添加Lambda函数返回生成的Swagger文档,后续即可将这个JSON/YML地址配置到Redoc或NSwag中使用。

注意事项

  • 反射方案需要处理复杂的参数/返回类型场景(比如泛型、嵌套对象),可以根据实际项目需求调整逻辑。
  • 生成的Swagger文档需要定期更新,或者在构建时自动生成并打包部署。

内容的提问来源于stack exchange,提问作者user24871458

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 20:21:09