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:
[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:
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:
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:
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:
$.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:
$.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:
$.ajax({
type: "POST",
url: "/JSON/DoSomething",
data: $.postify({
person: myPerson,
otherParam: true
})
});



[...] Nick Riggs, Web Developer – Post Complex JavaScript Objects to ASP.NET MVC Controllers nickriggs.com/index.php/posts/post-complex-javascript-objects-to-asp-net-mvc-controllers – view page – cached Nick Riggs, Web Developer » Post Complex JavaScript Objects to ASP.NET MVC Controllers Comments Feed Nick Riggs, Web Developer Clean Up the setTimeout Function Simple AJAX Polling Plugin for jQuery — From the page [...]
August 21, 2009 9:35 pm
[...] to VotePost Complex JavaScript Objects to ASP.NET MVC Controllers (8/21/2009)Friday, August 21, 2009 from Nick RiggsThere is a lot on conversation going on about binding complex [...]
August 23, 2009 10:50 pm
Post Complex JavaScript Objects to ASP.NET MVC Controllers – Nick Riggs…
Thank you for submitting this cool story – Trackback from DotNetShoutout…
August 24, 2009 9:09 am
Nick Riggs, Web Developer – Post Complex JavaScript Objects to ASP.NET MVC Controllers…
Thank you for submitting this cool story – Trackback from progg.ru…
August 25, 2009 11:36 am
Nick Riggs, Web Developer – Post Complex JavaScript Objects to ASP.NET MVC Controllers…
9efish.感谢你的文章 – Trackback from 9eFish…
August 25, 2009 7:38 pm
You should use json2.js for this instead of rolling a custom function. Its JSON.stringify() does the same thing.
The bonus when using json2.js is that browser-native JSON functionality in ECMAScript 3.1 mimics Crockford’s API. So, if your code is using json2.js’ JSON.stringify/parse, it will automatically use the faster native routines when the user’s running Firefox 3.5, IE 8, or the newest builds of Chrome/Safari.
August 26, 2009 11:45 am
Definitely a cool alternative approach compared to creating your own ActionFilterAttribute (I wouldn’t even consider the stringify option
)
I ask this not be be contrarian, but just a question…what does this method buy you that an ActionFilterAttribute does not? It’d be interesting to understand the performance implications. It seems the code to do this on the client vs. deserializing JSON on the server is rather similar.
August 26, 2009 11:53 am
@Dave: While I like json2.js, this post was meant to address “postifing” a JavaScript object so that it works within ASP.NET MVC’s default model binding. Which is something json2.js doesn’t address.
August 26, 2009 12:24 pm
@SanjayU: All this method really buys you is integration with MVC’s default model binding behavior. It’s an custom ActionFilter you don’t have to maintain.
August 26, 2009 12:25 pm
Nick, you’re absolutely right. I’m so used to POSTing JSON strings to ASMX/WCF services, I misunderstood what you were trying to do. Sorry about that.
Out of curiosity, have you had trouble when supplying the JSON object directly to jQuery in the data parameter? If the data parameter is an object, jQuery will automatically construct and POST the appropriate serialization of the object. So far, I haven’t run into a DTO object that jQuery’s auto-serialization didn’t properly hand off to MVC’s model binder.
August 26, 2009 8:18 pm
Hey Nick, this is really good stuff. I’d like to use it in some of my own projects. Would you please consider attaching a license to this code to make this easier?
September 18, 2009 10:18 am
Wonderfull, You saved me from a LOT of trouble. Thanks a lot!!!!!
February 27, 2010 7:24 pm
[...] the JavaScript objects into a post that MVC can bind to the controller, we are going to use the postify.js plugin I wrote back in August. That will make handling the saveButton’s click straight [...]
May 26, 2010 6:36 am
good job, i was looking for a thing like this.
thanks a lot.
July 23, 2010 5:23 am
You helped me work though a problem, but I favor a simpler solution than a new plug in –
I add a string “NameField” to my ViewModel and then adjust the name of my Serializable object to that name:
Model.NameField = “Family.Children[" + i.ToString() + "]“;
easy peasy!
July 26, 2010 10:40 am