ASP.Net MVC 3 - JSON Model binding to array

2019-02-02 08:37发布

问题:

I am on ASP.Net MVC 3, and going by the feature list supported in at, i should be able to get default json model binding working out of the box. However i havent been successful in binding an array/collection from json to the action method parameter. Although I did get simple json object binding working right. Would greatly appreciate if an expert here could tell me what i am doing wrong.

Here is the code:

Server side code first:

//Action Method

 public JsonResult SaveDiscount(IList<Discount> discounts)
    {
       foreach(var discount in discounts)
       {
       ....
       }
    }

//View model

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

}

//client side(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
    }

i did check the json payload in fiddler and it look like below:

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

And on the server side i do see the IList<Discount> discounts has been populated with 3 empty Discount objects - meaning the properties are null but the length of the discounts argument is 3.

回答1:

As Cresnet Fresh rightly pointed out in the comments to the question the model properties must be marked public.

So modifying Discount class as below resolved this.

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

}


回答2:

while @thanikkal answered this particular question, I had the same symptoms and a very similar setup.

instead of the public or { get; set; } in my models causing the model binding to not work it was actually my jQuery method! (RAWR!)

I was using $.post (which didn't work) instead of $.ajax.


Doesn't Work:

$.post("/Games/Action",
   { "userId": "1", "listName": [ { "fooId": "2", "barId": "99" } ] },
   'json',
   true
  );

The values are in the Form.Data[], but are not mapped properly.


Works:

 $.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);
        }
    });

All values mapped correctly.


Lost a few hours to this one, hope this helps others.



回答3:

Your code looks fine.. But check this

  1. Routing settings.
  2. Put [HttpPost] attribute on SaveDiscount

and try this

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

that would give make right data binding.