Вопрос

I'm using ServiceStack v 3.9.71 and the ServiceStack.Text.EnumMemberSerializer assembly to serialize enums into readable text.

This works great, my enum values are serialized into the name I've specified using the EnumMemberAttribute.

The problem, though, is Swagger does not use my names. My guess is it just calls the .ToString() method on the enum values rather than the EnumMemberAttribute value.

Here is the order in which I setup the serialization. (In AppHost):

new EnumSerializerConfigurator()
            .WithEnumTypes(new Type[] { typeof(MyEnum) })
            .Configure();

Plugins.Add(new SwaggerFeature());

It doesn't seem to matter if the enum serializer is set before or after the swagger feature is added.

Это было полезно?

Решение 3

I came up with, in my opinion, a better solution. I wrote a class that extends the ApiAllowableValuesAttribute:

public class ApiAllowableValues2Attribute : ApiAllowableValuesAttribute
{
    public ApiAllowableValues2Attribute(string name, Type enumType)
        : base(name)
    {
        List<string> values = new List<string>();

        var enumTypeValues = Enum.GetValues(enumType);

        // loop through each enum value
        foreach (var etValue in enumTypeValues)
        {
            // get the member in order to get the enumMemberAttribute
            var member = enumType.GetMember(
                Enum.GetName(enumType, etValue)).First();

            // get the enumMember attribute
            var enumMemberAttr = member.GetCustomAttributes(
                typeof(System.Runtime.Serialization.EnumMemberAttribute), true).First();

            // get the enumMember attribute value
            var enumMemberValue = ((System.Runtime.Serialization.EnumMemberAttribute)enumMemberAttr).Value;

            values.Add(enumMemberValue);

        }

        Values = values.ToArray();
    }
}

The client object:

public class MyClientObject
{
    [Description("The name")]
    public string Name {get;set;}

    [Description("The client object type")]
    [ApiAllowableValues2("MyEnum", typeof(MyEnum))]
    public MyEnum MyEnum { get; set; }
}

Now you don't have to specify the names again or worry about a name change breaking your Swagger documentation.

Другие советы

You are correct that the Swagger code does not use ServiceStack.Text.EnumMemberSerializer when parsing enum values. It only uses an Enum.GetValues here. Note that this is still the same in v4.

You can submit a pull request to make this change, but I'm not familiar with EnumMemberSerialzer and how it allows for retrieving the list of enum options. You may instead be able to use a string property decorated with ApiAllowableValues to achieve the affect.

Here is the solution I came up with (with the help of bpruitt-goddard, thanks mate):

The enum:

public enum MyEnum
{
    [EnumMember(Value = "Value One")]
    Value1 = 1,
    [EnumMember(Value = "Value Two")]
    Value2 = 2,
    [EnumMember(Value = "Value Three")]
    Value3 = 3
}

The client object:

public class MyClientObject
{
    [Description("The name")]
    public string Name {get;set;}

    [Description("The client object type")]
    [ApiAllowableValues("MyEnum", "Value One", "Value Two", "Value Three")]
    public MyEnum MyEnum { get; set; }
}

Inside the AppHost:

new EnumSerializerConfigurator()
            .WithEnumTypes(new Type[] { typeof(MyEnum) })
            .Configure();

Now the enum is serialized properly and the Swagger documentation is correct. The only issue with this is having the names in two different places. Perhaps there is a way to check the names match via a unit test.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top