如何使用我自己的自定义设计来自定义 swagger UI

How to customize the swagger UI using my own custom design

我想使用自己的自定义设计来自定义 swagger UI。我在启动时有以下配置。

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddSwaggerGen(c =>
    {
        c.DocumentFilter<DescriptionsDocumentFilter>();

        c.SwaggerDoc("v1", new OpenApiInfo { Title = "LoggerDemo", Version = "v1" });

        var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
        var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
        c.IncludeXmlComments(xmlPath);
    });
    services.AddHttpClient();
    services.AddMemoryCache();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseSwagger(o =>
        {
            o.RouteTemplate = "docs/{documentName}/docs.json";
        });

        app.UseSwaggerUI(c =>
        {
            c.RoutePrefix = "docs";
            c.SwaggerEndpoint("/docs/v1/docs.json", "Geo API");

            c.IndexStream = () => GetType().Assembly.GetManifestResourceStream
            (
                GetType().Namespace + ".Resources.Swagger_Custom_index.html"
            );
        });
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

以下是我遵循的步骤:

app.UseSwaggerUI(c =>
{
    c.IndexStream = () => GetType().Assembly.GetManifestResourceStream
    (
        GetType().Namespace + ".Resources.Swagger_Custom_index.html"
    );
});

但是我很难访问自定义 HTML 文件,如何访问自定义 HTML 文件?我应该使用什么 URL 来访问这些文件?

您需要在 .csproj 文件中使用 EmbeddedResource 指令将 HTML 文件嵌入到 DLL 中:

Resources/swagger.html

<!-- replace this with the actual swagger.html -->
<h1>hello swagger</h1>

.csproj

<Project Sdk="Microsoft.NET.Sdk">
    <!-- ... -->
    <ItemGroup>
        <Content Remove="Resources\*" />
        <EmbeddedResource Include="Resources\*" />
    </ItemGroup>
</Project>

然后你可以通过Assembly.GetManifestResourceStream访问它:

// Startup.Configure

app.UseSwaggerUI(options =>
{
    options.IndexStream = () => GetType().Assembly.GetManifestResourceStream($"{GetType().Namespace}.Resources.swagger.html");
});

奖励:在 Swagger 外部生成 OpenAPI 文档:

SwaggerMiddleware 处理服务 OpenAPI 文档。我们可以将其作为自己构建文档的参考。

首先用 DI 注册 SwaggerGenerator

// Startup.Configure
services.AddTransient<SwaggerGenerator>();

然后将它注入到 class 中,这里我使用端点直接为它提供服务:

// Startup.Configure
app.UseEndpoints(e =>
{
    // ...
    e.MapGet("/openapi.json", context =>
    {
        // inject SwaggerGenerator
        var swaggerGenerator = context.RequestServices.GetRequiredService<SwaggerGenerator>();
        // document name is defined in Startup.ConfigureServices method inside the AddSwaggerGen call
        var doc = swaggerGenerator.GetSwagger("v1");

        // serialize the document as json
        using var writer = new StringWriter(CultureInfo.InvariantCulture);
        var serializer = new OpenApiJsonWriter(writer);
        doc.SerializeAsV3(serializer);
        var json = writer.ToString(); // this is the openapi document
        
        // serve it as json
        context.Response.ContentType = MediaTypeNames.Application.Json;
        return context.Response.WriteAsync(json, new UTF8Encoding(false));
    });
});