问题描述
全部!
我在ASP.NET Core 3.1应用程序中使用Swagger。
我需要为API的新版本创建一个端点,并使用与先前版本相同的路由。
我的控制器是:
namespace Application.Controllers
{
[ApiVersion("1")]
[ApiVersion("2")]
[ApiController]
[Route("api/v{version: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");
});
加载后出现错误:获取错误未定义/swagger/v1/swagger.json 但是,如果我将第二条路径更改为“ resutlTwo”,则可以不经意地观察两个端点,而忽略当前版本(api1 v1或api2 v2)
如何每个API版本只能看到1个端点?
解决方法
我刚刚通过此设置测试了您的情况。您缺少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; }
}
}
在Startup#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
});
在Startup#Configure
中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"
}
]
}
}
此代码与我正在此处处理的相关问题非常相似。
,感谢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 $"v{specificVersion}" == version;
}
var versions = endpointMetadata
.Where(data => data is ApiVersionAttribute)
.SelectMany(data => (data as ApiVersionAttribute).Versions)
.Select(apiVersion => apiVersion.ToString());
return versions.Any(v => $"v{v}" == version);
});
并将端点分割为不同的文件。