views:

1540

answers:

5

I am calling an ASP.NET MVC action

public JsonResult GetPatient(string patientID)
{
...

from JavaScript using jQuery. The following call works

$.getJSON(
'/Services/GetPatient',
{ patientID: "1" },
function(jsonData) {
  alert(jsonData);
});

whereas this one does not.

$.ajax({
  type: 'POST',
  url: '/Services/GetPatient',
  data: { patientID: "1" },
  contentType: 'application/json; charset=utf-8',
  dataType: 'json',
  success: function(jsonData) {
    alert(jsonData);
  },
  error: function() {
    alert('Error loading PatientID=' + id);
  }
});

Both reach the action method, but the patientID value is null w/ the $.ajax call. I'd like to use the $.ajax call for some of the advanced callbacks.

Any thoughts appreciated.

A: 

The only difference I see is that getJSON performs a GET request instead of a POST.

kgiannakakis
Tried changing the type to GET, and the data change in rpcutts answer, but the value is still null in the action method.
ChrisP
+6  A: 

Replace

data: { patientID: "1" },

with

data: "{ 'patientID': '1' }",

Further reading: 3 mistakes to avoid when using jQuery with ASP.NET

rpcutts
Wouldn't that have to be something like data: '{ patientID: "1" }', to avoid nested double quotes?
Nosredna
Indeed it would
rpcutts
No go. The value is null in the action method with this change.
ChrisP
try deleting the contentType setting you have specified
redsquare
I believe the method argument must be the same as the JSON key. i.e. personID.Other than that I'm no sure of the problem because I've used this syntax several times and it works no problems.
rpcutts
Having to do this manually is horrible, so I recommend using http://code.google.com/p/jquery-json/ - this lets you wrap your real JSON object with the $.compactJSON() method, which will automatically send the object as a string, reducing headaches all round.
tags2k
I have the jquery-json plugin and tried it along w/ removing the contentType. The patientID value in the action method is still null. From the debugger, the value of "data" is: "{"patientID":"1"}"I tried experimenting w/ the options further, but still no success.For what it's worth I had another questionhttp://stackoverflow.com/questions/1039105/problem-passing-json-data-using-jquery-ajax-to-net-mvc-action-w-custom-bindwhere I had a similar problem, but was using the BindingModel on the action method.
ChrisP
Does anyone know the exact translation of $.getJSON() to $.ajax()?
ChrisP
A: 

.getJson is simply a wrapper around .ajax but it provides a simpler method signature as some of the settings are defaulted e.g dataType to json, type to get etc

N.B .load, .get and .post are also simple wrappers around the .ajax method.

redsquare
A: 
contentType: 'application/json; charset=utf-8'

Is not good. At least it doesnt work for me. The other syntax is ok. The parameter you supply is in the right format.

Malcolm Frexner
+5  A: 

Content-type

You don't need to specify that content-type on calls to MVC controller actions. The special "application/json; charset=utf-8" content-type is only necessary when calling ASP.NET AJAX "ScriptServices" and page methods. jQuery's default contentType of "application/x-www-form-urlencoded" is appropriate for requesting an MVC controller action.

More about that content-type here: http://weblogs.asp.net/scottgu/archive/2007/04/04/json-hijacking-and-how-asp-net-ajax-1-0-mitigates-these-attacks.aspx

Data

The data is correct as you have it. By passing jQuery a JSON object, as you have, it will be serialized as patientID=1 in the POST data. This standard form is how MVC expects the parameters.

You only have to enclose the parameters in quotes like "{ 'patientID' : 1 }" when you're using ASP.NET AJAX services. They expect a single string representing a JSON object to be parsed out, rather than the individual variables in the POST data.

JSON

It's not a problem in this specific case, but it's a good idea to get in the habit of quoting any string keys or values in your JSON object. If you inadvertently use a JavaScript reserved keyword as a key or value in the object, without quoting it, you'll run into a confusing-to-debug problem.

Conversely, you don't have to quote numeric or boolean values. It's always safe to use them directly in the object.

So, assuming you do want to POST instead of GET, your $.ajax() call might look like this:

$.ajax({
  type: 'POST',
  url: '/Services/GetPatient',
  data: { 'patientID' : 1 },
  dataType: 'json',
  success: function(jsonData) {
    alert(jsonData);
  },
  error: function() {
    alert('Error loading PatientID=' + id);
  }
});
Dave Ward
Thanks. This solved the problem. I used $.compactJSON() to format the JS object into JSON for the data option.
ChrisP
I've never used MVC but this is good to know. Thanks.
rpcutts
As $.compactJSON is not available in jQuery anymore, I used $.toJSON from this plugin here: http://code.google.com/p/jquery-json/
J. Bruni