views:

3563

answers:

4

I have a controller defined as:

        [AcceptVerbs(HttpVerbs.Post)]
        public JsonResult PostMoreData(DataContracts.Address address, DataContracts.GeoLocation geoLocation)
        {
            return Json("test");
        }

where DataContracts.Address and DataContracts.GeoLocation are complex types.

From my View i'm trying to post using jQuery as such:

        function PostMoreData() {

            var JsonAddress = {

                "Building": $('Building').val(),
                "UnitNumber": $('UnitNumber').val(),
                "StreetNumber": $('StreetNumber').val(),
                "StreetName": $('StreetName').val(),
                "StreetType": $('StreetType').val(),
                "Suburb": $('Suburb').val(),
                "State": $('State').val(),
                "Postcode": $('Postcode').val(),
                "MonthsAtAddress": $('MonthsAtAddress').val()

            };

            var JsonGeoLocation = {
                "Latitude": $('Latitude').val(),
                "Longitude": $('Longitude').val()
            };


            jQuery.post("/AddressValidation/PostMoreData", {address: JsonAddress, geoLocation: JsonGeoLocation}, function(data, textStatus) {
                if (textStatus == "success") {
                    var result = eval(data);
                    if (result.length > 0) {
                        alert(result);
                    }
                }
            }, "json");
        } 

However, on the controller, I get nulls.


It works if my Controller takes just 1 argument and I post just one object.

        [AcceptVerbs(HttpVerbs.Post)]
        public JsonResult PostMoreData(DataContracts.Address address)
        {
            return Json("test");
        }
        function PostMoreData() {

            var JsonAddress = {

                "Building": $('Building').val(),
                "UnitNumber": $('UnitNumber').val(),
                "StreetNumber": $('StreetNumber').val(),
                "StreetName": $('StreetName').val(),
                "StreetType": $('StreetType').val(),
                "Suburb": $('Suburb').val(),
                "State": $('State').val(),
                "Postcode": $('Postcode').val(),
                "MonthsAtAddress": $('MonthsAtAddress').val()

            };


            jQuery.post("/AddressValidation/PostMoreData", JsonAddress, function(data, textStatus) {
                if (textStatus == "success") {
                    var result = eval(data);
                    if (result.length > 0) {
                        alert(result);
                    }
                }
            }, "json");
        } 

Any ideas how i can post more than one object?

+2  A: 

Your code requires that the way jquery serializes an object is compatible with the MVC default model binder, which I think is unlikely.

If you can build your javascript object so that it serializes as a flat object with dot notation (JsonAddress.Building) that would work, or you can let jquery do the default serialization and then create a custom model binder to deserialize to the action parameter types.

liammclennan
+1  A: 

Note that the "default serialization" that jQuery is doing here isn't going to work no matter what your controller does. jQuery doesn't "traverse" the parameter map below the first level, so the example in the question is likely generating this post data:

address=[object]&geoLocation=[object]

The other, working example does not contain any sub-objects, so it is being translated directly, like this:

Building=value&UnitNumber=value&...&MonthsAtAddress=value

The easiest fix is making the parameter map flat, each key prefixed with either 'Address.' or 'GeoLocation.', depending.

Elliot Nelson
A: 

Hi Ash M, I had the same problem and couldn't get anything to work. Also someone raised it as a bug with jquery and they closed it as not a bug.

I have found a few solutions which answer part of the whole question. And the answer includes the following.

1) Client side: we would need to stringyfy all the objects you need to send. This could be a normal object or an array. It works on both.

2) Client side: You send the data as you have in the first post. As you would object by object.

Tip: When you send parameterised objects, jquery encodes the data sent to the server.

Following all are server side implementations 1) Deserializer class: which will take the input string and put it back in to object/list<>/IList<> what ever you have defined as datatype of the parameter of the controller function. You would need to implement ActionFilterAttribute for the above.

2) Finally add an attribute to controller function, so that it uses the deserialiser class to get the parameters.

As this is quite a lot of code let me know if you need details or have you solved the problem.

Deepak Chawla

+1  A: 

Thank you everyone for your input on this issue.

At this stage, we have departed from using jquery to post complex types to controllers. Instead we use the ms ajax framework to do that. ms ajax post nicely binds the complex types automatically out of the box.

So our solution now uses a mix of jquery and ms ajax framework.

Ash

Ash M
can you post some sample code or an article reference so we can follow your footsteps? I'm having a similar or possibly the same problem, but your answer isn't near as helpful as I now need to go figure out more specifically what parts of the ms ajax framework to start from in trying to move forward.
Maslow
+1 for further explanation.
Drew Noakes