【问题标题】:Is there a way change the Controller's name in the swagger-ui page?有没有办法在 swagger-ui 页面中更改控制器的名称?
【发布时间】:2016-05-06 15:29:14
【问题描述】:

我正在使用 Swashbuckle 在我的 WebApi 项目中启用 swagger 和 swagger-ui。

在下图中,您可以看到我在 swagger-ui 页面中显示的两个控制器。这些是在 C# 代码中命名的,但是我想知道是否有办法更改此处显示的内容?

这主要是因为您可以看到ManagementDashboardWidget 不是用户友好的名称,所以我想将其更改为用户友好的名称。

【问题讨论】:

  • 你试过用swagger的@Api作为你的restful服务类的注解吗?
  • @Sampada 我不确定如何访问它,请给我更多信息吗?
  • 很抱歉@API 可用于 Java 中的 swagger,而不是 swashbuckle swagger。
  • 您只需将 .cs 文件命名为符合您的意图即可实现您的目标。例如,将您的控制器代码文件命名为 GroupNameGoesHereController.cs,然后在 swagger 中您将看到名为 GroupNameGoesHere 的组。不幸的是,这不支持名称中的空格,因此如果您希望使用其他选项更好。
  • 重命名 .cs 不适用于我的情况。例如,由于 DI 实例化有很大不同,我对同一条路由有不同的控制器类。

标签: c# swagger swagger-ui swashbuckle


【解决方案1】:

您可以为此使用标签。默认情况下,Swashbuckle 会为每个操作添加一个带有控制器名称的标签。您可以使用SwaggerOperationAttribute 覆盖它。例如,下一行将默认标签 Values 替换为标签 Test:

public class ValuesController : ApiController
{
    [SwaggerOperation(Tags = new[] { "Test" })]
    public IHttpActionResult Get()
    {
        // ...
    }
}

Get 操作现在将放入组 Test

如果您希望操作出现在多个组中,您可以添加更多标签。例如:

[SwaggerOperation(Tags = new[] { "Test", "Release1" })]

会将Get 操作放在TestRelease1 组中。

【讨论】:

  • 这正是我想要的......我只是从来没有找到关于这部分的太多文档。非常感谢。
  • 这行得通,但它仍然将控制器名称作为标签留在 UI 中,但它下面没有任何操作。例如,假设我有ABCController,但我已将[SwaggerOperation(Tags = new[] { "DEF" })] 添加到所有路线,UI 显示“ABC”和“DEF”,但“ABC”下没有任何内容。我们如何完全摆脱“ABC”?
  • 看看下面我的回答。希望对你有帮助!
【解决方案2】:

我尝试使用 venerik 的答案,但它仍然在 UI 中保留了原始控制器名称以及您指定的新标签。我也不喜欢你必须为每个函数添加一个属性,所以我想出了一个解决方案,你只需向控制器添加一个属性。有两个步骤:

在控制器上添加DisplayNameAttribute

[DisplayName("Your New Tag")]
public class YourController : ApiController
{
    // ...
}

然后在 Swagger 配置中,您可以使用 GroupActionsBy 函数覆盖基本功能,以提取您在该属性中指定的名称:

GlobalConfiguration.Configuration
    .EnableSwagger(c => {
    
        c.GroupActionsBy(apiDesc => {
            var attr = apiDesc
                .GetControllerAndActionAttributes<DisplayNameAttribute>()
                .FirstOrDefault();
                
            // use controller name if the attribute isn't specified
            return attr?.DisplayName ?? apiDesc.ControllerName(); 
        });
        
    })
    .EnableSwaggerUi(c => {
        // your UI config here
    });

ControllerName()Swagger-Net 库中定义的扩展方法。如果您不使用它,您还可以从 apiDesc.ActionDescriptor.ControllerDescriptor.ControllerName 获取控制器名称

【讨论】:

  • 对我来说,apiDesc.ControllerName 不是一种方法。也许我正在使用不同版本的System.Web.Http...
  • @CodyStott ControllerName() 是在 Swagger-Net 库中定义的扩展方法,这是另一个与 Swashbuckle 非常相似的库(我假设您正在使用它)。话虽如此,您应该可以使用apiDesc.ActionDescriptor.ControllerDescriptor.ControllerName 来获取控制器名称。
【解决方案3】:

Swashbuckle 版本 5 支持以下选项(用于调用 AddSwaggerGen()):

options.TagActionsBy(api => new[] { api.GroupName });

这应该与您的控制器或操作上的以下属性结合使用:

[ApiExplorerSettings(GroupName = "...")]

