I have a HTML-page with some JS-code in it, which is loaded from the Android WebView. This JavaScript uses the jQuery-post-function to call the HandleAndroidJSON.aspx-site with data, and return a callback-function with a data-, status- (and jqXhr-) parameter:
function syncWithServer() {
var dataToSend = Android.getDataToSend();
$.post("HandleAndroidJSON.aspx", { data: dataToSend }, callbackDataFromServer);
}
function callbackDataFromServer(data, status) {
Android.setDataFromServer(data, status);
}
The "Android"-variable is a JavaScriptInterfacecreated in Android that makes it possible to call Android-methods from JS.
In my HandleAndroidJSON.aspx.cs-file I write a response depending on the data I receive from Android:
public partial class HandleAndroidJSON : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Response.Clear();
Response.ContentType = "text/plain";
// Read request parameter and deserialize JSON data.
string jsonDataFromClient = Request.Params["data"];
// ... Do stuff with the data ...
if (error != null)
{
//This goes into the data-parameter of the callbackFunction
Response.Write(error);
//Response.Status = "403 Error"; //This seems to only be HTTP-status responses,
//not the one used as parameter in the callback-function
}
else
{
//This does too
Response.Write(jsonDataToSend);
}
Response.End();
}
}
The Response.Write()-method returns in the the data-parameter in the callback-function as intended, but I cannot seem to set the status-parameter - it always returns the same string: "success" and doesn't change if I set the Response.Status-property.
So the question is simply, how do I set the status-parameter of the callbackDataFromServer-function (that is called from the jQuery-post-function) from the aspx.cs-code?
EDIT: I'm not talking about status-codes for HTTP. Setting the StatusDescription-, StatusCode- and the Status- properties, of the Response-property, doesn't change the status-parameter of the callback-function.
EDIT2: I don't think handling the status-parameter in the JavaScript-code solves the problem because I would have to validate the data in Android again anyway (since JavaScript-injection would be possible to do to avoid the error handling). I would like to pass it on to the Android-method via the status-parameter, in the callbackDataFromServer-function, as the current code indicates.
EDIT3: Even though I can't seem to find a straight answer to whether it's possible to set the status-parameter from the aspx-code, it seems that the only thing you can change beside the data-parameter is the jqXhr.status property, which can be set be the Response.StatusCode property in the aspx-site.
There's also the jqXhr.statusText property which holds a string, but it seems to be the default text, based on the statuscode, and not the Response.StatusDescription (setting the statusCode to 200 and the statusDescription to "success" returned as "OK", which is default for the statusCode 200).
This is the topic I was reading: Get the jqXhr.responseText on a jQuery getJSON request using JSONP
EDIT4: I now figured out that setting the StatusCode to a value, that implies something went wrong, will result in no data being sent, even though the Response.Write()-method has been called, which defeats the purpose I'm trying to achieve.
The proper question would then be: How can I properly pass on the error text (from ASP.NET, through jQuery) if something went wrong, instead of the data? And how can I ensure that the data I'm transfering is either an error or JSONData?
I figure the simple way is just to check if the data starts with a "{" or "[" but I feel like it's a bit of a hack.
inorder to get the status code you can use the status property of the third argument of success call back jqXHR, here is the fiddle http://jsfiddle.net/prD5c/
so your function looks like
function callbackDataFromServer(data, status,jqXhr) {
console.log(jqXhr.status);
Android.setDataFromServer(data, status);
}
you can use the statusCode like
$.ajax({
statusCode: {
202: function() {
alert("success");
},
403:function(){
alert(error);
}
}
});
as you are using $.post you can define this in the ajaxSetup like
$.ajaxSetup({
statusCode: {
202: function() {
alert("success");
},
403:function(){
alert(error);
}
}
});
http://api.jquery.com/jQuery.ajax/
Related
This is somewhat related to other similar questions:
jquery ajax returns error but is success
jquery .ajax always returns error - data being added to database
Jquery Ajax Call always returns error
However, my problem doesn't seem to be the data:"json" issue.
My code is a simple POST request to a server and, for testing purposes, it is always returning 200 OK.
If I run the jquery code directly after document ready, it works just fine and calls the success function.
But if I attach it to a on("click") button event, it always return the error function. Nothing has changed on the server and I can see on the console that the right resource is being called.
My main code is located on a js file:
var myObj = function(){
var url = "myURL";
this.functionINeed = function(data, cb) {
ajaxPost(url, data, cb);
};
function ajaxPost(url, data, cb){
$.ajax({
"url" : url,
"contentType" : "application/json; charset=UTF-8",
"data" : data,
"type" : "POST",
"success" : function(serverData, textStatus, jqXHR){
cb(null, {
"serverData" : serverData,
"textStatus" : textStatus,
"jqXHR" : jqXHR
});
},
"error": function (jqXHR, textStatus, errorThrown) {
cb({
"jqXHR" : jqXHR,
"textStatus" : textStatus,
"errorThrown" : errorThrown
});
}
});
};
}
//I initialize the object directly on the js file
MyObj = new myObj();
Then, the first scenario: call the function directly on page load:
var data = {
"action" : "someaction",
"code" : "somecode"
}
MyObj.functionINeed(JSON.stringify(data), function(err, response){
if(err){
alert(err.errorThrown);
return err;
}else{
alert(response.textStatus);
return response;
}
});
This works fine: the server is called, the content is returned and JQuery calls the success function.
However, if I attach this code to a button event, it always returns the error function. I am monitoring the server and I am sure it is returning the correct data.
$("#myButton").on("click", function(){
var data = {
"action" : "someaction",
"code" : "somecode"
}
MyObj.functionINeed(JSON.stringify(data), function(err, response){
if(err){
alert(err.errorThrown);
return err;
}else{
alert(response.textStatus);
return response;
}
});
});
For the records, my server is Node.js with Sails.js, but this doesn't seem to matter.
The many similar questions are somehow related to the data:"json" issue, but I've removed it and the most weird is that the behavior only happens when you attach the code to an event.
I would suspect there is some kind of scoping issue involved (object being instantiated on the file, for ex.), but the server is being correctly called every time. I just can't understand why JQuery interprets all responses as errors (and empty server data).
What am I doing wrong here?
After an insane afternoon trying all kinds of combinations, a light bulb went off and I figured out the problem is that my button html was inside a form.
<form>
<button></button>
</form>
After changing to a regular div, it worked.
<div>
<button></button>
</div>
Which is -- to me -- absolutely insane. It seems JQuery captures more information than meets the eye when sending the ajax query, and this was messing the response parsing by expecting some form encoded behavior. Does it mean I cannot have special purpose buttons inside my forms? Since I am using Bootstrap, that's "OK" because I can use the a tags for this (tested and worked). But this seems a JQuery bug (version: 1.11.2)
I am using ckeditor in our project. passing that value in ajax post like
//$form is -> $('form') jquery object
$("#ajaxsubmitbutton").on('click', function () {
CKupdate();
$.ajax({
type: ($form.attr('method').toLowerCase() == 'post' ? 'POST' : 'GET'),
url: ($form.attr('action') == 'undefined' ? window.location : $form.attr('action')),
data: $form.serialize(),
success: function (data) {
// Use local eval, since it will work in this context
callbackFunction(data);
},
error: function () {
var data = "ajaxerror";
callbackFunction(data);
}
});
});
Ckeditor update code :
function CKupdate(){
for ( instance in CKEDITOR.instances )
CKEDITOR.instances[instance].updateElement();
}
$form.serialize having below value :
"Id=0&Title=dfg&ShortText=rer&CultureCode=en-US&StartDate=3%2F12%2F2014&EndDate=3%2F26%2F2014&Text=%3Cp%3Etest3%3C%2Fp%3E%0D%0A"
controller code :
public JsonResult Save(int id, string title, string shortText, string text, DateTime? startDate, DateTime? endDate, string cultureCode)
{
//process some operation
}
it throws some ajax error like " 500 -internal server not found". i don't know what is the real cause for this issue
may be the problem in serializing the form. any help on this.
I suspect that the tags are the issue here-
Assuming Asp.net MVC here you have two options-
Decorate your model property with the [AllowHtml] method (not sure how much of a pain it would be to convert your properties to a model here)
Put the [ValidateInput(false)] tag on your controller method
You may need to add the following tag to system.web in your config as well
<httpRuntime requestValidationMode="2.0"/>
You may also run into issues if your submit isn't a post in which case you'll want to add allowget to your return value.
Not sure if this is your issue without the full error but that is where I'd start. You may want to check the response in fiddler or firebug to see if you can get more information on that exception.
Hope that helps.
I am falling into a silly issue where the server is giving JSON response with XSS safe text added.
The server gives only 2 kinds of response:
HTML page with hidden input field that contains the value I want
JSON String with the value which can be preferably converted to JS
Object.
The problem is, for preventing JavaScript XSS attacks, the JSON response is made like this:
while(1);{
"name": {
"abc": "123",
...
}
}
So this goes to parseerror in jQuery ajax method and therefore in the error callback.
How do I fix this?
Also, I tried putting a hook in the error function and change the JSON data:
error: function(jqXHR) {
removeJSCode (jqXHR.responseText);
}
// ...
function removeJSCode(json) {
.. Code to filter the response
}
But this does not work.
jQuery's $.ajax has dataFilter property in its configuration. Pass it a function and it runs after jQuery receives ajax data, but before jQuery has a chance to touch it.
The function is provided the string response as first argument and data type as second argument. The second argument will depend if you passed dataType in the configuration.
There, you can use .replace('while(1);','') and return the string from the function for jQuery to parse.
$.ajax({
...
dataType : 'json',
dataFilter : function(response,type){
//if not JSON, don't do anything with it
if(type !== 'json') return response;
//otherwise, replace and return
return response.replace('while(1);','');
}
...
});
The following javascript code gives me ">success-<", i.e. empty data. Pasting the url in my browser gives me the expected content.
$.get("http://company.tld/wiki/api.php?action=query&titles=Page%20Title&format=xml&prop=revisions&rvprop=content", function (data, status) {
alert(">" + status + "-" + data + "<");
});
It's a MediaWiki wiki. Here's the MediaWiki API specification: http://www.mediawiki.org/wiki/API:Query
Why am I not getting any data?
You might breach the ajax cross domain policy there.
Is that domain you try to access yours? better said, the one from your script?
From my experience, if you try to access data from a foreign domain, the success handler will fire regardless. But as you describe, with no data at all.
If data is an object you will receive the close results. Try use typeof data in the alert.
UPDATED:
To jAndy: In the documentation of jQuery.ajax we can read following (see http://docs.jquery.com/Ajax_Events):
success (Local Event).
This event is only called if the request was successful (no errors from the server, no errors with the data).
I just tried execute the following code
try {
$.ajax({url:"http://en.wikipedia.org/w/api.php?action=query&titles=jQuery&format=xml&prop=revisions&rvprop=content",
success: function (data, status, x) {
alert ("ok");
},
error: function (data, status, x) {
alert ("not ok");
},
dataType:"xml"});
} catch (e) {
alert ("exception");
};
where I try to use a crossdomain call. In IE I can see "exception" alert. In Chrome and Firefox: "not ok". The function success will NOT be called in case of error.
So the data from server are really an empty string ("") for the url of Tobbe.
To Tobbe: you should add the last parameter "xml" probably.
url = "http://example.com"
new Ajax.Request(url, {
onComplete: function(transport) {
alert(transport.status);
}
});
I'd like that to return a status of 200 if the site is working, or 500 if it is not working, etc.. But that code is returning 0 all the time.
Ultimately, I want to have a setinterval function that regularly pings a website for uptime status.
With JQuery you should get your status with a code similar to what you have, and it will be something like this:
$.ajax({
url: 'some.url.com',
type: 'POST',
complete: function(transport) {
if(transport.status == 200) {
alert('Success');
} else {
alert('Failed');
}
}
});
And if you want to use prototype your code should only add this:
onXYZ:function(transport){
}
In the text above XYZ should be replaced by the http status code you want to catch for the response.
Hope this helps
Ajax libraries don't "return status codes" themselves; that code is the HTTP response code returned in the response from the server. A status code of 200 indicates success; 404 indicates "not found", etc.
It's probable that a response code of 0 means the request wasn't even attempted. Is the request URL under the same domain (subdomain, if applicable) as that which the page is coming from? If not, then you may be running into problems with the same-origin policy, which prevents scripts from creating arbitrary requests.
To work around this, you'll need to proxy the data on the server side; for example using a script/framework handler/whatever which executes the web request and passes the data back down to clients. Call the "local" proxy instead of the remote data source.
Prototype has onXYZ callbacks, for example:
new Ajax.Request(url, {
method: 'get',
on500: function(transport) {
alert("failed!");
},
onSuccess: function(transport) {
alert("success!");
}
});
On thing though, if the website is down (as in, not reachable), it will not return a 500 error, so your approach isn't very good for starters.
I was able to make remote domains work by creating a server side proxy file to pass the status code through. I used the code on this post to create a asp.net page that would just set the status code of the page to the web request status code.
I then used the ajax example that Chermosillo provided like so.
$.ajax({
url: 'URLTestProxy.aspx?url=http://some.url.com',
type: 'POST',
complete: function(transport) {
if(transport.status == 200) {
alert('Success');
} else {
alert('Failed');
}
}
});
This way here you can get around the same origin policy and still get the status code of the remote url.
It may be helpful to know that the transport param in the example is an XMLHttpRequest object. Full details of the methods and properties available from this object can be found here:
http://www.w3.org/TR/XMLHttpRequest/#the-xmlhttprequest-interface
Most notable in the context of this question are the response items:
readonly attribute unsigned short status;
readonly attribute DOMString statusText;
DOMString getResponseHeader(DOMString header);
DOMString getAllResponseHeaders();
readonly attribute DOMString responseText;
readonly attribute Document responseXML;
You should be able to get any arbitrary header with the getResponseHeader() method.
For jQuery you might try:
complete: function(transport, textstatus){
alert(transport.getResponseHeader("Status"))
}
warning: not tested