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. Controllers using the default model Binder
There is a lot on conversation going on about the binding complex JavaScript objects to ASP. Complex objects is objects that has sub objects and/or arrays.
Let ' s assume the following complex model:
I have a person object with some properties, an array of phones 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-to-send this object to our Controller was 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 S Tring 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 the person and has ASP. NET MVC map it to our action ' s Perso n 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 had 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'll postify them! (I made the word postify? Up, it's mine now). My Custom Postify Plug-in would 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
21st
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's said, the plug-in greatly simplifies posting complex objects to ASP. NET MVC controllers. Here's 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 would handle formatting the data in an ASP post-friendly manner. On the server side, the parameter inflates nicely using the default model binder:
If you need to post to a action that takes multiple parameters, the complex object must is prefixed with the name of the Parameter–in, 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
})
});
Post Complex JavaScript Objects to ASP. Controllers