Difference Between $.getJSON() and $.ajax() in jQuery - asp.net-mvc

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.

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: JSON Hijacking and How ASP.NET AJAX 1.0 Avoids these Attacks
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);
}
});

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

Replace
data: { patientID: "1" },
with
data: "{ 'patientID': '1' }",
Further reading: 3 mistakes to avoid when using jQuery with ASP.NET

There is lots of confusion in some of the function of jquery like $.ajax, $.get, $.post, $.getScript, $.getJSON that what is the difference among them which is the best, which is the fast, which to use and when so below is the description of them to make them clear and to get rid of this type of confusions.
$.getJSON() function is a shorthand Ajax function (internally use $.get() with data type script), which is equivalent to below expression, Uses some limited criteria like Request type is GET and data Type is json.
Read More .. jquery-post-vs-get-vs-ajax

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

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.

with $.getJSON()) there is no any error callback only you can track succeed callback and there no standard setting supported like beforeSend, statusCode, mimeType etc, if you want it use $.ajax().

Related

ASP.NET MVC - access parameters NOT posted via form

Current Scenario
I am using MVC 4, .net 4.5 on vs2012. I have an action which accepts a custom type. This custom type(model) is tightly bound to a view. I am making a POST via AJAX using JSON. Post will only post the relevant data and no form. Its content type is "application/json; charset=UTF-8". I am getting a nicely populated(read valid) model in my action.
The issue
Now I need to add a custom filter but I am unable to access the data via Request, Request.Form, Request.Param? I have been looking in System.Web.HttpContext.Current. If data is getting populated in my model, then it has to be somewhere in the request itself. I guess I am missing the finer print.
The javascript for posting data is somewhat like
$("#postData").click(function (event) {
var savedObject = getJson(savedObject, parentContext);
$.ajax({
url: '/controller/action',
contentType: 'application/json',
dataType: 'json',
data: savedObject,
type: "POST",
success: successCallBack,
error: errorCallBack
});
});
I see your stated wish of sending JSON data only. If you really need to stick to this, you can access the raw parameters via Request.InputStream.
Controller:
var input = new StreamReader(Request.InputStream).ReadToEnd();
This will get you a URL encoded string that you can manually parse.
Really, I would recommend Shahrooz's answer as the correct way to get where you want to go.
If the controller's Request.Form is not populating for your Ajax post, it is likely because you are manually serializing and sending the data to the controller with a contentType of application/json (a common scenario).
Here is an jQuery.ajax example that will NOT populate Request.Form on the controller.
// JSON serialized form data.
var data = {"id" : "1234", "name" : "Dave"};
$.ajax({
type: "POST",
url: serviceUrl,
contentType: "application/json",
dataType: "json",
data: JSON.stringify(data || {}),
success: function () { }
});
Changing the contentType will cause the controller to process the post like a form submission.
// Form encoded data.
var data = {"id" : "1234", "name" : "Dave"};
data = $.param(data);
$.ajax({
type: "POST",
url: serviceUrl,
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
dataType: "json",
data: data,
success: function () { }
});
You can also leave contentType undefined as application/x-www-form-urlencoded; charset=UTF-8 it is the jQuery default.
I would note that I only used $.ajax to better illustrate what is going on. You could also use $.post, though you will still need to send form encoded data
I dont know what is your code but .If you remove contentType: "application/json; charset=utf-8" from your call to jQuery.ajax the default content type (form-urlencoded) will be used and the json data you have specified as your data parameter (data: { i: i, s: s, b: b }) will be mapped correctly to your action parameters....so unless you really want to send json data just remove the contentType and you will be fine.....look at this

AntiForgery and JSON incompatible?

I have been successfully using the AntiForgery option with Ajax in Orchard Modules for a while. Recently, I have been wanting to change from using the default ContentType = 'application/x-www-form-urlencoded; charset=UTF-8' to a JSON payload (ContentType='application/JSON').
As soon as I do this I get an exception thrown by ASP.NET 'A required anti-forgery token was not supplied or was invalid.'. OK, but how do I go about adding the __RequestVerificationToken while preserving JSON payload?
For reference, here is the code I'm using:
var config = {
url: url,
type: "POST",
data: data ,
dataType: "json",
contentType: "application/json; charset=utf-8"
};
$.ajax(config);
Controller (blows up with 'A required anti-forgery token was not supplied or was invalid.' before it gets here):
[HttpPost]
public ActionResult Update(ShoppingCartItemVM[] items)
{
// do stuff
}
Is this a limitation of the Orchard AntiForgery wrapper or of the MVC AntiForgery functionality? Or am I being stupid (again)?
Giscard is correct. I'll dig a bit deeper.
Note: Only the "post" results in orchard controller require the anti forgery token. So there is less of a requirement to remember that where using a "Get" in a request for json.
Often you will want to send more data than just the request token. In that case the 'data' object you send with your request must contain that __RequestVerificationToken value. In that case jQuery is useful for example:
var defaultPostValues = { __RequestVerificationToken:'#Html.AntiForgeryTokenValueOrchard()', id: 1, ..etc.. };
var myValues = { answers: [1,5,5,10] };
var data = $.extend({}, defaultPostValues, myValues);
var config = {
url: url,
type: "POST",
data: data ,
dataType: "json",
contentType: "application/json; charset=utf-8"
};
$.ajax(config);
The anti-forgery token can also be turned off per module definition (if I remember correctly?).
Module.txt
Name: Polls
AntiForgery: false
Author: Matt
... removed for brevity
Features:
Polls
... etc
However I would recommend using the antiforgery if your calls are within Orchard's modules, and disabling if and only if your data is needed else where by external requests. But I would recommend WebAPI within Orchard for that case but that creates a whole new story and probably likely moves far out of scope.
Maybe try this:
​data = {color: 'red', weight:'20lbs'};
// do some more work...
// Append the anti-forgery token to the POST values:
data['__RequestVerificationToken'] = '#Html.AntiForgeryTokenValueOrchard()';
// Make the .ajax() call:
var config = {
url: url,
type: "POST",
data: data ,
dataType: "json",
contentType: "application/json; charset=utf-8"
};
$.ajax(config);
If you are forming the json somewhere other than a razor view, you can do the #Html.AntiForgeryTokenValueOrchard() inside a razor view and pass it to a javascript object or variable so you can add it to the json via javascript.
EDIT: In addition to the method Matthew posted, you can also append the anti-forgery token to the POST values right before you make the AJAX call without using .extend(). Example: http://jsfiddle.net/JC66L/.

