question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Enums marked with alternate values using [EnumMember(Value="...")] are not supported

See original GitHub issue

Below is copied from https://github.com/domaindrivendev/Swashbuckle/issues/562, because I am seeing the same issue in Swashbuckle.AspNetCore. It looks like someone attempted to fix this in https://github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/414, but that PR is pretty out-of-date, and failing CI. That fix there appears to be replicating https://github.com/domaindrivendev/Swashbuckle/pull/563, but those changes are now out-of-date as well in Swashbuckle, as the enum schema is now generated using a Type extension.

Forgive the contrived example, but given the following code:

public class DefaultController : ApiController
{
    [ResponseType(typeof(TestResult))]
    public IHttpActionResult Get(string id)
    {
        return this.Ok(new TestResult());
    }
}

[DataContract]
public class TestResult
{
    [DataMember]
    public TestEnum Type { get; set; }
}

[DataContract]
public enum TestEnum
{
    [EnumMember(Value = "roger")]
    None = 0,
    [EnumMember(Value = "blake")]
    Something = 1,
    [EnumMember(Value = "sarah")]
    SomethingElse = 2
}

The API will return “roger”, “blake” or “sarah” depending on the enum value. Swashbuckle does not pick up on the alternative names and reports that the potential options are “None”, “Something” or “SomethingElse”.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:1
  • Comments:9 (2 by maintainers)

github_iconTop GitHub Comments

2reactions
elize-vdrcommented, Jan 21, 2022

In case anybody needs a solution I solved it in the following way: For this enum:

    public enum AssociationMultiplicity {
        [EnumMember(Value = "unknown")]
        Unknown,
        [EnumMember(Value = "zero-or-one")]
        ZeroOrOne,
        [EnumMember(Value = "one")]
        One,
        [EnumMember(Value = "many")]
        Many
    }

Create an extension for the enumerator to convert the value to the EnumMember attribute value, here it is:

    public static class AssociationMultiplicityExtension
    {
        public static string GetEnumMember(this AssociationMultiplicity value)
        {
            var type = value.GetType();
            var name = Enum.GetName(type, value);
            if (name == null)
                return null;
            var field = type.GetField(name);
            if (field is null || !Attribute.IsDefined(field, typeof(EnumMemberAttribute)))
                return null;
            if (Attribute.GetCustomAttribute(field, typeof(EnumMemberAttribute)) is EnumMemberAttribute attr)
            {
                return attr.Value;
            }
            return null;
        }
}

Then create a SchemaFilter class like this:

public class ProblemDetailsSchemaFilter : ISchemaFilter
{
    
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {        
        if (context.Type == typeof(AssociationMultiplicity))
        {
            schema.Enum.Clear();
            var valuesArray = Enum.GetValues(typeof(AssociationMultiplicity));

            foreach (AssociationMultiplicity val in valuesArray)
            {
                schema.Enum.Add(new OpenApiString(val.GetEnumMember()));
            }

        }
    }
}

And register this SchemaFilter in the ConfigureServices where the AddSwaggerGen is called:

services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebContractsParsing API - V1", Version = "v1" });
    // For future versions an example, see here: https://github.com/domaindrivendev/Swashbuckle.AspNetCore#include-descriptions-from-xml-comments
    // c.SwaggerDoc("v2", new OpenApiInfo { Title = "WebContractsParsing API - V2", Version = "v2" });

    var filePath = Path.Combine(System.AppContext.BaseDirectory, "WebContractsParsingApi.xml");
    c.IncludeXmlComments(filePath);
    
    c.DescribeAllParametersInCamelCase();

    c.SchemaFilter<ProblemDetailsSchemaFilter>();
}

And there the EnumMember value is in the swagger UI spec image

0reactions
xhafancommented, Jun 13, 2022

@elize-vdr’s solution does not work for me for 6.3.1, but it helped me to create a solution which works for me:

public class IgnoreEnumMemberValueSchemaFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        if (context.Type == typeof(AssociationMultiplicity))
        {
            schema.Enum.Clear();
            var enumValues = Enum.GetValues(typeof(AssociationMultiplicity));

            foreach (var val in enumValues)
            {
                schema.Enum.Add(new OpenApiString(GetEnumConstantNameIgnoringEnumMemberValue(val)));
            }
        }
    }

    private string GetEnumConstantNameIgnoringEnumMemberValue<TEnum>(TEnum value)
    {
        var type = value.GetType();
        return Enum.GetName(type, value);
    }
}

It basically ignores EnumMember values, and uses enum constant names as if the EnumMember attribute is missing.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How To Serialize Nonstandard Enum Values
The EnumMember attribute is used to drive serializing of non-standard enum values using both DataContract serialization and Newtonsoft JSON ...
Read more >
c# - Swagger UI Web Api documentation Present enums as ...
It's nuts that swagger doesn't display BOTH the name and value for each enum, and instead displays number alone (useless) or names alone...
Read more >
Enums
You can use the enum keyword to specify possible values of a request parameter or a model property. For example, the sort parameter...
Read more >
EnumMemberAttribute Class (System.Runtime.Serialization)
Specifies that the field is an enumeration member and should be serialized.
Read more >
Attaching Values to Java Enum
By default, Enum.toString() returns the same value as Enum.name(). 7.2. Implementing an Interface. The enum type in Java can implement ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found