SwaggerUI 不显示枚举摘要描述,C# .net 核心?

Posted

技术标签:

【中文标题】SwaggerUI 不显示枚举摘要描述,C# .net 核心?【英文标题】:SwaggerUI not display enum summary description, C# .net core? 【发布时间】:2019-04-16 08:31:15 【问题描述】:

我使用https://docs.microsoft.com/en-us/aspnet/core/tutorials/getting-started-with-swashbuckle?view=aspnetcore-2.1&tabs=visual-studio#xml-comments 在 SwaggerUI 中显示我的课程摘要描述,可以但不显示 enum 摘要描述! 我的startup.cs

services.AddSwaggerGen(c =>
   
    c.SwaggerDoc("v1", new Info
    
        Version = "v1",
        Title = "My App-Service",
        Description = "My Description",
    );
    c.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, $"Assembly.GetExecutingAssembly().GetName().Name.xml"));  
    c.DescribeAllEnumsAsStrings();
);

我的enum

public enum GenderEnum

    /// <summary>
    /// Man Description
    /// </summary>
    Man = 1,

    /// <summary>
    /// Woman Description
    /// </summary>
    Woman = 2

它显示如下内容:

我想在 SwaggerUI 中显示 Man DescriptionWoman Description 像这样:

Man = 1, Man Description
Woman = 2,  Woman Description

我正在使用Swashbuckle.AspNetCore v4.0.1

【问题讨论】:

这是 swagger github.com/swagger-api/swagger-ui/issues/3873 或 github.com/swagger-api/swagger-ui/issues/685 中的一个未解决问题 @Mohammad 只是为了澄清一下-您的意思是您想同时查看枚举值和每个值的描述吗?例如。类似:“Man - 男人描述,Woman - 女人描述”。 @Helen,没错 Swagger UI Web Api documentation Present enums as strings? 的可能重复项,特别是 this answer。 回顾 ^^ 链接的答案 - OpenAPI Specification current does not support enum value descriptions;解决方法是将这些描述包含在枚举或参数本身的描述中。 【参考方案1】:

截至 2021 年 6 月,OpenApi 现在支持此功能,您可以扩展 Swagger 以显示详细信息。这是我在 .NET 5.0 上的 C# 代码。

首先在一个文件中定义模式过滤器(将其命名为DescribeEnumMembers.cs 并确保将YourNamespace 更改为您的命名空间的名称):

using System;
using System.Text;
using System.Xml.Linq;
using System.Xml.XPath;

using Microsoft.OpenApi.Models;

using Swashbuckle.AspNetCore.SwaggerGen;

namespace YourNamespace

  /// <summary>
  /// Swagger schema filter to modify description of enum types so they
  /// show the XML docs attached to each member of the enum.
  /// </summary>
  public class DescribeEnumMembers: ISchemaFilter
  
    private readonly XDocument mXmlComments;

    /// <summary>
    /// Initialize schema filter.
    /// </summary>
    /// <param name="argXmlComments">Document containing XML docs for enum members.</param>
    public DescribeEnumMembers(XDocument argXmlComments)
      => mXmlComments = argXmlComments;

    /// <summary>
    /// Apply this schema filter.
    /// </summary>
    /// <param name="argSchema">Target schema object.</param>
    /// <param name="argContext">Schema filter context.</param>
    public void Apply(OpenApiSchema argSchema, SchemaFilterContext argContext) 
      var EnumType = argContext.Type;

      if(!EnumType.IsEnum) return;

      var sb = new StringBuilder(argSchema.Description);

      sb.AppendLine("<p>Possible values:</p>");
      sb.AppendLine("<ul>");

      foreach(var EnumMemberName in Enum.GetNames(EnumType)) 
        var FullEnumMemberName = $"F:EnumType.FullName.EnumMemberName";

        var EnumMemberDescription = mXmlComments.XPathEvaluate(
          $"normalize-space(//member[@name = 'FullEnumMemberName']/summary/text())"
        ) as string;

        if(string.IsNullOrEmpty(EnumMemberDescription)) continue;

        sb.AppendLine($"<li><b>EnumMemberName</b>: EnumMemberDescription</li>");
      

      sb.AppendLine("</ul>");

      argSchema.Description = sb.ToString();
    
  


然后在您的 ASP.NET ConfigureServices() 方法中启用它。这是我剪掉与本练习无关的部分后的代码:

public void ConfigureServices(IServiceCollection argServices) 
  // ...<snip other code>

  argServices.AddSwaggerGen(SetSwaggerGenOptions);

  // ...<snip other code>

  return;

  // ...<snip other code>

  void SetSwaggerGenOptions(SwaggerGenOptions argOptions) 
    // ...<snip other code>

    AddXmlDocs();
    return;

    void AddXmlDocs() 
      // generate paths for the XML doc files in the assembly's directory.
      var XmlDocPaths = Directory.GetFiles(
        path: AppDomain.CurrentDomain.BaseDirectory,
        searchPattern: "YourAssemblyNameHere*.xml"
      );

      // load the XML docs for processing.
      var XmlDocs = (
        from DocPath in XmlDocPaths select XDocument.Load(DocPath)
      ).ToList();

      // ...<snip other code>

      // add pre-processed XML docs to Swagger.
      foreach(var doc in XmlDocs) 
        argOptions.IncludeXmlComments(() => new XPathDocument(doc.CreateReader()), true);

        // apply schema filter to add description of enum members.
        argOptions.SchemaFilter<DescribeEnumMembers>(doc);
      
    
  