.ajax() appends 'data' key values to URL even in POST mode

This is my code for the .ajax() call:
$.ajax({
type: "POST",
url: "http://ws.geonames.org/searchJSON",
dataType: "jsonp",
data: {
featureClass: "P",
style: "full",
maxRows: 12,
name_startsWith: request.term
}
In addition to using type:"POST" as above, I also tried using $.ajaxSetup({type: "post"}); above this code block.
In both cases, the values in the data key are being appended to the URL. I want a clean URL with no parameters. This code is actually a part of an autocomplete field, it's wrapped into an anonymous function and given a key source like the main jQueryUI examples.
Note The actual URL is immaterial, I don't know if geonames supports POST requests but that's going to change later, this is just an example.
Simply add your parameters like this :
url: "http://ws.geonames.org/searchJSON/" + param,
If you want to force POST, you can try jQuery.post()
It is not possible to make a POST request with the JSONP datatype.
JSONP works by creating a <script> tag that executes Javascript from a different domain, it is not possible to send a POST request using a <script> tag.
If you specify dataType: "jsonp" and type: "POST", the "jsonp" takes precedent and it gets sent as a "GET" request (the "POST" gets ignored).

ASP.NET MVC and jQuery - Problem with ajax encoding

I'm using this to save some data to DB:
$("#btnSave").click(function () {
$.ajax({
type: 'POST',
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
data: 'description=' + oEditor.GetXHTML(),
url: '/SuperAdmin/ReceiveData/',
success: function () {
alert('news saved');
}
});
});
"oEditor.GetXHTML" is taken from FCKEditor.
And, to receive this data I have a ASP.NET MVC method (ActionResult):
public void ReceiveData(string description)
{
}
The point is: when I send, for example, this sentence include the "JavaScript Integration Module" scripts, the ReceiveData method only gets until include the ... what comes after that doesn't come.
Debugging my jQuery function above, I saw that the sentence that I'm trying to pass to the method has HTML encoding with &, amp; and so on. And the double quotes of the ..."JavaScript Integration Module"... is being interpreted by the ReceiveData method as a parameter, because the double quotes have the '&' in it encoding.
So, how can I transform this '& quote' to " before send to the MVC method? Or is there a way to make this method recognize this '& quote' as a character and not a parameter?
Thanks!!!
Use escape(oEditor.GetXHTML()).

JSON parameters auto. convert to lowercase when ajax request made to MVC action method?

Would anybody know why my parameter is being "converted" to lowercase when it hits my ASP.NET MVC controller action?
I can only assume it is being converted as looking at data value just prior to the ajax request it is in correct casing, but then when debugging my action method within .NET during the ajax request and checking the incoming parameter, it has been converted to lowercase?
This is causing dramas for me as I need to keep the case entered by the user.
Code below, example data being sent is: 'SimpleDATATest1'
$.ajax({
type: "GET",
url: "/configuration/module-message-types/GetTranslation",
data: "messageToTranslate=" + messageToTranslate,
dataType: "json",
success: function(result) {
// Insert the returned HTML into the <div>.
$('#TranslationResponse').html(result.message).fadeIn('fast');
$("#" + ajaxLoadImgId).hide();
},
error: function(req, status, error) {
$('#TranslationResponse').text('Could not load example translation message, please try reloading the page.');
$("#" + ajaxLoadImgId).hide();
}
});
And MVC Action method signature is:
[AcceptVerbs(HttpVerbs.Get)]
public JsonResult GetTranslation(string messageToTranslate)
However, when checking the value of 'messageToTranslate' it is returning as: 'simpledatatest1'.
How can I stop whatever forces at work from changing this?
Nevermind... I found this that I implemented was the culprit:
http://www.coderjournal.com/2008/03/force-mvc-route-url-lowercase/

Resources