在SwashBuckle中使用IOperationFilter删除路由 [英] Remove a route with IOperationFilter in SwashBuckle

查看:186
本文介绍了在SwashBuckle中使用IOperationFilter删除路由的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种以可配置的方式使用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 ,并定义了删除路径的 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 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