我正在使用Asp.Net Core 3.1构建我的API。我正在使用swagger为我的API生成文档。我决定根据控制器对我的招摇文件进行分组。所以我最终做了这样的事,
启动-配置服务:
options.SwaggerDoc(
"LibraryOpenAPISpecificationCategories",
...
启动-配置:
options.SwaggerEndpoint(
"/swagger/LibraryOpenAPISpecificationCategories/swagger.json",
"Library API (Categories)");
控制器:
[Route("api/categories")]
[ApiController]
[ApiExplorerSettings(GroupName = "LibraryOpenAPISpecificationCategories")]
public class CategoriesController : ControllerBase
在此之前,一切都很顺利。当我添加版本控制时,Swagger文档停止在控制器中显示方法。我试图在版本内部进行分组,这样每个版本都会有像这样的组
V1->LibraryOpenAPI规范类别
V1->LibraryOpenAPI规范项目
V2->库OpenAPI规范类别
V2->库OpenAPI规范项
以下是我所做的,
启动-配置服务:
services.AddVersionedApiExplorer(options =>
{
options.GroupNameFormat = "'v'VV";
});
services.AddApiVersioning(options =>
{
options.AssumeDefaultVersionWhenUnspecified = true;
options.DefaultApiVersion = new ApiVersion(1, 0);
options.ReportApiVersions = true;
});
var apiVersionDescriptionProvider =
services.BuildServiceProvider().GetService<IApiVersionDescriptionProvider>();
services.AddSwaggerGen(options =>
{
foreach (var description in apiVersionDescriptionProvider.ApiVersionDescriptions)
{
options.SwaggerDoc(
$"LibraryOpenAPISpecificationCategories{description.GroupName}",
...
启动-配置:
app.UseSwaggerUI(options =>
{
foreach (var description in apiVersionDescriptionProvider.ApiVersionDescriptions)
{
options.SwaggerEndpoint(
$"/swagger/LibraryOpenAPISpecificationCategories{description.GroupName}/swagger.json",
$"Library API (Categories) {description.GroupName.ToUpperInvariant()}");
控制器:
[Route("api/categories")]
[ApiController]
[ApiExplorerSettings(GroupName = "LibraryOpenAPISpecificationCategories")]
public class CategoriesController : ControllerBase
型锻文档中未显示错误。请帮我解决哪里出了问题。我遗漏了什么吗?
经过一些分析,我发现我的ConfigureServices
中的AddSwaggerGen
中遗漏了DocInclusionPredicate
。
以下是我的解决方法,
options.DocInclusionPredicate((documentName, apiDescription) =>
{
var actionApiVersionModel = apiDescription.ActionDescriptor
.GetApiVersionModel(ApiVersionMapping.Explicit | ApiVersionMapping.Implicit);
var apiExplorerSettingsAttribute = (ApiExplorerSettingsAttribute)apiDescription.ActionDescriptor.EndpointMetadata.First(x => x.GetType().Equals(typeof(ApiExplorerSettingsAttribute)));
if (actionApiVersionModel == null)
{
return true;
}
if (actionApiVersionModel.DeclaredApiVersions.Any())
{
return actionApiVersionModel.DeclaredApiVersions.Any(v =>
$"{apiExplorerSettingsAttribute.GroupName}v{v.ToString()}" == documentName);
}
return actionApiVersionModel.ImplementedApiVersions.Any(v =>
$"{apiExplorerSettingsAttribute.GroupName}v{v.ToString()}" == documentName);
});
希望这能帮助到其他人。
由于一些人在不同的地方要求这样做,下面是如何实现自定义的IApiDescriptionProvider。它只是在处理结束时更新ApiDescription.GroupName
。这将完全独立于Swashbuckle或任何其他OpenAPI/Swagger文档生成器:
public class CollateApiDescriptionProvider : IApiDescriptionProvider
{
readonly IOptions<ApiExplorerOptions> options;
public CollateApiDescriptionProvider( IOptions<ApiExplorerOptions> options ) =>
this.options = options;
public int Order => 0;
public void OnProvidersExecuting( ApiDescriptionProviderContext context ) { }
public void OnProvidersExecuted( ApiDescriptionProviderContext context )
{
var results = context.Results;
var format = options.Value.GroupNameFormat;
var text = new StringBuilder();
for ( var i = 0; i < results.Count; i++ )
{
var result = results[i];
var action = result.ActionDescriptor;
var version = result.GetApiVersion();
var groupName = action.GetProperty<ApiDescriptionActionData>()?.GroupName;
text.Clear();
// add the formatted API version according to the configuration
text.Append( version.ToString( format, null ) )
// if there's a group name, prepend it
if ( !string.IsNullOrEmpty( groupName ) )
{
text.Insert( 0, ' ' );
text.Insert( 0, groupName );
}
result.GroupName = text.ToString();
}
}
}
要注册您的新提供商,请将其添加到服务集合:
services.TryAddEnumerable(
ServiceDescriptor.Transient<IApiDescriptionProvider, CollateApiDescriptionProvider>() );
注意:这应该发生在
services.AddApiVersioning()
之后
您可以随心所欲地使用组名称,但要注意,您不能创建多级分组。它根本没有开箱即用的支持。在大多数情况下,每个API版本只能有一个OpenAPI/Swagger文档。这是因为URL在文档中必须是唯一的。
从技术上讲,可以在多个级别上进行分组,但这需要对UI和文档生成过程进行一些更改。我只见过少数人愿意投入这么多精力。他们有效地创建了自己的UI和文档生成后端。