【问题标题】:.NET Core 2.1 Swashbuckle - group controllers by area.NET Core 2.1 Swashbuckle - 按区域分组控制器
【发布时间】:2019-04-29 12:28:33
【问题描述】:

我的情况比较简单。我有一个非常大的 .NET Core 2.1 MVC/WebApi,分为几个区域,代表我系统的不同模块。我使用 Swagger (SwashBuckle),效果很好。我的路由类似于{area}/{controller}/{action}

在 Swagger UI 中,每个操作都被分组到控制器中(标准行为)。我的控制器和操作列表变得非常庞大且难以掌握。正因为如此,如果 Swagger 可以将我的控制器分成不同的区域,我会很高兴!可以折叠area xarea x 中的每个控制器。

我真的很想念这个功能或自己实现它的方法!任何想法表示赞赏!

更新

我试过用标签来注释动作。

这给了我:

- Area 1
    - MethodFromControllerA()
    - MethodFromControllerB()
- Area 2
    - MethodFromControllerC()
    - MethodFromControllerD()

我想要什么:

- Area 1
    - ControllerA
        - MethodFromControllerA()
    - ControllerB
        - MethodFromControllerB()
- Area 2
    - ControllerC
        - MethodFromControllerC()
    - ControllerD
        - MethodFromControllerD()

更新 2

另一种选择是为我的每个区域设置多个规格。就像每个区域的不同 Swagger UI。可能吗?

【问题讨论】:

  • 也许也可以看看这个:stackoverflow.com/questions/37703251/…(虽然没有 asp.net 核心)
  • @B12Toaster 这些很接近 - 但没有具体的解决方案!另一种选择是为我的每个领域制定多个规范。就像每个区域的不同 Swagger UI。可能吗?
  • 取决于您的 api 以及您希望如何使其可访问 :) 我会避免这样做,因为它很难搜索您的 api。您可以做的另一件事(hacky)是将 js 代码注入到您的 swagger ui 中,然后通过 javascript dom 操作以某种方式重新排列和缩进生成的 html/css div:D
  • 如果您在同一区域的控制器共享相同的路径前缀,那么您可以在“/”上拆分,并根据此前缀重新排序。否则,尝试通过注释以某种方式将元信息添加到您的控制器或操作中。 ...或者可能为您的控制器添加一个前缀,例如 AreaxFooController。然后在您的 js 中对控制器名称执行拆分...有创意:D

标签: asp.net-core swagger asp.net-core-2.1 swashbuckle


【解决方案1】:

您首先需要安装annotations 并在您的启动中启用它们:

services.AddSwaggerGen(c =>
{
   c.EnableAnnotations();
});

然后你需要将你的“区域”作为标签添加到每个动作中。

[SwaggerOperation(
    Tags = new[] { "Area51" }
)]

当你打开你的 swagger ui 时,它现在应该自动按标签分组(默认情况下,控制器名称是所选标签)。

目前无法使用现有的 swagger ui 生成器进行开箱即用的端点嵌套分组。

【讨论】:

  • 这确实将我的操作分组在指定的标签中。但是,我在每个区域都有几个控制器,我仍然不想在控制器中对操作进行分组。
  • 我认为两级嵌套是不可能的。
  • 我担心它不是...... :-( 但我真的可以用它来为我的前端开发同事记录我们的大型系统
  • 嗯,也许this 技术适合您的需要(或同一线程中提到的this one)? ...仔细观察,它看起来仍然只是一个层次结构。
【解决方案2】:

如果您仍然希望按区域名称执行此操作,这是在 Swashbuckle.AspNetCore 中执行此操作的完整代码:

c.OperationFilter<TagByAreaNameOperationFilter>();
public class TagByAreaNameOperationFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        if (context.ApiDescription.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor)
        {
            var areaName = controllerActionDescriptor.ControllerTypeInfo.GetCustomAttributes(typeof(AreaAttribute), true)
                .Cast<AreaAttribute>().FirstOrDefault();
            if (areaName != null)
            {
                operation.Tags = new List<OpenApiTag> { new OpenApiTag { Name = areaName.RouteValue } };
            }
            else
            {
                operation.Tags = new List<OpenApiTag> { new OpenApiTag { Name = controllerActionDescriptor.ControllerName } };
            }
        }
    }
}

【讨论】:

    【解决方案3】:

    我创建了一个简单的自定义属性来注释我想要分组的控制器,并在注册 Swashbuckle 时使用了TagActionsBy 方法。

    builder.Services
        .AddSwaggerGen(c =>
        {
            c.TagActionsBy(api =>
            {
                if (api.ActionDescriptor is ControllerActionDescriptor actionDescriptor)
                {
                    var group = actionDescriptor.ControllerTypeInfo.GetCustomAttributes(typeof(GroupTagAttribute), true)
                        .Cast<GroupTagAttribute>().FirstOrDefault();
    
                    return group != null
                        ? new List<string> {group.Name}
                        : new List<string> {actionDescriptor.ControllerName};
                }
    
                throw new NullReferenceException("Couldn't find the group name");
            });
            // the rest of the configuration
        });
    

    GroupTagAttribute

    public class GroupTagAttribute : Attribute
    {
        public string Name { get; }
    
        public ApiGroupAttribute(string name)
        {
            Name = name;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-04-07
      • 2018-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多