尝试通过 httpclient 调用访问 IHostedService 中的 swagger.json 时出现超时错误

时间:2021-07-23 12:27:06

标签: c# asp.net-core swagger asp.net-core-5.0 swashbuckle.aspnetcore

我想访问 swagger.json 文件并将其反序列化并将其存储到缓存中。

我正在 IHostedService 中进行异步调用。

public class InitializeCacheService : IHostedService
{
    private IMemoryCache _cache;
    public static readonly string swaggerJson = "swagger.json";
    private readonly HttpClient _httpClient;
    private readonly IServiceProvider _serviceProvider;

    public InitializeCacheService(IMemoryCache cache, HttpClient client, IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
        _httpClient = client;

        _cache = cache;
    }
    public async Task StartAsync(CancellationToken cancellationToken)
    {
        if (!_cache.TryGetValue(swaggerJson, out SwaggerDocumentCache cacheEntry))
        {
            _httpClient.BaseAddress = new Uri("https://localhost:44397");

            var response = await _httpClient.GetAsync("swagger/v1/swagger.json");

            response.EnsureSuccessStatusCode();

            using var responseStream = await response.Content.ReadAsStreamAsync();

            cacheEntry = await JsonSerializer.DeserializeAsync
                <SwaggerDocumentCache>(responseStream);

            var cacheEntryOptions = new MemoryCacheEntryOptions()
                  .SetSlidingExpiration(TimeSpan.FromSeconds(3));

            _cache.Set(swaggerJson, cacheEntry, cacheEntryOptions);
        }
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        return Task.CompletedTask;
    }
}

但是应用程序一直在旋转,并且正在超时 var response = await _httpClient.GetAsync("swagger/v1/swagger.json");

它给出的错误是:

<块引用>

IOException: 无法从传输连接读取数据:由于线程退出或应用程序请求,I/O 操作已中止。

我在这里缺少什么?访问 swagger.json 以构建自定义 API Playground 应用程序的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

SwaggerMiddleware 处理提供 OpenAPI 文档。我们可以使用它作为参考来自己构建文档。

首先向 DI 注册 SwaggerGenerator

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

然后将其注入到一个类中,这里我使用一个端点直接为其提供服务:

// 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));
    });
});

答案 1 :(得分:0)

我相信实际的 JSON 不一定是一个有效的端点,它本身可能是一个问题。您是否尝试过在端点路由上没有明确文件名的呼叫?