Post Complex JavaScript Objects to ASP.NET MVC Controllers
http://www.nickriggs.com/posts/post-complex-javascript-objects-to-asp-net-mvc-controllers/
Post Complex JavaScript Objects to ASP.NET MVC Controllers
Posted in ASP.NET’JavaScript August 21, 2009
Use the plug-in postify.js to handle posting complex JavaScript objects to ASP.NET MVC controllers using the default model binder
There is a lot on conversation going on about binding complex JavaScript objects to ASP.NET MVC actions. Complex objects are objects that have sub objects and/or arrays.
Let’s assume the following complex model:
I have a Person object with some properties, an array of phone numbers and an Address object. I would like to pass a JavaScript representation of this object to our Controller’s Create action:
1
2
3
4
5
6
7
8
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Person person)
{
//Code to add the person goes here
//return the view
return View();
}
On the client, the JavaScript representation of a Person would be:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
var myPerson = {
FirstName: "Nick",
LastName: "Riggs",
Age: 29,
Address: {
Street: "2780 Somewhere Far",
City: "Birmingham",
State: "AL"
},
PhoneNumbers: [
"205-555-5634",
"205-555-2294",
"205-555-7681"
]
};
One way to send this object to our Controller is to “stringify” the object into a JSON string using a plugin like toJSON. However, this requires us to change the Action to accept a string instead of a typed parameter, and then deserialize the string using the JavaScriptSerializer. I can get around this by automating the deserialization with a custom ActionFilterAttribute or ModelBinder. But, what if I want to use the built-in DefaultModelBinder functionality?
The default model binding in ASP.NET MVC works based on form post data. For example, if I were going to post a simple version of Person and have ASP.NET MVC map it to our action’s person parameter, I could post:
1
2
3
person.FirstName: Nick
person.LastName: Riggs
person.Age: 29
ASP.NET MVC does a good job of recognizing this post data as being a Person and mapping it as such. On top of that, it has its own simple yet powerful syntax for representing more complex objects, such as this:
1
2
3
4
5
6
7
8
9
person.FirstName: Nick
person.LastName: Riggs
person.Age: 29
person.PhoneNumbers[0]: 205-555-5634
person.PhoneNumbers[1]: 205-555-5634
person.PhoneNumbers[2]: 205-555-5634
person.Address.Street: 2780 Somewhere Far
person.Address.City: Birmingham
person.Address.State: AL
So, instead of stringifying my JavaScript objects, I will postify them! (I made the word postify™ up, it’s mine now). My custom postify plug-in will do the work. Here is the source code:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
$.postify = function(value) {
var result = {};
var buildResult = function(object, prefix) {
for (var key in object) {
var postKey = isFinite(key)
? (prefix != "" ? prefix : "") + "[" + key + "]"
: (prefix != "" ? prefix + "." : "") + key;
switch (typeof (object[key])) {
case "number": case "string": case "boolean":
result[postKey] = object[key];
break;
case "object":
if (object[key].toUTCString)
result[postKey] = object[key].toUTCString().replace("UTC", "GMT");
else {
buildResult(object[key], postKey != "" ? postKey : key);
}
}
}
};
buildResult(value, "");
return result;
};
This is the first cut of the plug-in, and I’m sure it’s missing something – I’ll update the source code as I make updates. That said, the plug-in greatly simplifies posting complex objects to ASP.NET MVC controllers. Here is a sample in jQuery that posts myPerson:
1
2
3
4
5
$.ajax({
type: "POST",
url: "/People/Create",
data: $.postify(myPerson)
});
That’s it! The plugin will handle formatting the data in an ASP.NET MVC post-friendly manner. On the server side, the parameter inflates nicely using the default model binder:
If you need to post to an action that takes multiple parameters, the complex object must be prefixed with the name of the parameter – in our case, Person. To include another parameter, use this syntax:
1
2
3
4
5
6
7
8
$.ajax({
type: "POST",
url: "/JSON/DoSomething",
data: $.postify({
person: myPerson,
otherParam: true
})
});


浙公网安备 33010602011771号