从json到enum的mvc绑定问题(从int到enum的customexception)

时间:2011-02-16 14:43:47

标签: json model-view-controller binding

我有这个问题:我使用json将数据发送到服务器。 一切正常,但问题是这样的情况:

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

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

这创造了我的json:

{"Sex" : 0}

当我发送回服务器时,这会填充ModelStateError并出现此问题: 从类型'System.Int32'到类型'SexType'的参数转换失败,因为没有类型转换器可以在这些类型之间进行转换。

但是,如果我用“一切正常”包装价值:

{"Sex" : '0'}

任何人都有同样的问题吗?

Tnx for all!

2 个答案:

答案 0 :(得分:6)

是的,我遇到了同样的问题。奇怪的问题是如果你发回来了:

{"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));

我不确定是否有更快的方法,但这很有效。

答案 1 :(得分:2)

模型绑定使用Enum.Parse()方法,该方法在解释字符串方面相当聪明,但是没有明确地将其他类型转换或转换为字符串,即使存在系统级设施也是如此,即使它们是Enum中使用的内部存储类型。

这是正确的行为吗?可以这么说,因为如果你不知道将你的枚举值转换为字符串,你可能不会意识到Enum值的右边在Enum中也不一定是唯一的。

作为个人品味的问题(也许这也可能是因为我做了太多的统计分析编程)对于性爱我通常更喜欢将其定义为一个明确的布尔值,即不是区分“男性”的任意值和'女'我使用一个名为eg的变量IsFemale并将其设置为true或false。这与json的效果更好,因为它依赖于两种语言共有的原始类型,并且当你想要使用它时需要更少的输入。