在 .net core 中通过以下方式修复 Api 版本控制后
services.AddApiVersioning(options =>
{
options.AssumeDefaultVersionWhenUnspecified = true;
options.DefaultApiVersion = new ApiVersion(1, 0);
options.UseApiBehavior = false; //If true [ApiController] attribute required for versioning
})
.AddVersionedApiExplorer(options =>
{
options.GroupNameFormat = "'v'VVV";
options.SubstituteApiVersionInUrl = true;
});
我面临的下一个问题是默认 api 版本显示在 swagger 文档中。如下图所示。
有很多文章可以使用 swashbuckle 修复它,但是如何使用 NSwag 修复它?
通过 NSwug,我们可以使用 DocumentProcessors,它可用于过滤掉不需要的 swagger 路径。
我使用了下面的nuget包
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="5.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer" Version="5.0.0" />
<PackageReference Include="NSwag.AspNetCore" Version="13.9.4" />
下面显示了我如何注册它们并解决问题
public void ConfigureServices(IServiceCollection services)
{
....
services.AddApiVersioning(options =>
{
options.AssumeDefaultVersionWhenUnspecified = true;
options.DefaultApiVersion = new ApiVersion(1, 0);
})
.AddVersionedApiExplorer(options =>
{
options.GroupNameFormat = "'v'VVV";
options.SubstituteApiVersionInUrl = true;
});
services.AddSwaggerDocument(config =>
{
SwaggerConfigure(config, "v1", true);
});
services.AddSwaggerDocument(config =>
{
SwaggerConfigure(config, "v2", false);
});
}
SwaggerConfigure 实现
private void SwaggerConfigure(AspNetCoreOpenApiDocumentGeneratorSettings configure, string version, bool isDefaultVersion)
{
configure.DocumentName = version;
configure.ApiGroupNames = new[] { version };
if (isDefaultVersion)
{
configure.DocumentProcessors.Add(new RemoveVersionFromDefault(version));
}
configure.PostProcess = document =>
{
document.Info.Version = version;
document.Info.Title = $"{GetApiTitle()} API";
};
configure.AllowNullableBodyParameters = false;
configure.SerializerSettings = new JsonSerializerSettings();
}
文档处理器实现
public class RemoveVersionFromDefault : IDocumentProcessor
{
private readonly string _defaultVersion;
public RemoveVersionFromDefault(string defaultVersion)
{
_defaultVersion = defaultVersion;
}
public void Process(DocumentProcessorContext context)
{
var keys = new List<string>();
foreach (var (key, value) in context.Document.Paths)
{
if (key.Contains($"/{_defaultVersion}/"))
{
keys.Add(key);
}
}
foreach (var key in keys)
{
context.Document.Paths.Remove(key);
}
}
}
就是这样。希望这能帮助正在寻找 NSwug 类似解决方案的人
有多种方法可以解决这种情况。另一种方法是创建并注册最后执行的自定义 IApiDescriptionProvider。从提供给 IApiDescriptionProvider.OnProvidersExecuted
上下文的结果
ApiDescription实例中,您可以找到您要查找的内容并从结果中删除描述符。在这种情况下,您希望删除与 API 版本参数匹配的默认 API 版本的描述符。
这种方法有几个好处:
IOptions<ApiVersioningOptions>
ApiDescriptor.GetApiVersion
扩展方法来匹配 API 版本,并过滤仍具有 API 版本参数的描述符。您可以对名称进行硬编码,或者从步骤 1 中注入的 ApiVersioningOptions.RouteConstraintName
中获取它。无需 magic string 解析或匹配。旁白:有关以下的评论:
options.UseApiBehavior = false; //If true [ApiController] attribute required for versioning
不太准确。您可能会得到您想要的结果,但故事还不止于此。这种行为和定制没有很好的记录,几乎没有人改变它。该行为实际上由 IApiControllerSpecification 和 IApiControllerFilter 控制。默认过滤器实现只运行所有注册的规范,因此没有理由更改它。每个规范定义了控制器是否匹配。有一个与
匹配的开箱即用规范,但这并不是唯一存在的规范(例如:OData 控制器)。[ApiController]
选项存在的原因是因为在UseApiBehavior
之前(在2.1中我认为),没有明确的方法来消除仅UI控制器和仅API控制器之间的歧义。这确实让一些混合使用两种类型控制器的开发人员感到恼火。相反,按下硬开关来禁用该功能可能会破坏想要该行为的开发人员。将值设置为[ApiController]
只会忽略所有过滤并恢复到false
之前的日子,这是在名为 API Behaviours 的功能增强中引入的。如果您决定这样做,新设计允许您更换或创建新规格。它可能不适用于您,但应该知道配置选项不是用于匹配[ApiController]
的硬on
或off
,并且其他更复杂的控制器过滤也是可能的。[ApiController]
这是一个使用 Nswag 的解决方案,我陷入了这个问题,然后通过一些搜索来调查 AddOperationFilter 并解决了问题。希望它对某人有帮助!:)
settings.GeneratorSettings.AddOperationFilter(x =>
{
if (x.Document.Paths == null) return true;
var keysToRemove = x.Document.Paths
.Where(kv => kv.Key.StartsWith("/api/"))
.Select(kv => kv.Key)
.ToList();
foreach (var key in keysToRemove)
{
x.Document.Paths.Remove(key);
}
return true;
});