是否可以在 ASP .NET Core 中使用 Swashbuckle 在 Swagger 2.0 和 Open API 3 格式中公开相同的 Swagger JSON?

Posted

技术标签:

【中文标题】是否可以在 ASP .NET Core 中使用 Swashbuckle 在 Swagger 2.0 和 Open API 3 格式中公开相同的 Swagger JSON?【英文标题】:Is it possible to expose the same Swagger JSON in both Swagger 2.0 and Open API 3 formats with Swashbuckle in ASP .NET Core? 【发布时间】:2021-07-27 14:02:54 【问题描述】:

我们有一个仅适用于 Swagger 2.0 JSON 格式的旧版应用程序。对于我们希望使用 Open API 格式的其他所有内容。

Swashbuckle .NET Core 有什么方法可以在不同的 URL 下以不同格式公开 JSON?看起来UseSwagger 方法选项中的SerializeAsV2 属性对于所有端点都是全局的。

基本上我希望以下端点包含不同格式的相同 API 数据。

/swagger/v1/openapi/swagger.json
/swagger/v1/swagger2/swagger.json

【问题讨论】:

【参考方案1】:

另一种方法是拆分请求管道:

// serve v3 from /swagger/v1/swagger.json
app.UseSwagger(o => o.RouteTemplate = "swagger/documentName/swagger.json");

// serve v2 from /swagger2/v1/swagger.json
app.Map("/swagger2", swaggerApp => 
    swaggerApp.UseSwagger(options => 
        // note the dropped prefix "swagger/"
        options.RouteTemplate = "documentName/swagger.json";
        options.SerializeAsV2 = true;
    )
);

【讨论】:

这真的很优雅,效果很好。谢谢!【参考方案2】:

您可以将 OpenAPI 文档序列化为 V2 并自行提供。以SwaggerMiddleware为参考:

第一次注册SwaggerGenerator

services.AddTransient<SwaggerGenerator>();

然后注入SwaggerGenerator 并构建文档。从端点或控制器提供它。您可以将版本作为路径参数来决定提供哪个版本。

app.UseEndpoints(e =>

    // ...
    e.MapGet("/swagger/documentName/swagger.version.json", context =>
    
        var documentName = context.Request.RouteValues.GetValueOrDefault("documentName", null) as string;
        var version = context.Request.RouteValues.GetValueOrDefault("version", null) as string;
        if (documentName is null || version is null)
        
            context.Response.StatusCode = StatusCodes.Status400BadRequest;
            return Task.CompletedTask;
        

        // inject SwaggerGenerator
        var swaggerGenerator = context.RequestServices.GetRequiredService<SwaggerGenerator>();
        var doc = swaggerGenerator.GetSwagger(documentName);

        // serialize the document as json
        using var writer = new StringWriter(CultureInfo.InvariantCulture);
        var serializer = new OpenApiJsonWriter(writer);
        if (version == "v2")
        
            doc.SerializeAsV2(serializer);
        
        else
        
            doc.SerializeAsV3(serializer);
        
        var json = writer.ToString();

        // serve it as json
        context.Response.ContentType = MediaTypeNames.Application.Json;
        return context.Response.WriteAsync(json, new UTF8Encoding(false));
    );
);

当您访问/swagger/v1/openapi.v2.json 时,您将获得序列化为 v2 的 OpenAPI 文档。


  "swagger": "2.0",
  "info": 
    "title": "ApiPlayground",
    "version": "1.0"
  ,
  "paths":  ... 

/swagger/v1/openapi.v3.json 会给您序列化为 v3 的文档:


  "openapi": "3.0.1",
  "info": 
    "title": "ApiPlayground",
    "version": "1.0"
  ,
  "paths":  ... ,
  "components":  ... 

【讨论】:

我还需要调用UseSwagger() 方法吗?感谢您提供详细的示例。 不,它可以保留,也可以完全删除。但是您可能需要更新SwaggerUI 中间件配置。 app.UseSwaggerUI(c =&gt; c.SwaggerEndpoint("/swagger/v1/swagger.v2.json", "ApiPlayground v1"));

以上是关于是否可以在 ASP .NET Core 中使用 Swashbuckle 在 Swagger 2.0 和 Open API 3 格式中公开相同的 Swagger JSON?的主要内容,如果未能解决你的问题,请参考以下文章

asp.net core 中的 MVC 架构模式

如何在ASP.NET Core 中使用IHttpClientFactory

ASP.NET Core 2.0 - Windows Auth 与 LDAP 组到角色

在 ASP.NET Core 2.1 中使用 cookie [重复]

ASP.NET Core 托管捆绑包 5 是不是也可以运行 .NET/ASP.NET Core 2.1 应用程序?

ASP.NET.Core中使用AutoMapper