#asp.net-core #swashbuckle.aspnetcore
Вопрос:
У нас есть устаревшее приложение, которое работает только с форматом JSON Swagger 2.0. Для всего остального мы хотели бы использовать открытый формат API.
Есть ли какой-нибудь способ с помощью Swashbuckle .NET Core предоставляет JSON в разных форматах по отдельным URL-адресам? Похоже SerializeAsV2
, что свойство в параметрах UseSwagger
метода является глобальным для всех конечных точек.
В принципе, я хотел бы иметь следующие конечные точки, которые содержат одни и те же данные 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;
})
);
Комментарии:
1. Это действительно элегантно и отлично работает. Спасибо!
Ответ №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
получите документ OpenAPI , сериализованный как версия 2.
{
"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": { ... }
}
Комментарии:
1. Мне все еще нужно вызывать
UseSwagger()
метод? Спасибо за подробный пример.2. Нет, он может остаться, или вы можете удалить его совсем. Но вам может потребоваться обновить
SwaggerUI
конфигурацию промежуточного программного обеспечения.app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.v2.json", "ApiPlayground v1"));