Not all JSON posts are created equal

by Anthony 16. November 2013 07:22

For a little while I was confused on how to perform a JSON post to MVC and have the objects model automatically resolve.  Should I use JSON.Stringify or should I just post the JSON directly?  It turns out the answer is YES with caveats?  What?!?!?  Let me explain.  Lets say you are posting a a simple list of parameters to a method with a signature like this:

public ActionResult _GetBooksbyGenre(string genre, int count, string requestedBy)

This action can be called by performing a simple JSON post like this:

 $.ajax({
        url: "_GetBooksbyGenre",
        type: "post",
        data: { genre: "Horror", count: 10, requestedBy: "me" },
        success: function(data) {
        model.currentGenre(data);
    }
});

No fuss no muss, a simple call with no JSON stringify.  Now lets say you have a complex nesting of JSON Objects like Genre>Book>Author

 

Here is a JSON Representation of that object:

{
	Name: "Horror",
	Books:
	[
		{
			Title: "The Call of Cthulhu",
			WritenBy: {
				FirstName: "H.P.",
				LastName: "Lovecraft"
			}
		},
		{ Title: "The Fall of the House of Usher" }, {
			WritenBy: {
				FirstName: "Edgar Allan",
				LastName: "Poe"
			}
		}]
};

If we post this to a action with the following signature :

public ActionResult _GetBooksbyGenre(string genre, int count, string requestedBy)

With a similar ajax method:

$.ajax({
	url: "_AddBooksbyGenre",
	type: "post",
	data: horrorGenre,
	success: function(data) {
		model.currentGenre(data);
	}
});

It posts just fine and we get the name of the Genre But all of the nested objects are null?  This occurs because the MVC object serializer does not understand the nested representation since it is not JSON it is POST data.  The difference is the standard post data is not JSON, the $.ajax method is interpreting the json and submitting it as form data.  The post data looks like this:

Name=Horror&Books%5B0%5D%5BTitle%5D=The+Call+of+Cthulhu&Books%5B0%5D%5BWritenBy%5D%
5BFirstName%5D=H.P.&Books%5B0%5D%5BWritenBy%5D%5BLastName%5D=Lovecraft&Books%5B1%5D%
5BTitle%5D=The+Fall+of+the+House+of+Usher&Books%5B2%5D%5BWritenBy%5D%5BFirstName%5D
=Edgar+Allan&Books%5B2%5D%5BWritenBy%5D%5BLastName%5D=Poe

That is not JSON, and it is not in a format MVC understands.

If we make minor changes to the ajax call:

$.ajax({
	url: "_AddBooksbyGenre",
	type: "post",
        contentType: "application/json; charset=utf-8",
	data:  JSON.stringify(horrorGenre),
	success: function(data) {
		model.currentGenre(data);
	}
});

 

The key to the changes are the highlighted items.  When this is posted you get the following in the request stream:

{"Name":"Horror","Books":[{"Title":"The Call of Cthulhu","WritenBy":{"FirstName":"H.P.","LastName":"Lovecraft"}},{"Title":"The Fall of the House of Usher"},{"WritenBy":{"FirstName":"Edgar Allan","LastName":"Poe"}}]}

Now that is JSON.  So the moral of the story is, if you are just posting flat params you can use JSON.stringify but it doesn't really matter.  If you are posting complex JSON you need to use JSON.stringify with the "application/json" content type.  I hope that clears up the confusion for some people.  I know, for a while, I just thought I was going crazy when it worked sometimes but not other but when I finally understood what was going on it made complete sense.  

 

 

Tags: , , ,

AJAX | jquery | JSON | MVC5

blog comments powered by Disqus

Calendar

<<  October 2014  >>
MoTuWeThFrSaSu
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

View posts in large calendar

Page List

RecentComments

None