如何在 Swagger 中获取枚举文档

问题描述 投票:0回答:1

我正在使用 Swagger API 文档,并希望在文档中包含我对枚举的描述。我正在使用自定义过滤器使用注释从类和枚举中提取信息。 例如:

    using System.ComponentModel;
    ...
    [DisplayName("Upload class")]            // Works fine
    public class Upload
    {
        [DisplayName("Primary Key")]          // Works fine
        public int UploadMetaId { get; set; }
        [Display(Name = "document name")]     // Works fine too
        public string Title { get; set; }
    }

但是我的枚举有问题:

[DisplayName("Document types")]    // Illegal, gives error CS0592
// or
[Display(Name = "Document types")]  // Illegal too, gives also CS0592
public enum UploadType
{
    [Display(Name = "Årsopgørelse")] // Works fine
    PartnerAarsopgoerelse = 1,
    [Display(Name = "Ægtefælles årsopgørelse")]
    AegtefaelleAarsopgoerelse = 2
}

错误 CS0592 表示它在此声明类型上无效。

那么我可以用什么来代替呢?

更新

我正在使用以下 NuGet 包:

  • Microsoft.OpenApi (1.6.15)
  • SwashBucle.AspNetCore(6.6.2)
c# enums swagger swashbuckle.aspnetcore
1个回答
0
投票

感谢@ralf 和他评论中的文章,我使用自己的 IDocumentFilter 创建了一个解决方案。

我希望我可以通过使用下面的代码来帮助某人进行大量搜索。

我在program.cs中从项目中获取XML文档并将相关的“摘要”传递给IDocumentFilter:

 private static void ConfigureServices(IServiceCollection services)
 {
     ...
     services.AddSwaggerGen(c =>
     {
         ...
         Dictionary<string, string> Dict = new Dictionary<string, string>();
         var dir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
         foreach (var filePath in System.IO.Directory.GetFiles(dir, "*.xml"))
         {
             c.IncludeXmlComments(filePath);
             GetXMLDoc(filePath, Dict);          
         }
         c.DocumentFilter<SwaggerEnumDocumentFilter>(Dict);               
     });
 }

private static void GetXMLDoc(string path, Dictionary<string,string> Dict)
{
    var _xmlComments = new XmlDocument();
    var reader = XmlReader.Create(path);
    _xmlComments.Load(reader);
    var xpath = $"//member[@name[starts-with(.,'F')] or @name[starts-with(.,'T')]]";
    var nodes = _xmlComments.DocumentElement.SelectNodes(xpath);
    foreach(XmlNode node in nodes)
    {
        var attribute = node.Attributes["name"];
        if (attribute != null)
        {
            string summary = node.FirstChild.InnerText.Trim(' ','\n');
            Dict.Add(attribute.Value, summary);
        }
    }
}

在过滤器中,我从传递的字典中选取 XML 文档:

public class SwaggerEnumDocumentFilter : IDocumentFilter
{

    Dictionary<string, string> EnumDescription = new Dictionary<string, string>();

    public SwaggerEnumDocumentFilter(Dictionary<string, string> enumDescription)
    {
        EnumDescription = enumDescription;
    }

    public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
    {
        // add enum descriptions Schemas section in Swagger
        foreach (var property in swaggerDoc.Components.Schemas)
        {
            var propertyEnums = property.Value.Enum;
            if (propertyEnums is { Count: > 0 })
            {
                property.Value.Description += DescribeEnum(property.Key, false);
            }
        }

        if (swaggerDoc.Paths.Count <= 0)
        {
            return;
        }

        //add enum descriptions to input parameters
        foreach (var pathItem in swaggerDoc.Paths.Values)
        {
            foreach (var operation in pathItem.Operations)
            {
                if (operation.Value.Parameters != null)
                {
                    foreach (var param in operation.Value.Parameters)
                    {
                        if (param.Schema.Reference != null)
                        {
                            param.Description += DescribeEnum(param.Schema.Reference.Id, true);
                        }
                    }
                }
            }
        }
    }

    private Type GetEnumTypeByName(string enumTypeName)
    {
        if (string.IsNullOrEmpty(enumTypeName))
        {
            return null;
        }

        try
        {
            return AppDomain.CurrentDomain
                            .GetAssemblies()
                            .SelectMany(x => x.GetTypes())
                            .Single(x => x.FullName != null && x.Name == enumTypeName);
        }
        catch (InvalidOperationException e)
        {
            throw new Exception($"SwaggerDoc: Can not find a unique Enum for specified typeName '{enumTypeName}'. Please provide a more unique enum name.");
        }
    }

    private string DescribeEnum(string propertyTypeName, bool inApiList)
    {
        var enumType = GetEnumTypeByName(propertyTypeName);

        if (enumType == null)
        {
            return null;
        }

        var values = Enum.GetValues(enumType);
        if (values == null)
        {
            return null;
        }

        string result = "<ul>";

        if (inApiList)
        {
            var key = $"T:{enumType.FullName}";
            var summary = EnumDescription.ContainsKey(key) ? EnumDescription[key] : "";
            result = $"<p>{summary}</p><ul>";
        }

        foreach (var value in values)
        {
            var key = $"F:{enumType.FullName}.{value}";
            var summary = EnumDescription.ContainsKey(key) ? EnumDescription[key] : "";
            string n = EnumUtils.GetDisplayName((System.Enum)value);
            result += $"<li>{(int)value} - {n} : {summary} </li>";
        }
        result += "</ul>";
        return result;
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.