【问题标题】:ASP.Net MVC3 - why does the default support for JSON model binding fail to decode to enum types?ASP.Net MVC3 - 为什么对 JSON 模型绑定的默认支持无法解码为枚举类型?
【发布时间】:2011-01-03 05:24:07
【问题描述】:

我遇到了 ASP.Net MVC3 (RC2) 的问题。我发现 MVC3 中隐含的新 JSON 模型绑定功能不想反序列化为具有枚举类型的属性。

这是一个示例类和枚举类型:

public enum MyEnum { Nothing = 0, SomeValue = 5 }
public class MyClass
{
    public MyEnum Value { get; set; }
    public string OtherValue { get; set; }
}

考虑以下代码,它成功通过了单元测试:

[TestMethod]
public void Test()
{
    var jss = new JavaScriptSerializer();
    var obj1 = new MyClass { Value = MyEnum.SomeValue };
    var json = jss.Serialize(obj1);
    var obj2 = jss.Deserialize<MyClass>(json);
    Assert.AreEqual(obj1.Value, obj2.Value);
}

如果我序列化上面的obj1,然后将该数据发布到具有 MyClass 类型的单个参数的 MVC3 控制器(下面的示例),则对象的任何其他属性都会正确反序列化,但任何枚举类型的属性都会反序列化到默认(零)值。

[HttpPost]
public ActionResult TestAction(MyClass data)
{
    return Content(data.Value.ToString()); // displays "Nothing"
}

我已经从 codeplex 下载了 MVC 源代码,但我不知道执行反序列化的实际代码发生在哪里,这意味着我无法弄清楚 Microsoft 的人用来执行反序列化的内容,因此确定我做错了什么或是否有解决方法。

任何建议将不胜感激。

【问题讨论】:

标签: json asp.net-mvc-3


【解决方案1】:

我找到了答案。我希望这在 MVC3 RTM 中得到修复,但本质上发生的是对象通过JsonValueProviderFactory 在内部正确反序列化,它使用JavaScriptSerializer 来完成工作。它使用DeserializeObject(),以便可以将值传递回默认模型绑定器。问题是当属性类型是枚举时,默认模型绑定器不会转换/分配 int 值。

在此处的 ASP.Net 论坛上对此进行了讨论:
http://forums.asp.net/p/1622895/4180989.aspx

这里讨论的解决方案是像这样覆盖默认模型绑定器:

public class EnumConverterModelBinder : DefaultModelBinder
{
    protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder)
    {
        var propertyType = propertyDescriptor.PropertyType;
        if(propertyType.IsEnum)
        {
            var providerValue = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
            if(null != providerValue)
            {
                var value = providerValue.RawValue;
                if(null != value)
                {
                    var valueType = value.GetType();
                    if(!valueType.IsEnum)
                    {
                        return Enum.ToObject(propertyType, value);
                    }
                }
            }
        }
        return base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder);
    }
}

然后在Application_Start 中,添加以下行:

ModelBinders.Binders.DefaultBinder = new EnumConverterModelBinder();

【讨论】:

  • 此问题将在 ASP.NET MVC 的下一版本中修复。
【解决方案2】:

你怎么称呼这个动作?你试过了吗:

$.post(
    '/TestAction', 
    JSON.stringify({ OtherValue : 'foo', Value: 5 }), 
    function(result) {
        alert('ok');
    }
);

【讨论】:

  • 我不是从网页调用它,而是通过WebClient.UploadString() 从另一个应用程序调用它。后期处理确实有效,只是类的枚举属性不反序列化。所有其他属性都很好。
  • 我发现了问题; DefaultModelBinder 类不会将整数转换为枚举。 forums.asp.net/p/1622895/4180989.aspx
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-03
  • 1970-01-01
  • 2011-09-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多