健康检查端点生成的 HealthReport 对象结构冻结 Swagger 文档页面

HealthReport object structure produced by health checks endpoint freezes Swagger docs page

我为我的 .Net 5 Web API 项目启用了运行状况检查

public sealed class Startup
{
    public void ConfigureServices(IServiceCollection serviceCollection)
    {
        serviceCollection.AddHealthChecks();

        // ...
    }

    public void Configure(IApplicationBuilder applicationBuilder, IWebHostEnvironment webHostEnvironment)
    {
        // ...

        applicationBuilder.UseHealthChecks("/health");

        // ...
    }
}

不幸的是,health 端点没有出现在 swagger 文档中。这就是为什么我创建了一个额外的控制器

[ApiController]
[Route("[controller]")]
public sealed class HealthController : ControllerBase
{
    private readonly HealthCheckService _healthCheckService;

    public HealthController(HealthCheckService healthCheckService)
    {
        _healthCheckService = healthCheckService;
    }

    [HttpGet]
    public async Task<ActionResult<HealthReport>> GetHealthIndication()
    {
        HealthReport healthReport = await _healthCheckService.CheckHealthAsync();

        if (healthReport.Status == HealthStatus.Healthy)
        {
            return Ok(healthReport);
        }

        int serviceUnavailableStatusCode = (int) HttpStatusCode.ServiceUnavailable;
        
        return StatusCode(serviceUnavailableStatusCode, healthReport);
    }
}

当运行 应用程序 Swagger 生成了很多模型。打开健康端点时,页面会冻结数秒,因为它必须加载 HealthReport 对象结构。

TLDR;

在 Swagger 配置中为异常 class 添加架构映射。

services.AddSwaggerGen(c =>
            {
                c.MapType<Exception>(() => new OpenApiSchema { Type = "object" });
            });

此代码会将带有异常 class 的架构转换为对象,因此您在客户端面临的行为将最小化。


解释:

根本原因: Swagger 冻结,因为 swagger javascript 客户端正在尝试基于从 swagger json.

获取的模式创建示例模型

如果您查看异常 class,它包含大量嵌套的属性和类型。如果我们指示 swagger 生成器将异常 class 视为创建的 JSON 文件中的一个简单对象,客户端就不必花时间创建嵌套对象。 (或者您也可以在此转换中包含 TimeSpan class)。

有多种方法可以解决这个问题:

  1. 如上所述,简单地指示 Swagger 生成器在配置级别本身映射类型。
  2. 如果您想基于特定的 Action(Swagger 上下文中的 Operation)或 Controller(Swagger 上下文中的 Document)创建模式,那么您可以实现各自的过滤器并即时修改 Swagger 文档内容。 https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/master/README.md#override-schema-for-specific-types
  3. 创建您自己的响应模型:这是有道理的,因为随着时间的推移,HealthReport 的架构可能会发生变化,因此服务的输出可能会随着时间的推移而发生变化而没有意识到。

Do I even have to create my own controller, aren't there any integrations yet? I'm looking for a solution.UseHealthChecks(HealthController.GetHealthIndication)

Swashbuckle(Swagger codegen 和 UI)使用反射和程序集文档(.xml 文件)创建 swagger 文档,因此它不会扫描控制器的其他程序集。