MVC4 操作中的反序列化对象导致空值

Posted

技术标签:

【中文标题】MVC4 操作中的反序列化对象导致空值【英文标题】:De-serializing object in MVC4 action results in null values 【发布时间】:2013-02-06 02:02:06 【问题描述】:

我正在使用 jQuery 1.9.1 和 MVC 4。

我有以下 javascript

$.ajax(
    url: '/Home/doSomething',
    type: 'POST',
    data: JSON.stringify( devices: [ Id: 123, Name: "something", MapName: "map" , Id: 321, Name: "a name", MapName: "another map" ] ),
    dataType: 'json',
    contentType: 'application/json'

以及我的 HomeController 中的以下 c#:

[HttpPost]
public string doSomething( Device[ ] devices )

    //stuff consuming that array

Device 类的定义如下:

[Serializable]
public class Device

    public long Id;
    public string Name;
    public string MapName;

根据调试器,devices 数组是一个 2 元素数组,每个 Device 元素的所有属性都为 null。

根据chrome,post数据是这样的:


    "devices": [
        
            "Id": 123,
            "Name": "something",
            "MapName": "map"
        ,
        
            "Id": 321,
            "Name": "a name",
            "MapName": "another map"
        
    ]

这里有什么问题让 MVC 发誓这些对象是空的,但仍然给我一个适当长度的数组?

我尝试过直接发布数组,而不对其调用 JSON.stringify。 我已经尝试将数组作为一个名为“设备”的属性发布在一个对象内,但又没有对其进行区分。 我已经尝试将数组作为一个名为“设备”的属性发布到一个对象中,同时只对数组本身进行字符串化。

所有这些都会导致一种或另一种形式的不良行为。要么 chrome 没有首先发布适当的数据,要么 MVC 没有反序列化它。

我在网上搜索过,似乎找不到任何应该破坏它的例子。

编辑 2013-02-21 13:12 UTC-5:

我也尝试过不使用 JSON 并让 jQuery 将其作为表单数据发布。 这是代码:

var postData =  devices: [ Id: 123, Name: "something", MapName: "map" ,  Id: 321, Name: "a name", MapName: "another map" ] ;
$.ajax(
    url: '/Home/doSomething',
    type: 'POST',
    data: postData
);

而且C#还是和上面一样。

不过,该行为仍与使用 JSON 时相同。 MVC 看到一个包含 2 个元素的数组,但该数组中对象的所有值都是默认值(整数为 0,字符串为 null)。

【问题讨论】:

对于它的价值,当我不将其发布为 JSON 时,这也会失败。我没有使用 JSON 与此结婚,但我确实需要 MVC 来反序列化发布数据 /somehow/。 【参考方案1】:

这就是最终奏效的方法......

首先,我更改了 javascript 以使用名为“devices”的属性创建对象,该属性包含字符串化数组:

var postData =  devices: JSON.stringify([ Id: 123, Name: "something", MapName: "map" ,  Id: 321, Name: "a name", MapName: "another map" ]) ;
$.ajax(
    url: '/Home/doSomething',
    type: 'POST',
    dataType: 'json',
    data: postData
    

然后我让控制器动作接受一个名为“设备”的字符串,并使用 JSON.Net 手动反序列化:

[HttpPost]
public string MakeMmLinks( string devices )

    List<Device> devicesList = JsonConvert.DeserializeObject<List<Device>>( devices );
    ...

这很好,但让我困扰的是对象反序列化应该是 MVC 原生处理的东西。

如果有人对这里发生的事情或我做错了什么有任何见解,我很想听听。

【讨论】:

没有任何见解,但谢谢,我花了很长时间在同一个问题上摸不着头脑。【参考方案2】:

在这种情况下,我发现tradition: true 非常重要。不确定你需要字符串化

dataType: 'json',
traditional: true

【讨论】:

【参考方案3】:

您正在发布一个 object,其属性包含 2 个设备的数组。 如果您只想发布设备数组,请尝试以下操作。

var devices = [ Id: 123, Name: "something", MapName: "map" ,  Id: 321, Name: "a name", MapName: "another map" ];
$.ajax(
    url: '/Home/doSomething',
    type: 'POST',
    data: JSON.stringify(devices),
    dataType: 'json',
    contentType: 'application/json'
);

【讨论】:

这就是我最初的做法,并导致相同的行为。 MVC 接收数组,知道其中有多少元素,并将元素的所有属性设置为 null。 为什么要向控制器发布字符串?发布 js 对象本身。 直接发布数组也会导致不良行为。当我直接发布数组时,Chrome 会发送 "undefined=&undefined=" 作为发布数据。

以上是关于MVC4 操作中的反序列化对象导致空值的主要内容,如果未能解决你的问题,请参考以下文章

使用 Jackson 从 XML 到 POJO 的反序列化问题:没有从字符串值反序列化的字符串参数构造函数/工厂方法

使用 XmlSerializer 将空 xml 属性值反序列化为可为空的 int 属性

.net 3.5 中的反序列化对象

没有像默认构造一样的创建者):不能从对象值反序列化(没有基于委托或属性的创建者

反序列化错误 : 不能构造Dto的实例(尽管至少有一个Creator存在):不能从对象值反序列化。

根据字段值反序列化为密封子类