Post Complex JavaScript Objects to ASP.NET MVC Controllers

时间:2021-12-31 11:35:16

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.NETJavaScript 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:

Post Complex JavaScript Objects to ASP.NET MVC Controllers

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

})

});