I wanted to access the swagger.json file and deserialized it and store it into the cache.
I am making the async call in the 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;
}
}
But the application is spinning and spinning and it is getting time out in
var response = await _httpClient.GetAsync("swagger/v1/swagger.json");
The error it is giving is:
IOException: Unable to read data from the transport connection: The I/O operation has been aborted because of either a thread exit or an application request.
What I am missing here? What is the correct way of accessing the swagger.json
to build a custom API playground application?
SwaggerMiddleware handles serving OpenAPI documents. We can use that as reference to build the document ourselves.
First register SwaggerGenerator
with DI:
// Startup.Configure
services.AddTransient<SwaggerGenerator>();
Then inject it inside a class, here I'm using an endpoint to serve it directly:
// 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));
});
});