【问题标题】:How to omit methods from Swagger documentation on WebAPI using Swashbuckle如何使用 Swashbuckle 从关于 WebAPI 的 Swagger 文档中省略方法
【发布时间】:2015-06-24 10:40:30
【问题描述】:

我有一个 C# ASP.NET WebAPI 应用程序,其中 API 文档是使用 Swashbuckle 自动生成的。我希望能够从文档中省略某些方法,但我似乎无法弄清楚如何告诉 Swagger 不要将它们包含在 Swagger UI 输出中。

我觉得这与添加模型或模式过滤器有关,但不清楚该怎么做,文档似乎只提供了如何修改方法输出的示例,而不是将其从输出中完全删除。

【问题讨论】:

    标签: c# asp.net .net swagger


    【解决方案1】:

    您可以在使用文档过滤器生成 swagger 文档后从它中删除“操作” - 只需将动词设置为 null(不过,也可能有其他方法)

    以下示例仅允许使用 GET 动词 - 并取自 this issue

    class RemoveVerbsFilter : IDocumentFilter
    {
        public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
        {
            foreach (PathItem path in swaggerDoc.paths.Values)
            {
                path.delete = null;
                //path.get = null; // leaving GET in
                path.head = null;
                path.options = null;
                path.patch = null;
                path.post = null;
                path.put = null;
            }
        }
    }
    

    在你的招摇配置中:

    ...EnableSwagger(conf => 
    {
        // ...
    
        conf.DocumentFilter<RemoveVerbsFilter>();
    });
    

    【讨论】:

    • 请注意:即使您取消注释 path.get = null;,这也不会删除路径——因此这些路径仍将包含在 Swagger 文件中,但只是没有详细信息。正如您在 GitHub 上的原始回复中提到的那样,在您的答案中包含 ApiExplorerSettingsAttribute 可能会更好。使用 ApiExplorerSettings 还可以避免将类型信息添加到 Swagger 文件的 schemes 列表中。
    【解决方案2】:

    我希望完全删除路径项的字典条目:

    var pathsToRemove = swaggerDoc.Paths
                    .Where(pathItem => !pathItem.Key.Contains("api/"))
                    .ToList();
    
    foreach (var item in pathsToRemove)
    {
        swaggerDoc.Paths.Remove(item.Key);
    }
    

    使用这种方法,您不会在生成的 swagger.json 定义中获得“空”项目。

    【讨论】:

      【解决方案3】:

      您可以将以下属性添加到 Controllers 和 Actions 以将它们从生成的文档中排除:[ApiExplorerSettings(IgnoreApi = true)]

      【讨论】:

      • 工作得很好,这应该是答案
      • 有没有办法以编程方式做到这一点?根据配置设置,我想在某些环境中公开 API,但在其他环境中不公开。
      • Swashbuckle 文档:Omit Arbitrary Operations
      • System.Web.Http.Description.ApiExplorerSettings, System.Web.Http
      • 它仍然可以工作 asp.net mvc int dot net-framework :)
      【解决方案4】:

      有人在 github 上发布了解决方案,所以我将其粘贴在这里。所有的功劳都归他所有。 https://github.com/domaindrivendev/Swashbuckle/issues/153#issuecomment-213342771

      首先创建一个属性类

      [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
      public class HideInDocsAttribute : Attribute
      {
      }
      

      然后创建一个文档过滤器类

      public class HideInDocsFilter : IDocumentFilter
      {
          public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
          {
              foreach (var apiDescription in apiExplorer.ApiDescriptions)
              {
                  if (!apiDescription.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<HideInDocsAttribute>().Any() && !apiDescription.ActionDescriptor.GetCustomAttributes<HideInDocsAttribute>().Any()) continue;
                  var route = "/" + apiDescription.Route.RouteTemplate.TrimEnd('/');
                  swaggerDoc.paths.Remove(route);
              }
          }
      }
      

      然后在 Swagger Config 类中,添加那个文档过滤器

      public class SwaggerConfig
      {
          public static void Register(HttpConfiguration config)
          {
              var thisAssembly = typeof(SwaggerConfig).Assembly;
      
              config
                   .EnableSwagger(c =>
                      {
                          ...                       
                          c.DocumentFilter<HideInDocsFilter>();
                          ...
                      })
                  .EnableSwaggerUi(c =>
                      {
                          ...
                      });
          }
      }
      

      最后一步是在你不希望 Swashbuckle 生成文档的 Controller 或 Method 上添加 [HideInDocsAttribute] 属性。

      【讨论】:

      • 我认为 RemoveRoute 可能是我正在寻找的机器人。
      【解决方案5】:

      基于@spottedmahns answer。 我的任务是相反的。只显示那些被允许的。

      框架:.NetCore 2.1;招摇:3.0.0

      添加属性

      [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
      public class ShowInSwaggerAttribute : Attribute
      {
      }
      

      并实现自定义IDocumentFilter

      public class ShowInSwaggerFilter : IDocumentFilter
      {
          public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
          {
      
              foreach (var contextApiDescription in context.ApiDescriptions)
              {
                  var actionDescriptor = (ControllerActionDescriptor) contextApiDescription.ActionDescriptor;
      
                  if (actionDescriptor.ControllerTypeInfo.GetCustomAttributes<ShowInSwaggerAttribute>().Any() ||
                      actionDescriptor.MethodInfo.GetCustomAttributes<ShowInSwaggerAttribute>().Any())
                  {
                      continue;
                  }
                  else
                  {
                      var key = "/" + contextApiDescription.RelativePath.TrimEnd('/');
                      var pathItem = swaggerDoc.Paths[key];
                      if(pathItem == null)
                          continue;
      
                      switch (contextApiDescription.HttpMethod.ToUpper())
                      {
                          case "GET":
                              pathItem.Get = null;
                              break;
                          case "POST":
                              pathItem.Post = null;
                              break;
                          case "PUT":
                              pathItem.Put = null;
                              break;
                          case "DELETE":
                              pathItem.Delete = null;
                              break;
                      }
      
                      if (pathItem.Get == null  // ignore other methods
                          && pathItem.Post == null 
                          && pathItem.Put == null 
                          && pathItem.Delete == null)
                          swaggerDoc.Paths.Remove(key);
                  }
              }
          }
      }
      

      配置服务代码:

      public void ConfigureServices(IServiceCollection services)
      {
           // other code
      
          services.AddSwaggerGen(c =>
          {
              // other configurations
              c.DocumentFilter<ShowInSwaggerFilter>();
          });
      }
      

      【讨论】:

      • 谢谢阿莱哈。这种方法实际上适用于 ApiExplorerSettingsAttribute 不起作用的 SwashBuckle.OData。
      【解决方案6】:

      制作过滤器

      public class SwaggerTagFilter : IDocumentFilter
      {
          public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
          {
              foreach(var contextApiDescription in context.ApiDescriptions)
              {
                  var actionDescriptor = (ControllerActionDescriptor)contextApiDescription.ActionDescriptor;
                  
                  if(!actionDescriptor.ControllerTypeInfo.GetCustomAttributes<SwaggerTagAttribute>().Any() && 
                     !actionDescriptor.MethodInfo.GetCustomAttributes<SwaggerTagAttribute>().Any())
                  {
                      var key = "/" + contextApiDescription.RelativePath.TrimEnd('/');
                      swaggerDoc.Paths.Remove(key);
                  }
              }
          }
      }
      

      创建一个属性

      [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
      public class SwaggerTagAttribute : Attribute
      {
      }
      

      在startup.cs中应用

      services.AddSwaggerGen(c => {
          c.SwaggerDoc(1, new Info { Title = "API_NAME", Version = "API_VERSION" });
          c.DocumentFilter<SwaggerTagFilter>(); // [SwaggerTag]
      });
      

      将 [SwaggerTag] 属性添加到要包含在 Swagger JSON 中的方法和控制器

      【讨论】:

      • 甜蜜。适当的方法,感谢您分享 sln。
      【解决方案7】:

      在 SwaggerConfig 中添加一行

      c.DocumentFilter<HideInDocsFilter>();
      
      ...
      
      public class HideInDocsFilter : IDocumentFilter
      {
          public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
          { 
              var pathsToRemove = swaggerDoc.Paths
                  .Where(pathItem => !pathItem.Key.Contains("api/"))
                  .ToList();
          
              foreach (var item in pathsToRemove)
              {
                  swaggerDoc.Paths.Remove(item.Key);
              }
          }
      }
      

      【讨论】:

        【解决方案8】:

        可能对某人有所帮助,但在开发(调试)期间,我们喜欢公开整个控制器和/或操作,然后在生产期间隐藏它们(发布构建)

        #if DEBUG
            [ApiExplorerSettings(IgnoreApi = false)]
        #else
            [ApiExplorerSettings(IgnoreApi = true)]
        #endif  
        

        【讨论】:

          【解决方案9】:

          与@aleha 一样,我想在默认情况下排除,这样我就不会意外暴露端点(默认情况下是安全的),但我使用的是使用 OpenApiDocument 的更新版本的 Swagger。

          创建 ShowInSwagger 属性

          [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
          public class ShowInSwaggerAttribute : Attribute
          {}
          

          然后创建一个文档过滤器

          using Microsoft.AspNetCore.Mvc.Controllers;
          using Microsoft.OpenApi.Models;
          using Swashbuckle.AspNetCore.SwaggerGen;
          using System.Reflection;
          using System;
          using System.Linq;
          using TLS.Common.Attributes;
          
          namespace TLS.Common.Filters
          {
              public class ShowInSwaggerFilter : IDocumentFilter
              {
                  public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
                  {
                      foreach (var contextApiDescription in context.ApiDescriptions)
                      {
                          var actionDescriptor = (ControllerActionDescriptor)contextApiDescription.ActionDescriptor;
          
                          if (actionDescriptor.ControllerTypeInfo.GetCustomAttributes<ShowInSwaggerAttribute>().Any() ||
                              actionDescriptor.MethodInfo.GetCustomAttributes<ShowInSwaggerAttribute>().Any())
                          {
                              continue;
                          }
                          else
                          {
                              var key = "/" + contextApiDescription.RelativePath.TrimEnd('/');
                              var operation = (OperationType)Enum.Parse(typeof(OperationType), contextApiDescription.HttpMethod, true);
          
                              swaggerDoc.Paths[key].Operations.Remove(operation);
          
                              // drop the entire route of there are no operations left
                              if (!swaggerDoc.Paths[key].Operations.Any())
                              {
                                  swaggerDoc.Paths.Remove(key);
                              }
                          }
                      }
                  }
              }
          }
          

          然后在您的 startup.cs 或 ConfigureServices 中:

          public void ConfigureServices(IServiceCollection services)
          {
               // other code
          
              services.AddSwaggerGen(c =>
              {
                  c.DocumentFilter<ShowInSwaggerFilter>();
                  // other config
              });
          }
          

          【讨论】:

            【解决方案10】:

            您可以在控制器和方法级别创建自定义过滤器。因此,任何具有您的属性的控制器/方法都将在 Swagger 文档中可用。此过滤器还从您的文档中删除了重复的 HTTP 动词(在此示例中,我仅将其用于 GET/PUT/POST/PATCH),但是,您始终可以根据您的要求进行自定义

            属性

            [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
            public class PublicApi:Attribute
            {
            
            }
            

            文档过滤器

            public class PublicApiFilter : IDocumentFilter
            {
                public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
                {
            
                    var publicPaths = new List<string> {"/api"};
            
                    var publicApiDescriptions = new List<ApiDescription>();
            
                    var publicMethods = FilterByPublicControllers(swaggerDoc, apiExplorer, publicPaths, publicApiDescriptions);
            
                    FilterByPublicActions(swaggerDoc, publicApiDescriptions, publicMethods);
                }
            
                private static Dictionary<string, List<string>> FilterByPublicControllers(SwaggerDocument swaggerDoc, IApiExplorer apiExplorer, List<string> publicPaths, List<ApiDescription> publicApiDescriptions)
                {
                    var publicMethods = new Dictionary<string, List<string>>();
                    foreach (var apiDescription in apiExplorer.ApiDescriptions)
                    {
                        var isPublicApiController = apiDescription.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<PublicApi>().Any();
                        var isPublicApiMethod = apiDescription.ActionDescriptor.GetCustomAttributes<PublicApi>().Any();
            
            
                        if (!isPublicApiController && !isPublicApiMethod)
                        {
                            continue;
                        }
            
                        var relativePath = ToRelativePath(apiDescription);
            
                        publicPaths.Add(relativePath);
                        publicApiDescriptions.Add(apiDescription);
            
                        var action = apiDescription.ActionDescriptor.ActionName;
                        List<string> available = null;
                        if (!publicMethods.TryGetValue(relativePath, out available))
                            publicMethods[relativePath] = new List<string>();
                        publicMethods[relativePath].Add(action);
                    }
            
                    swaggerDoc.paths = swaggerDoc.paths.Where(pair => publicPaths.Contains(pair.Key))
                        .ToDictionary(pair => pair.Key,
                            pair => pair.Value);
                    return publicMethods;
                }
            
                private static void FilterByPublicActions(SwaggerDocument swaggerDoc, List<ApiDescription> publicApis, Dictionary<string, List<string>> publicMethods)
                {
                    foreach (var api in publicApis)
                    {
                        var relativePath = ToRelativePath(api);
                        var availableActions = publicMethods[relativePath];
                        if (availableActions == null)
                        {
                            continue;
                        }
            
                        foreach (var path in swaggerDoc.paths.Where(pair => pair.Key.IndexOf(relativePath) > -1).ToList())
                        {
                            if (!availableActions.Contains("Get"))
                                path.Value.get = null;
                            if (!availableActions.Contains("Post"))
                                path.Value.post = null;
                            if (!availableActions.Contains("Put"))
                                path.Value.put = null;
                            if (!availableActions.Contains("Patch"))
                                path.Value.patch = null;
                        }
                    }
                }
            
                private static string ToRelativePath(ApiDescription apiDescription)
                {
                    return "/" + apiDescription.RelativePath.Substring(0,apiDescription.RelativePath.LastIndexOf('/'));
                }
            }
            

            最后,注册你的 SwaggerConfig

            public class SwaggerConfig
            {
                public static void Register()
                {
            
                    var thisAssembly = typeof(SwaggerConfig).Assembly;
                    GlobalConfiguration.Configuration
                        .EnableSwagger(c =>
                            {
                                c.SingleApiVersion("v1", "Reports");
                                c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
                                c.DocumentFilter<PublicApiFilter>();
                            })
                        .EnableSwaggerUi(c =>
                            {
            
                            });
            
                }
            }
            

            示例

            控制器

            [PublicApi]
            public class ProfileController : ApiController
            

            方法

             public class UserController : ApiController
             {
                [PublicApi]
                public ResUsers Get(string sessionKey, int userId, int groupId) {
                    return Get(sessionKey, userId, groupId, 0);
                }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-04-13
              • 2020-05-26
              • 2017-01-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多