Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Posting array of JSON objects to MVC3 action method via jQuery ajax

Does the model binder not suport arrays of JSON objects? The code below works when sending a single JSON domain object as part of the ajax post. However, when sending an array of JSON domain objects, the action parameter is null.

     var domains = [{
                        DomainName: 'testt1',
                        Price: '19.99',
                        Available: true
                    }, {
                        DomainName: 'testt2',
                        Price: '15.99',
                        Available: false
                    }];

                $.ajax({
                    type: 'POST',
                    url: Url.BasketAddDomain,
                    dataType: "json",
                    data: domains,
                    success: function (basketHtml) {

                    },
                    error: function (a, b, c) {
                        alert('A problem ocurred');
                    }
            });

This is the action method:

public ActionResult AddDomain(IEnumerable<DomainBasketItemModel> domain)
{
    ...

Any ideas if it is possible to do this?

EDIT

@Milimetric

Your solution works! However, this is my fault, but the code I demonstrated isn't the real code of my problem, I was trying to show equivalent code that is easier to understand.

I am actually creating an array, then interating some DOM elements and pushing a JSON object onto the array, then posting this array as the data...

var domains = [];

                $(this).parents('table').find('input:checked').each(function () {
                    var domain = {
                        DomainName: $(this).parent().parent().find('.name').html(),
                        Price: $(this).parent().parent().find('.price span').html(),
                        Available: $(this).parent().parent().find('.available').html() == "Available"
                    }

                    domains.push(domain);
                });

                $.ajax({
                    type: 'POST',
                    url: Url.BasketAddDomain,
                    dataType: "json",
                    data: { domain: domains },
                    success: function (basketHtml) {

                    },
                    error: function (a, b, c) {
                        alert('A problem ocurred');
                    }
                });
like image 275
jcvandan Avatar asked May 17 '11 13:05

jcvandan


2 Answers

You need:

var domains = { domains: [... your elements ...]};

            $.ajax({
                type: 'post',
                url: 'Your-URI',
                data: JSON.stringify(domains),
                contentType: "application/json; charset=utf-8",
                traditional: true,
                success: function (data) {
                    ...
                }
            });

In general, check out the Request object in the debugger, you'll see what's being passed and get an idea of how to "speak" HTTP.

NOTE: Just found this out. The model binder chokes on nullable decimal properties like:

public decimal? latitude { get; set; }

So it won't bind that if you're posting to it with a json string that looks like this:

{"latitude":12.0}

But it WILL work if you post something like this:

{"latitude":"12.0"}

See: http://syper-blogger.blogspot.com/2011/07/hello-world.html

like image 68
Milimetric Avatar answered Nov 19 '22 16:11

Milimetric


I had a similar problem. To solve it, I took a slightly different approach. Instead of a JSON object, I used arrays of hidden form variables. As long as the variable names matched up, model binding worked like a charm.

function AddDomainBasket(domainName, price, available) {

    if ( typeof AddDomainBasket.counter == 'undefined' ) {
        AddDomainBasket.counter = 0;
    }

    $("#some_form").append('<input type="hidden" name="[' + AddDomainBasket.counter + '].DomainName" value="' + domainName_index + '" />');
    $("#some_form").append('<input type="hidden" name="[' + AddDomainBasket.counter + '].Price" value="' + price + '" />');
    $("#some_form").append('<input type="hidden" name="[' + AddDomainBasket.counter + '].Available" value="' + available + '" />');

    ++AddDomainBasket.counter;
}

And then submit the serlialized form

$(this).parents('table').find('input:checked').each(function () {
    AddDomainBasket($(this).parent().parent().find('.name').html(),
                    $(this).parent().parent().find('.price span').html(),
                    $(this).parent().parent().find('.available').html() ==   "Available");
                }
            });

$.ajax({
    type: 'POST',
    url: Url.BasketAddDomain,
    data: $('#some_form').serialize(),
    success: function (basketHtml) {
        },
        error: function (a, b, c) {
            alert('A problem ocurred');
    }
});
like image 1
Steve Mallory Avatar answered Nov 19 '22 16:11

Steve Mallory