但是,默认情况下,组名用于将操作包含在特定文档中。因此,这可能会导致意外结果(取决于您在调用 options.SwaggerDoc(name, ...) 时对文档的命名)。

要使其正常工作,您可能必须添加以下内容:

options.DocInclusionPredicate((name, api) => true);

这里,对于每个操作,name 是文档的名称,组名称在api.GroupName 中可用。要在文档中包含操作而不考虑其组名,只需返回 true。

【讨论】:

  • 应该指出,通过将DocInclusionPredicate 设置为true,那么您将来是否需要包含Multiple Documents,那么您需要找到另一种方式。
【解决方案4】:

默认情况下,如果我有一个名为 ShippingController 的控制器,那么 swagger 会生成名为“Shipping”的 UI

我希望将控制器的名称更改为更友好的名称或其他语言。我能找到的最好方法是使用 SwaggerOperation 属性来更改名称,但这有一个限制,它是一个方法级别的属性,我真的不想在每个方法上指定名称。

所以,我创建了一个约定类来与控制器 Route 属性一起使用,我们通常在控制器上使用它,然后让 swagger 使用它作为控制器的名称。好吧,您知道属性上有一个 name 属性,但生成的 swagger 似乎没有使用它。

第 1 步:创建此类:

当应用程序启动时,它将运行它,如果我的控制器具有指定的属性,我将能够在控制器上查找 Route 属性,然后使用 name 属性更改控制器的名称。

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApplicationModels;

namespace RestServices.Configuration.ConfigInstallers.Conventions
{
    public class ControllerDocumentationConvention : IControllerModelConvention
    {
        void IControllerModelConvention.Apply(ControllerModel controller)
        {
            if (controller == null)
                return;

            foreach (var attribute in controller.Attributes)
            {
                if (attribute.GetType() == typeof(RouteAttribute))
                {
                    var routeAttribute = (RouteAttribute)attribute;
                    if (!string.IsNullOrWhiteSpace(routeAttribute.Name))
                        controller.ControllerName = routeAttribute.Name;
                }
            }

        }
    }
}

第 2 步:Startup.cs:

修改 StartUp.cs 文件,在配置服务中我们需要在 Conventions 列表中注册我们的类。见下文:

services.AddControllers(o =>
{
   o.Conventions.Add(new ControllerDocumentationConvention());
});

第 3 步:在每个控制器中,在 Route Attribute 中添加 name 属性:

[ApiController]
[ApiVersion("1.0")]
[ApiExplorerSettings(IgnoreApi = false, GroupName = "v1")]
[Route("api/Envios/{version:apiVersion}", Name =  "Envios", Order = 1)]
[Produces("application/json")]
public class ShippingController

现在,当我运行应用程序并生成我的招摇时,您可以看到控制器名称已更改为与路由属性名称属性中的文本相同。

【讨论】:

  • 这很优雅。好建议!
  • 辛苦了!
  • 很好的解决方案,也可用于 NSwag,其中 options.TagActionsBy 不可用。对不滥用 Route-attribute 中的 name-property 的改进不大,这似乎不是我使用的最佳匹配属性:我使用 ApiExplorerSettingsAttribute 来设置组名,并在ControllerDocumentationConvention.
【解决方案5】:

如果想在控制器/类级别执行此操作,以下是来自here的非常有用的摘录

在您的控制器上使用 [ApiExplorerSettings(GroupName = "Group")]

然后在启动中

services.AddSwaggerGen(options =>
{
options.SwaggerDoc(version,
    new Info
    {
        Title = name,
        Version = version
    }
);

options.DocInclusionPredicate((_, api) => !string.IsNullOrWhiteSpace(api.GroupName));

options.TagActionsBy(api => api.GroupName);
});

还要注意

5.0.0-beta 的 swashbuckle 现在包含一个支持返回标签数组的 TagActionsBy 重载。这应该可以简化上述自定义

【讨论】:

    【解决方案6】:

    启动 .net 6 可以在控制器级别使用TagsAttribute(docs.microsoft):

    [Tags("entity")]
    [ApiController]
    public class DerivedEntitiesController : ControllerBase
    {
    

    或在行动层面:

    [Tags("entity")]
    [HttpPut("entity/{key}")]
    public IActionResult PutEntity(Guid key, [FromBody] Entity entity)
    {
    

    Swagger 将根据Tags 进行分组并尊重 API 版本控制。

    【讨论】:

      猜你喜欢
      • 2019-06-10
      • 1970-01-01
      • 2022-12-17
      • 1970-01-01
      • 1970-01-01
      • 2010-10-28
      • 1970-01-01
      • 2010-10-08
      • 1970-01-01
      相关资源
      最近更新 更多