Mvc связывает проблему от json до enum (обычное исключение от int до enum) - PullRequest
3 голосов
/ 16 февраля 2011

У меня есть эта проблема: я использую JSON для отправки данных на сервер.Все работает нормально, но проблема в такой ситуации:

public enum SexType
{
  Male : 0,
  Female : 1
}

class People{
  public SexType Sex {get;set;}
}

Это создает мне json:

{"Sex" : 0}

Когда я отправляю обратно на сервер, это заполняет ModelStateError этой проблемой:Преобразование параметра из типа «System.Int32» в тип «SexType» завершилось неудачно, потому что преобразователь типов не может преобразовать эти типы в другие.

Но если я заключу значение в «все работает хорошо:

У кого-нибудь есть такая же проблема?

Tnx для всех!

Ответы [ 2 ]

6 голосов
/ 06 апреля 2011

Да, у меня та же проблема. Странная проблема в том, что если вы отправили обратно:

{"Sex" : 'Male'}

это не десериализовало бы никаких проблем. Чтобы решить эту проблему, я реализовал пользовательский механизм связывания моделей для перечислений, используя приведенный здесь пример (слегка измененный, поскольку были некоторые ошибки): http://eliasbland.wordpress.com/2009/08/08/enumeration-model-binder-for-asp-net-mvc/

namespace yournamespace
{
    /// <summary>
    /// Generic Custom Model Binder used to properly interpret int representation of enum types from JSON deserialization, including default values
    /// </summary>
    /// <typeparam name="T">The enum type to apply this Custom Model Binder to</typeparam>
    public class EnumBinder<T> : IModelBinder
    {
        private T DefaultValue { get; set; }

        public EnumBinder(T defaultValue)
        {
            DefaultValue = defaultValue;
        }

        #region IModelBinder Members
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            return bindingContext.ValueProvider.GetValue(bindingContext.ModelName) == null ? DefaultValue : GetEnumValue(DefaultValue, bindingContext.ValueProvider.GetValue(bindingContext.ModelName).AttemptedValue);
        }
        #endregion

        public static T GetEnumValue<T>(T defaultValue, string value)
        {
            T enumType = defaultValue;

            if ((!String.IsNullOrEmpty(value)) && (Contains(typeof(T), value)))
                enumType = (T)Enum.Parse(typeof(T), value, true);

            return enumType;
        }

        public static bool Contains(Type enumType, string value)
        {
            return Enum.GetNames(enumType).Contains(value, StringComparer.OrdinalIgnoreCase);
        }
    }
}

и затем зарегистрируйте подшивку модели в global.asax.cs. В вашем случае это будет что-то вроде:

ModelBinders.Binders.Add(typeof(SexType), new EnumBinder<SexType>(SexType.Male));

Я не уверен, что есть более быстрый путь, но это прекрасно работает.

2 голосов
/ 22 июня 2013

Привязка модели использует метод Enum.Parse (), который достаточно умен для интерпретации строк, но НЕ ЯВЛЯЕТСЯ явным образом приведением или преобразованием других типов в строки, даже если для этого существуют средства системного уровня, даже если онитип внутренней памяти, используемый в Enum.

Это правильное поведение?Возможно, так как, если вы не знаете достаточно для преобразования значений Enum в строки, вы можете не знать, что правая часть значений Enum также не обязательно уникальна в Enum.

В качестве личного вкуса (и это, вероятно, также потому, что я занимаюсь программированием статистического анализа) для секса я обычно предпочитаю определять его как явное булево значение, т.е. вместо того, чтобы различать произвольные значения для«Мужской» и «Женский» Я использую переменную с именем, например, IsFemale, и устанавливаю для нее значение true или false.Это лучше работает с json, поскольку оно опирается на примитивные типы, общие для обоих языков, и требует меньше ввода, когда вы хотите его использовать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...