如何在编译时为ASP.NET项目中的每个Controller生成单独的OpenAPI Swagger.json文件?

v9tzhpje  于 2023-04-06  发布在  .NET
关注(0)|答案(1)|浏览(101)

我们的ASP.NET Core Web应用程序有一个不断增长的控制器列表。在项目的构建时,我希望以编程方式为每个控制器生成一个单独的单独的swagger.json文件。(我们需要磁盘上的这些文件,以便由另一个进程拾取。)
我尝试过使用NSwag和Swashbuckle。我将它们配置为为每个Controller生成一个Document,但它们的构建时CLI库似乎只支持为单个指定文档生成单个swagger.json文件。我不想手动硬编码任何特定的文档或Controller引用。
https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/2578
https://github.com/RicoSuter/NSwag/issues/4292

sr4lhrrt

sr4lhrrt1#

下面是我使用NSWag提出的一个解决方案,但它最终可以使用任何可以生成文件的库。
基本上发生的是msbuild步骤“引导”你的web应用程序,在它被构建之后,这个过程检查一个特殊的标志(generate-swagger),以表明你只想生成swagger,然后退出这个过程。

Helper扩展方式

public static class WebApplicationExtensions
{
    public static async Task GenerateSwaggerFilesAsync(this WebApplication app, string folderPath)
    {
        Console.WriteLine($"Generating Swagger Files > \"{Path.GetFullPath(folderPath)}\"");

        if (Directory.Exists(folderPath))
        {
            Directory.Delete(folderPath, true);
        }

        var apiGroups = app.Services.GetService<IApiDescriptionGroupCollectionProvider>()!.ApiDescriptionGroups;
        foreach (var apiGroup in apiGroups.Items)
        {
            var settings = new AspNetCoreOpenApiDocumentGeneratorSettings
            {
                Title = apiGroup.GroupName,
                DocumentName = apiGroup.GroupName,
                ApiGroupNames = new string[] { apiGroup.GroupName! },
                SchemaType = NJsonSchema.SchemaType.OpenApi3,
                SerializerSettings = new JsonSerializerSettings
                {
                    ContractResolver = new CamelCasePropertyNamesContractResolver()
                }
            };

            // TODO: Add any processors you want
            settings.OperationProcessors.Add(new ActionNameOperationProcessor());

            var apiGenerator = new AspNetCoreOpenApiDocumentGenerator(settings);

            var apiDocument = await apiGenerator.GenerateAsync(apiGroups);

            var json = apiDocument.ToJson();

            var subFolder = folderPath.UrlCombine(apiGroup.GroupName!);

            Directory.CreateDirectory(subFolder);

            var file = $"{subFolder}/swagger.json";

            await File.WriteAllTextAsync(file, json);
        }

        if (app.Configuration["generate-swagger"] == "true")
        {
            await app.StopAsync();
            Environment.Exit(0);
        }
    }

    public class ActionNameOperationProcessor : IOperationProcessor
    {
        public bool Process(OperationProcessorContext context)
        {
            var aspNetCoreContext = (AspNetCoreOperationProcessorContext)context;
            var controllerActionDescriptor = (ControllerActionDescriptor)aspNetCoreContext.ApiDescription.ActionDescriptor;

            context.OperationDescription.Operation.OperationId = controllerActionDescriptor.ActionName;
            context.OperationDescription.Operation.Tags = new List<string> { aspNetCoreContext.ApiDescription.GroupName! };

            return true;
        }
    }

}

在Program/Startup.cs中调用并提供目录

app.MapControllers();

// Generate Swagger
await app.GenerateSwaggerFilesAsync("./.swagger");

app.Run();

将此添加到您的web .csproj中,以便在构建时生成

<Target Name="GenerateSwagger" AfterTargets="Build" Condition="'$(Configuration)'=='Debug'">
    <Exec WorkingDirectory="$(RunWorkingDirectory)" Command="$(RunCommand) --generate-swagger true" />
</Target>

相关问题