Reputation: 67175
I have some code that uses jQuery's $.ajax()
.
I found that I had to pass my data through JSON.stringify()
.
$.ajax({
url: '/Resource/ReportError',
type: 'POST',
data: JSON.stringify({
ResourceId: popup.data('id'),
Reason: reason,
Description: $('#report-error-description').val(),
Email: $('#report-error-email').val()
}),
contentType: 'application/json; charset=utf-8',
success: function (data) {
// ...
},
error: function () {
// ...
}
});
So far, so good. But now I'm using it to get some data, passing in only an ID. So I figured I should be using GET instead.
$.ajax({
url: '/Resource/GetInitialReviewData',
type: 'GET',
data: JSON.stringify({ resourceId: resourceId }),
contentType: 'application/json; charset=utf-8',
success: function (data) {
// ...
},
error: function () {
// ...
}
});
But this fails with an error about the resourceId
being null
on the server.
If I remove the call to JSON.stringify()
, then it works!
data: { resourceId: resourceId },
Can anyone explain this in a way that's easy to understand? Why do I need JSON.stringify
for POST but not for GET.
Upvotes: 1
Views: 92
Reputation:
You do not need to use JSON.stringify()
for a POST, although you can (but it is generally unnecessary unless your manually generating complex types or arrays which do not match the c# dot and indexer notation). The default contentType
for the $.ajax()
method is 'application/x-www-form-urlencoded; charset=UTF-8'
which is essentially like a giant query string of the successful forms controls name/value pairs. To see what it would look like, your can use console.log($('form').serialize());
.
If you omit the contentType
then you can use the object without stringifying it.
$.ajax({
url: '/Resource/ReportError',
type: 'POST',
data: {
ResourceId: popup.data('id'),
Reason: reason,
Description: $('#report-error-description').val(),
Email: $('#report-error-email').val()
},
success: function (data) {
The DefaultModelBinder
will then use the FormValueProvider
to read and bind the data to your method parameters.
When you use JSON.stringify()
it converts your object to JSON-formatted text - a giant string containing the name/value pairs (notice the quotes around the resulting value) and you could receive this by having a single string
parameter in your method and deserializing it yourself. By adding the contentType: 'application/json; charset=utf-8'
the DefaultModelBinder
will now use the JsonValueProviderFactory
to read the string, deserialize it (using the JavaScriptSerializer
) and bind the data to your method parameters.
In the case of a GET, there is no body, and the contentType
option is not applicable (it will be ignored) as the DefaultModelBinder
will only read the values from the query string (or route values). As noted in maddockst's answer, by using JSON.stringify()
in your $.ajax()
GET call, your generating a url of
.../Resource/GetInitialReviewData{"resourceId":"someValue"}
instead of the required
.../Resource/GetInitialReviewData?resourceId=someValue
Upvotes: 1
Reputation: 1385
The data
attribute when used in conjunction with type: 'GET'
will convert the value specified into a query string and append it to the URL. So if you called the URL http://www.test.com
with data {name: 'Tom'}
, you'd end up with the following URL:
http://www.test.com?name=Tom
If you pass a string, that string will be appended to the URL so the resulting URL when calling JSON.stringify
would be:
http://www.test.com{"name":"tom"}
When you use data
with type: 'POST'
, data
is sent in the body of the request. The body of the request needs to be a string, the reason for the call to JSON.stringify
.
Upvotes: 3