记得更改 "YourAssemblyNameHere*.xml" 以匹配您的程序集名称。启用模式过滤器的重要行是:

argOptions.SchemaFilter<DescribeEnumMembers>(doc);

...必须在以下行之后调用:

argOptions.IncludeXmlComments(() => new XPathDocument(doc.CreateReader()), true);

使用上面的代码,如果你有一个像这样定义的枚举类型,例如:

  /// <summary>
  /// Setting to control when a no-match report is returned when searching.
  /// </summary>
  public enum NoMatchReportSetting
  
    /// <summary>
    /// Return no-match report only if the search query has no match.
    /// </summary>
    IfNoMatch = 0,
    /// <summary>
    /// Always return no-match report even if the search query has a match.
    /// </summary>
    Always = 1,
    /// <summary>
    /// Never return no-match report even if search query has no match.
    /// </summary>
    No = 99
  

Swagger 文档最终将显示每个枚举成员的描述,作为枚举类型本身描述的一部分:

【讨论】:

【参考方案2】:

此解决方案允许

显示基础价值以及名称/描述 处理多个 xml 文档文件,但只处理一次文档。 无需更改代码即可自定义布局

这是课程...

using System;
using System.Collections;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Xml.XPath;

using Microsoft.OpenApi.Models;

using Swashbuckle.AspNetCore.SwaggerGen;

namespace YourNamespace

    /// <summary>
    /// Swagger schema filter to modify description of enum types so they
    /// show the XML docs attached to each member of the enum.
    /// </summary>
    public class DescribeEnumMembers : ISchemaFilter
    
        private readonly XDocument xmlComments;
        private readonly string assemblyName;

        /// <summary>
        /// Initialize schema filter.
        /// </summary>
        /// <param name="xmlComments">Document containing XML docs for enum members.</param>
        public DescribeEnumMembers(XDocument xmlComments)
        
            this.xmlComments = xmlComments;
            this.assemblyName = DetermineAssembly(xmlComments);
        

        /// <summary>
        /// Pre-amble to use before the enum items
        /// </summary>
        public static string Prefix  get; set;  = "<p>Possible values:</p>";

        /// <summary>
        /// Format to use, 0 : value, 1: Name, 2: Description
        /// </summary>
        public static string Format  get; set;  = "<b>0 - 1</b>: 2";

        /// <summary>
        /// Apply this schema filter.
        /// </summary>
        /// <param name="schema">Target schema object.</param>
        /// <param name="context">Schema filter context.</param>
        public void Apply(OpenApiSchema schema, SchemaFilterContext context)
        
            var type = context.Type;

            // Only process enums and...
            if (!type.IsEnum)
            
                return;
            

            // ...only the comments defined in their origin assembly
            if (type.Assembly.GetName().Name != assemblyName)
            
                return;
            
            var sb = new StringBuilder(schema.Description);

            if (!string.IsNullOrEmpty(Prefix))
            
                sb.AppendLine(Prefix);
            

            sb.AppendLine("<ul>");

            // TODO: Handle flags better e.g. Hex formatting
            foreach (var name in Enum.GetValues(type))
            
                // Allows for large enums
                var value = Convert.ToInt64(name);
                var fullName = $"F:type.FullName.name";

                var description = xmlComments.XPathEvaluate(
                    $"normalize-space(//member[@name = 'fullName']/summary/text())"
                ) as string;

                sb.AppendLine(string.Format("<li>" + Format + "</li>", value, name, description));
            

            sb.AppendLine("</ul>");

            schema.Description = sb.ToString();
        

        private string DetermineAssembly(XDocument doc)
        
            var name = ((IEnumerable)doc.XPathEvaluate("/doc/assembly")).Cast<XElement>().ToList().FirstOrDefault();
            
            return name?.Value;
        
    

和利用率...

services.AddSwaggerGen(c =>

    ...
    
    // See https://github.com/domaindrivendev/Swashbuckle/issues/86
    var dir = new DirectoryInfo(AppContext.BaseDirectory);
    
    foreach (var fi in dir.EnumerateFiles("*.xml"))
    
        var doc = XDocument.Load(fi.FullName);
        c.IncludeXmlComments(() => new XPathDocument(doc.CreateReader()), true);
        c.SchemaFilter<DescribeEnumMembers>(doc);
    
);

然后报告为

【讨论】:

【参考方案3】:

不幸的是,OpenAPI 规范似乎不支持这一点。有一个开放的Github issue for this。

还有一个开放的Github issue for Swashbuckle。 但是,在这个问题中,有一个解决方法来创建一个模式过滤器,它至少在枚举类型描述中显示枚举值 cmets。

【讨论】:

【参考方案4】:

我使用描述属性解决了这个问题。这是一个示例用法:

public enum GenderEnum

    [Description("Man Description")]
    Man = 1,

    [Description("Woman Description")]
    Woman = 2

【讨论】:

添加这些注释后,UI 发生了哪些变化? 这在我的 SwaggerUI 中没有任何作用。 必须已经设置了描述 如果它比其他答案更容易,您可以发布一个示例作为答案

以上是关于SwaggerUI 不显示枚举摘要描述,C# .net 核心?的主要内容,如果未能解决你的问题,请参考以下文章

[小技巧]C#中如何为枚举类型添加描述方法

SwaggerUI 页面显示注释不显示条框

如何使用 Swashbuckle 的 SwaggerUI 显示静态 swagger.json 文件而不是 SwaggerGen 的动态创建的定义?

如何在 OpenAPI (Swagger) 中定义枚举?

windows常用系统命令

Swagger 在 OWIN Startup Web API C# 中不起作用