Reputation: 2532
I'm currently trying to post a JSON object from my view to my controller in an MVC 3 app and I'm expecting the data from the request to bind to the model parameter of my controller action. However, when I inspect the HTTP POST request, it looks like the data is being passed as a query string and I'm unsure why (pretty new to all this).
Here's my POST request:
$.ajax({
type: 'POST',
url: "Test/Add",
data: { Name: name, Age: age },
success: function (data) {
console.log("success");
},
error: function (xhr, data, message) {
console.log(data + ": " + message);
},
dataType: "json"
});
Here's the code from my Controller followed by the code for the model I'm trying to bind to:
[HttpPost]
public ActionResult Add(PersonModel person)
{
System.Threading.Thread.Sleep(1000);
return View();
}
// person model:
public class Person {
public string Name {get;set;}
public int Age {get;set;}
}
This is the request from fiddler - I've highlighted the parts I'm unsure about:
I thought content type would be "application/json" and that the data wouldn't look like a query string - I thought it would look something like this:
{
Name: "James",
Age: 13
}
Ultimately the problem is that if I stick a breakpoint in my controller action I expect to see a populated Person object but it's always null. If I replace the signature to be something like (object name, object age)
then I get values for the parameters (a string array for both - so name is a string array with 1 element which is equal to "James").
Any ideas where I've gone wrong?
Oh and just FYI, I'm not actually 13! Those were the first numbers I mashed.
Thanks!
James
Upvotes: 2
Views: 4068
Reputation: 17540
@David is correct in that you need to set the contentType to 'application/json'. But you also need to send JSON. You are sending an object over. To convert it to JSON use JSON.stringify. I tried sending it over as an object with this contentType setting and received a server error. I actually got it to work correctly without setting the contentType. Even though the request came across as "Name=James&Age=13" MVC was able to convert it into an object. I modified your test to echo back the results as JSON and display them.
Here is the modified Controller
[HttpPost]
public string Add(PersonModel person)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
string result = serializer.Serialize(person);
return result;
}
// person model:
public class PersonModel
{
public string Name { get; set; }
public int Age { get; set; }
}
The modified Javascript and HTML looks like this:
<input id="doAjax" type="button" value="Send Json..."/>
<br />
Results:<br />
<textarea id="results" cols="30" rows="3"></textarea>
<script type="text/javascript">
$( document ).ready( function () {
$( "#doAjax" ).click( sendJson );
} );
function sendJson() {
var name = "James";
var age = "13";
var person = { Name: name, Age: age };
var personJson = JSON.stringify( person );
$.ajax( {
type: 'POST',
url: "Test/Add",
data: personJson,
contentType: 'application/json',
success: function ( data ) {
var jsonStr = JSON.stringify( data );
$( "#results" ).val( jsonStr );
},
error: function ( xhr, data, message ) {
var jsonStr = JSON.stringify( data );
$( "#results" ).val( jsonStr + ": " + message );
},
dataType: "json"
} );
}
Here are the results of some tests:
data = person; contentType = not set; request = "Name=James&Age=13"; response = "{"Name":"James","Age":13}"
data = personJson; contentType = not set; request = "{"Name":"James","Age":"13"}"; response = "{"Name":null,"Age":0}"
data = person; contentType = 'application/json'; request = "Name=James&Age=13"; response = "System.ArgumentException: Invalid JSON primitive: Name"
data = personJson; contentType = 'application/json'; request = "{"Name":"James","Age":"13"}"; response = "{"Name":"James","Age":"13"}"
Note that when the contentType is not set it defaults to 'application/x-www-form-urlencoded'
Upvotes: 2
Reputation: 10753
The dataType
passed to $.ajax
is the expected response type. You need to add the contentType
to specify the payload type.
$.ajax({
type: 'POST',
url: "Test/Add",
data: { Name: name, Age: age },
contentType: 'application/json' //*********
success: function (data) {
console.log("success");
},
error: function (xhr, data, message) {
console.log(data + ": " + message);
},
dataType: "json"
});
Here's the jQuery documentation for .ajax()
that indicates the default contentType is 'application/x-www-form-urlencoded'
Upvotes: 1