ServiceStack.Text.EnumMemberSerializer не работает с плагином Swagger

Я использую ServiceStack v 3.9.71 и ServiceStack.Text.EnumMemberSerializer сборка для сериализации перечислений в читаемый текст.

Это прекрасно работает, мои значения enum сериализуются в имя, которое я указал, используя EnumMemberAttribute,

Проблема, однако, заключается в том, что Swagger не использует мои имена. Я думаю, это просто вызывает .ToString() метод на значениях перечисления, а не EnumMemberAttribute значение.

Вот порядок, в котором я настраиваю сериализацию. (В AppHost):

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

Plugins.Add(new SwaggerFeature());

Кажется, не имеет значения, установлен ли сериализатор enum до или после добавления функции чванства.

3 ответа

Решение

Я придумал, на мой взгляд, лучшее решение. Я написал класс, который расширяет 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();
    }
}

Клиентский объект:

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; }
}

Теперь вам не нужно снова указывать имена или беспокоиться об изменении имени, что нарушает вашу документацию Swagger.

Вы правы в том, что код Swagger не использует ServiceStack.Text.EnumMemberSerializer при анализе значений перечисления. Он использует только Enum.GetValues здесь Обратите внимание, что это все то же самое в v4.

Вы можете отправить запрос на выборку, чтобы внести это изменение, но я не знаком с EnumMemberSerialzer и тем, как он позволяет получать список опций перечисления. Вместо этого вы можете использовать строковое свойство, украшенное ApiAllowableValues, для достижения эффекта.

Вот решение, которое я придумал (с помощью bpruitt-goddard, спасибо, приятель):

Перечисление:

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

Клиентский объект:

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; }
}

Внутри AppHost:

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

Теперь перечисление правильно сериализовано и документация Swagger верна. Единственная проблема с этим - иметь имена в двух разных местах. Возможно, есть способ проверить совпадение имен с помощью юнит-теста.

Другие вопросы по тегам