在SwashBuckle中使用IOperationFilter删除路由 [英] Remove a route with IOperationFilter in SwashBuckle
问题描述
我正在寻找一种以可配置的方式使用SwashBuckle在Swagger文档中显示/隐藏WebAPI路由的方法。添加 [ApiExplorerSettings(IgnoreApi = true)]
确实可以隐藏路由,但是每次需要更改时,我都需要重新编译。
I am looking for a way to show/hide WebAPI routes in the Swagger documentation using SwashBuckle in a configurable way. Adding [ApiExplorerSettings(IgnoreApi = true)]
will indeed hide the routes but I'd need to recompile every time I want that to change.
我已经研究过创建一个 IOperationFilter
以使用我定义的自定义属性。这样,我可以用 [SwaggerTag( MobileOnly)]
装饰路由,并检查web.config或其他内容以查看是否应显示该路由。属性的定义如下:
I have looked into creating an IOperationFilter
to work with a custom Attribute that I defined. That way I can decorate the routes with a [SwaggerTag("MobileOnly")]
and check the web.config or something to see if the route should be shown. The Attribute is defined as such:
public class SwaggerTagAttribute : Attribute
{
public string[] Tags { get; private set; }
public SwaggerTagAttribute(params string[] tags)
{
this.Tags = tags;
}
}
IOperationFilter $定义了检测属性的c $ c>,并定义了删除路径的
IDocumentFilter
:
The IOperationFilter
that detects the attribute is defined and the IDocumentFilter
that removes the path is defined here:
public class RemoveTaggedOperationsFilter : IOperationFilter, IDocumentFilter
{
private List<string> TagsToHide;
public RemoveTaggedOperationsFilter()
{
TagsToHide = ConfigurationManager.AppSettings["TagsToHide"].Split(',').ToList();
}
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
var tags = apiDescription.ActionDescriptor
.GetCustomAttributes<SwaggerTagAttribute>()
.Select(t => t.Tags)
.FirstOrDefault();
if (tags != null && TagsToHide.Intersect(tags).Any())
{
operation.tags = new List<string> {"Remove Me "};
}
}
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
{
foreach (var value in swaggerDoc.paths.Values)
{
if (value.post != null && value.post.tags.Contains("Remove Me"))
value.post = null;
if (value.get != null && value.get.tags.Contains("Remove Me"))
value.get = null;
if (value.put != null && value.put.tags.Contains("Remove Me"))
value.put = null;
if (value.delete != null && value.delete.tags.Contains("Remove Me"))
value.delete = null;
}
}
}
并以此方式注册:
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.OperationFilter<RemoveTaggedOperationsFilter>();
c.DocumentFilter<RemoveTaggedOperationsFilter>();
});
我觉得这样效率低下,而且当我较早访问它时,很难标记某些内容以便稍后删除。有什么办法可以从 IOperationFilter.Apply
中删除路由,而不是等待 IDocumentFilter
并扫描
I feel that this is inefficient and hacky to tag something for removal later when I have access to it earlier. Is there any way that I just remove the route from the within IOperationFilter.Apply
rather than wait for the IDocumentFilter
and scan through it?
推荐答案
有人早些时候发布了一个答案,并说一旦有机会,他们就会发布代码。他们出于某种原因删除了答案,但这使我有了更好的解决方案。
Someone had posted an answer earlier and said they'd post code once they got a chance. They have deleted their answer for some reason but it got me to a better solution.
而不是使用 IOperationFilter
标记路由,然后使用 IDocumentFilter
稍后删除路由,只需使用 IDocumentFilter
查找自定义属性,然后一举删除即可。代码如下:
Rather than using IOperationFilter
to tag the route and then IDocumentFilter
to remove the route later you can just use IDocumentFilter
to find the custom attribute and remove it in one fell swoop. The code is below:
public class HideTaggedOperationsFilter : IDocumentFilter
{
private List<string> TagsToHide;
public HideTaggedOperationsFilter()
{
TagsToHide = ConfigurationManager.AppSettings["TagsToHide"].Split(',').ToList();
}
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
{
if (_tagsToHide == null) return;
foreach (var apiDescription in apiExplorer.ApiDescriptions)
{
var tags = apiDescription.ActionDescriptor
.GetCustomAttributes<SwaggerTagAttribute>()
.Select(t => t.Tags)
.FirstOrDefault();
if (tags == null || !_tagsToHide.Intersect(tags).Any())
continue;
var route = "/" + apiDescription.Route.RouteTemplate.TrimEnd('/');
swaggerDoc.paths.Remove(route);
}
}
}
public class SwaggerTagAttribute : Attribute
{
public string[] Tags { get; }
public SwaggerTagAttribute(params string[] tags)
{
this.Tags = tags;
}
}
注册 IDocumentFilter
:
GlobalConfiguration.Configuration.EnableSwagger(c =>
{
...
c.DocumentFilter<HideTaggedOperationsFilter>();
});
然后只需装饰一条这样的路线:
Then just decorate a route like so:
[SwaggerTag("MobileOnly")]
public IHttpActionResult SendTest(Guid userId)
{
return OK();
}
编辑:
GitHub页面上有一些SwashBuckle的问题帖子,建议在 Apply $ c中的
swaggerDoc.path
上将每个HTTP动词设置为null。 $ c>。我发现这破坏了许多诸如AutoRest之类的自动代码生成器,因此我只是删除了整个路径。 (看起来也更简洁)
There are some issue posts on the GitHub page for SwashBuckle that recommend setting each of the HTTP verbs to null on the
swaggerDoc.path
in Apply
. I found this to break a lot of auto code generators like AutoRest so I am simply removing the path as a whole. (It looks more succinct too)
这篇关于在SwashBuckle中使用IOperationFilter删除路由的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!