是否有一种方法显示所有枚举作为他们的字符串值在swagger而不是他们的int值?

我希望能够提交POST动作,并根据它们的字符串值放置枚举,而不必每次都查看enum。

我尝试了DescribeAllEnumsAsStrings,但服务器然后接收字符串而不是enum值,这不是我们要寻找的。

有人解决了吗?

编辑:

public class Letter 
{
    [Required]
    public string Content {get; set;}

    [Required]
    [EnumDataType(typeof(Priority))]
    public Priority Priority {get; set;}
}


public class LettersController : ApiController
{
    [HttpPost]
    public IHttpActionResult SendLetter(Letter letter)
    {
        // Validation not passing when using DescribeEnumsAsStrings
        if (!ModelState.IsValid)
            return BadRequest("Not valid")

        ..
    }

    // In the documentation for this request I want to see the string values of the enum before submitting: Low, Medium, High. Instead of 0, 1, 2
    [HttpGet]
    public IHttpActionResult GetByPriority (Priority priority)
    {

    }
}


public enum Priority
{
    Low, 
    Medium,
    High
}

当前回答

我得到了它的工作。net 6 Web API使用以下代码从其他答案在这里:

1 -创建一个DocumentFilter

/// <summary>
/// Add enum value descriptions to Swagger
/// </summary>
public class SwaggerEnumDocumentFilter : IDocumentFilter
{
    public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
    {
        // add enum descriptions to result models
        foreach (var property in swaggerDoc.Components.Schemas)
        {
            var propertyEnums = property.Value.Enum;
            if (propertyEnums is { Count: > 0 })
            {
                property.Value.Description += DescribeEnum(propertyEnums, property.Key);
            }
        }

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

        // add enum descriptions to input parameters
        foreach (var pathItem in swaggerDoc.Paths.Values)
        {
            DescribeEnumParameters(pathItem.Parameters);

            var affectedOperations = new List<OperationType> { OperationType.Get, OperationType.Post, OperationType.Put, OperationType.Patch };

            foreach (var operation in pathItem.Operations)
            {
                if (affectedOperations.Contains(operation.Key))
                {
                    DescribeEnumParameters(operation.Value.Parameters);
                }
            }
        }
    }

    private static void DescribeEnumParameters(IList<OpenApiParameter> parameters)
    {
        if (parameters == null) return;

        foreach (var param in parameters)
        {
            if (param.Schema.Reference != null)
            {
                var enumType = GetEnumTypeByName(param.Schema.Reference.Id);
                var names = Enum.GetNames(enumType).ToList();

                param.Description += string.Join(", ", names.Select(name => $"{Convert.ToInt32(Enum.Parse(enumType, name))} - {name}").ToList());
            }
        }
    }

    private static 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 static string DescribeEnum(IEnumerable<IOpenApiAny> enums, string propertyTypeName)
    {
        var enumType = GetEnumTypeByName(propertyTypeName);

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

        var parsedEnums = new List<OpenApiInteger>();
        foreach (var @enum in enums)
        {
            if (@enum is OpenApiInteger enumInt)
            {
                parsedEnums.Add(enumInt);
            }
        }

        return string.Join(", ", parsedEnums.Select(x => $"{x.Value} - {Enum.GetName(enumType, x.Value)}"));
    }

}

2 -将其添加到Program.cs文件中

   services.AddSwaggerGen(config =>
        {

            config.DocumentFilter<SwaggerEnumDocumentFilter>();

        })

其他回答

.Net Core 3.0

   using Newtonsoft.Json.Converters;

 services
    .AddMvc(options =>
    {
     options.EnableEndpointRouting = false;
     })
    .AddNewtonsoftJson(options => options.SerializerSettings.Converters.Add(new StringEnumConverter()))

如果大摇大摆的版本是5.5。X,那么你需要:

安装:install - package swashbuckl . aspnetcore . newtonsoft -Version 5.5.0 services.AddSwaggerGenNewtonsoftSupport ();

参考:https://github.com/domaindrivendev/Swashbuckle.AspNetCore # systemtextjson-stj-vs-newtonsoft

