Swagger 版本控制不起作用。它显示所有端点,尽管选择了 API 版本
Posted
技术标签:
【中文标题】Swagger 版本控制不起作用。它显示所有端点,尽管选择了 API 版本【英文标题】:Swagger versioning is not working. It displays all endpoints, despite the selected API version 【发布时间】:2020-09-04 08:57:56 【问题描述】:全部!
我在 ASP.NET Core 3.1 应用程序中使用 Swagger。
我需要为新版本的 API 创建一个端点,并使用与以前版本相同的路由。
我的控制器是:
namespace Application.Controllers
[ApiVersion("1")]
[ApiVersion("2")]
[ApiController]
[Route("api/vversion:apiVersion")]
public class CustomController: ControllerBase
[HttpGet]
[Route("result")]
public IActionResult GetResult()
return Ok("v1")
[HttpGet]
[MapToApiVersion("2")]
[Route("result")]
public IActionResult GetResult(int number)
return Ok("v2")
我的配置:
services.AddApiVersioning(
options =>
options.ReportApiVersions = true;
);
services.AddSwaggerGen(c =>
c.SwaggerDoc($"v1", new OpenApiInfo Title = "api1", Version = $"v1" );
c.SwaggerDoc($"v2", new OpenApiInfo Title = "api2", Version = $"v2" );
c.OperationFilter<RemoveVersionParameterFilter>();
c.DocumentFilter<ReplaceVersionWithExactValueInPathFilter>();
c.EnableAnnotations();
);
app.UseSwagger().UseSwaggerUI(c =>
c.SwaggerEndpoint($"/swagger/v1/swagger.json", $"api1 v1");
c.SwaggerEndpoint($"/swagger/v2/swagger.json", $"api2 v2");
);
加载后出现错误:Fetch error undefined /swagger/v1/swagger.json 但是如果我将第二条路由更改为“resutlTwo”,我可以大摇大摆地观察两个端点,忽略当前版本(api1 v1 或 api2 v2)
如何才能看到每个 API 版本只有 1 个端点?
【问题讨论】:
【参考方案1】:感谢Roar S. 的帮助!
我刚刚加了
services.AddApiVersioning(apiVersioningOptions =>
apiVersioningOptions.ReportApiVersions = true;
apiVersioningOptions.ApiVersionReader = new UrlSegmentApiVersionReader();
);
和
c.DocInclusionPredicate((version, desc) =>
var endpointMetadata = desc.ActionDescriptor.EndpointMetadata;
if (!desc.TryGetMethodInfo(out MethodInfo methodInfo))
return false;
var specificVersion = endpointMetadata
.Where(data => data is MapToApiVersionAttribute)
.SelectMany(data => (data as MapToApiVersionAttribute).Versions)
.Select(apiVersion => apiVersion.ToString())
.SingleOrDefault();
if (!string.IsNullOrEmpty(specificVersion))
return $"vspecificVersion" == version;
var versions = endpointMetadata
.Where(data => data is ApiVersionAttribute)
.SelectMany(data => (data as ApiVersionAttribute).Versions)
.Select(apiVersion => apiVersion.ToString());
return versions.Any(v => $"vv" == version);
);
并将端点拆分为不同的文件。
【讨论】:
感谢分享您的工作配置。是的,我的配置有点过分,但我想展示我是如何测试你的代码的。在许多情况下,可能还缺少其他部分。【参考方案2】:我刚刚使用此设置测试了您的情况。您缺少UrlSegmentApiVersionReader
。
public class SwaggerOptions
public string Title get; set;
public string JsonRoute get; set;
public string Description get; set;
public List<Version> Versions get; set;
public class Version
public string Name get; set;
public string UiEndpoint get; set;
在启动#ConfigureServices 中
// Configure versions
services.AddApiVersioning(apiVersioningOptions =>
apiVersioningOptions.ReportApiVersions = true;
apiVersioningOptions.ApiVersionReader = new UrlSegmentApiVersionReader();
);
// Register the Swagger generator, defining 1 or more Swagger documents
services.AddSwaggerGen(swaggerGenOptions =>
var swaggerOptions = new SwaggerOptions();
Configuration.GetSection("Swagger").Bind(swaggerOptions);
foreach (var currentVersion in swaggerOptions.Versions)
swaggerGenOptions.SwaggerDoc(currentVersion.Name, new OpenApiInfo
Title = swaggerOptions.Title,
Version = currentVersion.Name,
Description = swaggerOptions.Description
);
swaggerGenOptions.DocInclusionPredicate((version, desc) =>
if (!desc.TryGetMethodInfo(out MethodInfo methodInfo))
return false;
var versions = methodInfo.DeclaringType.GetConstructors()
.SelectMany(constructorInfo => constructorInfo.DeclaringType.CustomAttributes
.Where(attributeData => attributeData.AttributeType == typeof(ApiVersionAttribute))
.SelectMany(attributeData => attributeData.ConstructorArguments
.Select(attributeTypedArgument => attributeTypedArgument.Value)));
return versions.Any(v => $"v" == version);
);
swaggerGenOptions.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, $"Assembly.GetExecutingAssembly().GetName().Name.xml"));
... some filter settings here
);
在启动#配置中
var swaggerOptions = new SwaggerOptions();
Configuration.GetSection("Swagger").Bind(swaggerOptions);
app.UseSwagger(option => option.RouteTemplate = swaggerOptions.JsonRoute);
app.UseSwaggerUI(option =>
foreach (var currentVersion in swaggerOptions.Versions)
option.SwaggerEndpoint(currentVersion.UiEndpoint, $"swaggerOptions.Title currentVersion.Name");
);
appsettings.json
"Swagger":
"Title": "App title",
"JsonRoute": "swagger/documentName/swagger.json",
"Description": "Some text",
"Versions": [
"Name": "2.0",
"UiEndpoint": "/swagger/2.0/swagger.json"
,
"Name": "1.0",
"UiEndpoint": "/swagger/1.0/swagger.json"
]
此代码与我在 SO 上处理的相关问题非常相似。
【讨论】:
以上是关于Swagger 版本控制不起作用。它显示所有端点,尽管选择了 API 版本的主要内容,如果未能解决你的问题,请参考以下文章
Fluent Assertions 检查是不是所有端点都具有特定的 swagger 属性