ASP.Net MVC 3 - 将JSON绑定到数组的模型

17
我正在使用ASP.Net MVC 3,根据支持的功能列表,我应该能够轻松地使用默认的JSON模型绑定。然而,我无法成功地将数组/集合从JSON绑定到操作方法参数。虽然我确实成功了将简单的JSON对象绑定正确。如果有专家能告诉我问题出在哪里,我将不胜感激。
以下是代码:
首先是服务器端代码:
// Action 方法
 public JsonResult SaveDiscount(IList<Discount> discounts)
    {
       foreach(var discount in discounts)
       {
       ....
       }
    }

//视图模型

public class Discount
{
    string Sku{get; set;}
    string DiscountValue{get; set;}
    string DiscountType{get; set;}

}

//客户端(jQuery/JS):

    var discount = {};
    var jsondatacoll = [];
    $('#discountgrid tr').each(function () {

        sku = $(this).find("td").eq(1).html();
        discValue = $(this).find('.discval').val();
        discType = $(this).find('.disctype').val();

        discount = { Sku: sku, DiscountType: discType, DiscountValue: discValue};
        jsondatacoll.push(discount);
        }
    })
    if (jsondatacoll.length > 0) {
        var catalogDiscount = JSON.stringify(jsondatacoll);

        $.ajax(
        {
            url: '/url/savediscount',
            type: 'POST',
            data: catalogDiscount,
            dataType: 'json',
            contentType: 'application/json; charset=utf-8',
            success: function (data, textStatus, jqXHR) {
                ...                   
            },
            error: function (objAJAXRequest, strError) {                 
               ...
            }
        }
     );   //ajax
    }

我在 Fiddler 中检查了 JSON 负载,它看起来像下面这样:

[
    {"Sku":"sku1","DiscountType":"type1","DiscountValue":"10"},     
    {"Sku":sku2","DiscountType":"type1","DiscountValue":"12"}, 
    {"Sku":"sku3","DiscountType":"type2","DiscountValue":"40"}
]

在服务器端,我看到IList<Discount> discounts 已经被填充了3个空的Discount对象 - 这意味着属性为null,但是折扣参数的长度为3。


15
你的模型属性应该标记为“public”。这是打字错误还是疏忽? - Crescent Fresh
哇,伙计!那是个疏忽啊!你想把这作为答案输入,这样我就可以标记它了吗? :) - thanikkal
5
感谢您的帖子除了那些缺失的“publics”以外都是正确的。我注意到contentType与使用JSON.stringify一起设置,这使得一切变得不同。我为此苦苦挣扎了数小时!谢谢! - Daniel Gill
如果你喜欢@DanielGill评论中提到的内容,可以查看这篇文章,介绍如何通过ajax发送复杂数据类型 http://encosia.com/using-complex-types-to-make-calling-services-less-complex/ - RyanfaeScotland
3个回答

14

正如Cresnet Fresh在评论中指出的那样,模型属性必须标记为public。

因此,将Discount类修改如下即可解决此问题。

public class Discount
{
    public string Sku{get; set;}
    public string DiscountValue{get; set;}
    public string DiscountType{get; set;}

}

有人能解释一下(最好是提供一个解释的链接),为什么必须这样做吗?我猜想是因为首先创建了一个空对象(因此需要无参构造函数),然后设置属性,但我更喜欢基于事实而非猜测工作。 - RyanfaeScotland

11

@thanikkal回答这个问题时,我遇到了相同的症状和非常相似的设置。

不是我的模型中的public{ get; set; }导致模型绑定不起作用,而是我的jQuery方法!(RAWR!)

我使用的是$.post(它不起作用),而不是$.ajax


不起作用:

$.post("/Games/Action",
   { "userId": "1", "listName": [ { "fooId": "2", "barId": "99" } ] },
   'json',
   true
  );
数值在Form.Data[]中,但未正确映射。

要求:

 $.ajax(
    {
        url: '/Games/Action',
        type: 'POST',
        data: JSON.stringify({ userId: "1", listName: [ { fooId: 2, barId: 99 } ] }),
        dataType: 'json',
        contentType: 'application/json; charset=utf-8',
        success: function (data, textStatus, jqXHR)
        {
            console.log(data);
        },
        error: function (objAJAXRequest, strError)
        {
            console.log(data);
        }
    });

所有数值都被正确映射。


为此浪费了几个小时,希望这可以帮助其他人。


2
我可以确认上述内容是真实的。我使用了$.post,虽然我在我的模型中看到一个数组被填充,但所有的值都是null。转而使用$.ajax解决了这个问题,这似乎很奇怪。我使用的是MVC 4,jQuery 2.0.2。 - David Hirst
谢谢,我想这节省了我几个小时的时间。 - Ronnie
1
只是为了更详细地解释一下,$.post()函数是$.ajax()的简写形式,如此处所述:http://api.jquery.com/jquery.post/。但是调用$.ajax()时并不包括contentType属性。上述解决方案对我有效,但如果我移除contentType属性,则无效,因此这正是我需要的(至少在我的情况下)。 - Ronnie

-1

你的代码看起来没问题。但是请检查以下内容:

  1. 路由设置。
  2. 在 SaveDiscount 上加上 [HttpPost] 属性。

然后尝试一下这个:

var catalogDiscount = JSON.stringify( { discounts: jsondatacoll } );

那将会产生正确的数据绑定。


感谢您在这里回答。如上面的评论所解释的那样,我忘记将我的ViewModel属性标记为public。 - thanikkal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接