asp.net core 3

using System.Text.Json.Serialization;

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
         services.AddControllers().AddJsonOptions(options =>
             options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));

但是Swashbuckle Version 5.0.0-rc4似乎还没有准备好支持这个功能。所以我们需要在Swashbuckle配置文件中使用一个选项(已弃用),直到它像Newtonsoft库一样支持和反映它。

public void ConfigureServices(IServiceCollection services)
{ 
      services.AddSwaggerGen(c =>
      {
            c.DescribeAllEnumsAsStrings();

这个答案和其他答案之间的区别是只使用Microsoft JSON库而不是Newtonsoft。

为了得到Swagger和. net版本6的答案,我遇到了一些问题。x工作。我想继续为枚举使用整数值,但也要显示可能值的列表(以可读的格式)。所以这是我的修改版本(包括一些答案的部分),也许它可以为你们节省一些时间;)

附注:还有一些改进的空间,你也应该检查方法“GetEnumTypeByName”的逻辑是否适合你。在我的情况下,我想主要更新描述仅为项目内部和唯一的枚举。

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Models.Api;
using Swashbuckle.AspNetCore.SwaggerGen;

/// <summary>
/// Add enum value descriptions to Swagger
/// </summary>
public class SwaggerEnumDocumentFilter : IDocumentFilter
{
    public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
    {
        // add enum descriptions to result models
        foreach (var property in swaggerDoc.Components.Schemas)
        {
            var propertyEnums = property.Value.Enum;
            if (propertyEnums is { Count: > 0 })
            {
                property.Value.Description += DescribeEnum(propertyEnums, property.Key);
            }
        }

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

        // add enum descriptions to input parameters
        foreach (var pathItem in swaggerDoc.Paths.Values)
        {
            DescribeEnumParameters(pathItem.Parameters);

            var affectedOperations = new List<OperationType> { OperationType.Get, OperationType.Post, OperationType.Put };

            foreach (var operation in pathItem.Operations)
            {
                if (affectedOperations.Contains(operation.Key))
                {
                    DescribeEnumParameters(operation.Value.Parameters);
                }
            }
        }
    }

    private static void DescribeEnumParameters(IList<OpenApiParameter> parameters)
    {
        if (parameters == null) return;

        foreach (var param in parameters)
        {
            if (param.Schema.Reference != null)
            {
                param.Description += DescribeEnum(param.Schema.Reference.Id);
            }
        }
    }

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

        try
        {
            var projectNamespaceRoot = "MyProject.";

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

    private static string DescribeEnum(IEnumerable<IOpenApiAny> enums, string propertyTypeName)
    {
        var enumType = GetEnumTypeByName(propertyTypeName);

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

        var parsedEnums = new List<OpenApiInteger>();
        foreach (var @enum in enums)
        {
            if (@enum is OpenApiInteger enumInt)
            {
                parsedEnums.Add(enumInt);
            }
        }

        return string.Join(", ", parsedEnums.Select(x => $"{x} = {Enum.GetName(enumType, x.Value)}"));
    }
}

正如其他人已经提到的,你必须在你的Swagger设置中注册这个过滤器:

services.AddSwaggerGen(options =>
        {
            options.SwaggerDoc("v1", new OpenApiInfo
            {
                // some configuration
            });
              
            options.DocumentFilter<SwaggerEnumDocumentFilter>();
        });

我的枚举变量带有值:

配置服务:

services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "web server api", Version = "v1" });
                c.SchemaFilter<EnumSchemaFilter>();
            });

过滤器:

public class EnumSchemaFilter : ISchemaFilter
    {
        public void Apply(OpenApiSchema model, SchemaFilterContext context)
        {
            if (context.Type.IsEnum)
            {
                model.Enum.Clear();
                Enum.GetNames(context.Type)
                    .ToList()
                    .ForEach(name => model.Enum.Add(new OpenApiString($"{Convert.ToInt64(Enum.Parse(context.Type, name))} - {name}")));
            }
        }
    }