14

My ajax code is

$.ajax({
    type: 'GET',
    dataType: "jsonp",
    processData: false,
    crossDomain: true,
    jsonp: false,
    url: "http://someotherdomain.com/service.svc",
    success: function (responseData, textStatus, jqXHR) {
        console.log("in");
    },
    error: function (responseData, textStatus, errorThrown) {
        alert('POST failed.');
    }
});

This is a cross domain ajax request.

I am getting correct response for the request, while checking with firebug i can see that response.

This is the response I am getting in firebug response and while accessing this url through web browser

{"AuthenticateUserResult":"{\"PKPersonId\":1234,\"Salutation\":null,\"FirstName\":\"Miqdad\",\"LastName\":\"Kumar\",\"Designation\":null,\"Profile\":\"\",\"PhotoPath\":\"\/UploadFiles\/\"}"}

But I am getting error

SyntaxError: invalid label

{"AuthenticateUserResult":"{\"PKPersonId\":8970,\"Salutation\

Whether I need to use any other method to get it works. I want to implement this in phonegap+jquery mobile app.

Also, I don't have any access to the web service

If I disable chrome web security it's working fine

Universal Electricity
  • 775
  • 1
  • 12
  • 26
Miqdad Ali
  • 6,129
  • 7
  • 31
  • 50
  • 1
    Is there any reasoning behind using these three options, or did you just stick them in to see if they work: `processData:false,crossDomain:true,jsonp: false,` `processData` isn't needed because #1 you're not sending any data, and #2 it doesn't mean anything for a jsonp request. `crossDomain:true` is almost never needed, the only case where it is is if you want to do a same-origin request while treating it like a cross-origin request. Since you're making a cross-origin request, it's already going to be true by default. `jsonp:false` should never be used without `jsonpCallback:"callback"`. – Kevin B Jun 07 '13 at 17:32
  • no... Thats i have added for testing. This cross domain request that's why I used such codes ;) – Miqdad Ali Jun 07 '13 at 17:34
  • see updated comment, sorry. None of those three options make any sense with the request you're making. – Kevin B Jun 07 '13 at 17:37
  • If anything, you need to be making a CORS request, but that's only going to work if the webservice supports CORS and we can't tell whether or not it does given what's been provided. – Kevin B Jun 07 '13 at 17:38
  • To begin with, remove those three options and try the request again. Do you get to the success? (the error callback can be removed, jsonp requests don't trigger it.) – Kevin B Jun 07 '13 at 17:39
  • I have removed that 3 lines and tested, but I am not getting any response that time. Ajax error method is triggering – Miqdad Ali Jun 07 '13 at 17:41
  • What version of jQuery? and in your error callback, alert the value of the 2nd and 3rd arguments. – Kevin B Jun 07 '13 at 17:42
  • I have tried with `jQuery JavaScript Library v1.9.1` and `jQuery JavaScript Library v1.8.2` – Miqdad Ali Jun 07 '13 at 17:43
  • Something isn't quite adding up then. the error callback shouldn't be triggering if you have `dataType: "jsonp"` – Kevin B Jun 07 '13 at 17:44
  • that case also error method is triggering, but I am getting rseponse for the ajax request – Miqdad Ali Jun 07 '13 at 17:46
  • i think , thats because of this invalid label error – Miqdad Ali Jun 07 '13 at 17:46
  • Well, it's pretty much confirmed at this point that the webservice does not support JSONP, therefore you're only option is to use a script proxy. – Kevin B Jun 07 '13 at 17:48
  • Could please explain it, or please provide any documentation for that – Miqdad Ali Jun 07 '13 at 17:58
  • what server-side language do you use? php? asp? something else? no server-side language? – Kevin B Jun 07 '13 at 18:08
  • i dont know anything about that one, i think its asp, because my api url is ending with `service.svc` – Miqdad Ali Jun 07 '13 at 18:13
  • not the api, the server that's outputting your html. – Kevin B Jun 07 '13 at 18:15
  • i am using this in mobile app with phonegap – Miqdad Ali Jun 07 '13 at 21:21
  • then you can use a 3rd party proxy, such as YQL – Kevin B Jun 07 '13 at 21:29
  • Could you please explain it – Miqdad Ali Jun 08 '13 at 04:42

7 Answers7

7

Looks like the inner JSON struct is passed along as a string. You'll have to JSON.parse() it once more to get that data as an object.

try {
  responseData = JSON.parse(responseData);
}
catch (e) {}

Edit: Try the following:

$.ajax({
    type: 'GET',
    dataType: "json",
    url: "http://someotherdomain.com/service.svc",
    success: function (responseData, textStatus, jqXHR) {
        console.log("in");
        var data = JSON.parse(responseData['AuthenticateUserResult']);
        console.log(data);
    },
    error: function (responseData, textStatus, errorThrown) {
        alert('POST failed.');
    }
});
EWit
  • 1,954
  • 13
  • 22
  • 19
6

Unfortunately it seems that this web service returns JSON which contains another JSON - parsing contents of the inner JSON is successful. The solution is ugly but works for me. JSON.parse(...) tries to convert the entire string and fails. Assuming that you always get the answer starting with {"AuthenticateUserResult": and interesting data is after this, try:

$.ajax({
    type: 'GET',
    dataType: "text",
    crossDomain: true,
    url: "http://someotherdomain.com/service.svc",
    success: function (responseData, textStatus, jqXHR) {
        var authResult = JSON.parse(
            responseData.replace(
                '{"AuthenticateUserResult":"', ''
            ).replace('}"}', '}')
        );
        console.log("in");
    },
    error: function (responseData, textStatus, errorThrown) {
        alert('POST failed.');
    }
});

It is very important that dataType must be text to prevent auto-parsing of malformed JSON you are receiving from web service.

Basically, I'm wiping out the outer JSON by removing topmost braces and key AuthenticateUserResult along with leading and trailing quotation marks. The result is a well formed JSON, ready for parsing.

ElmoVanKielmo
  • 10,907
  • 2
  • 32
  • 46
  • I have tried this tooo... but my script is not reaching inside success method – Miqdad Ali Jun 20 '13 at 09:30
  • Does it reach the error method? What's in responseData, textStatus and errorThrown? Assuming you have set `dataType` to `text`. – ElmoVanKielmo Jun 20 '13 at 10:22
  • So, have you tried to alert textStatus, responseData and errorThrown? – ElmoVanKielmo Jun 20 '13 at 12:03
  • I know this won't be the final solution, but we need to step forward. You said that this "nested JSON" is present in `responseData` regardless of the error. So try to use my code in `error` method instead of `success`. If you can successfully assign the data to variable `authResult` (JSON.parse doesn't fail), then we will just have to deduct from `textStatus` and `errorThrown` what exactly goes wrong. – ElmoVanKielmo Jun 21 '13 at 07:32
4

The response from server is JSON String format. If the set dataType as 'json' jquery will attempt to use it directly. You need to set dataType as 'text' and then parse it manually.

$.ajax({
    type: 'GET',
    dataType: "text", // You need to use dataType text else it will try to parse it.
    url: "http://someotherdomain.com/service.svc",
    success: function (responseData, textStatus, jqXHR) {
        console.log("in");
        var data = JSON.parse(responseData['AuthenticateUserResult']);
        console.log(data);
    },
    error: function (responseData, textStatus, errorThrown) {
        alert('POST failed.');
    }
});
Subir Kumar Sao
  • 8,171
  • 3
  • 26
  • 47
3

If you are planning to use JSONP you can use getJSON which made for that. jQuery has helper methods for JSONP.

$.getJSON( 'http://someotherdomain.com/service.svc&callback=?', function( result ) {
       console.log(result);
});

Read the below links

http://api.jquery.com/jQuery.getJSON/

Basic example of using .ajax() with JSONP?

Basic how-to for cross domain jsonp

Community
  • 1
  • 1
Techie
  • 44,706
  • 42
  • 157
  • 243
0

When using "jsonp", you would basically be returning data wrapped in a function call, something like

jsonpCallback([{"id":1,"value":"testing"},{"id":2,"value":"test again"}])
where the function/callback name is 'jsonpCallback'.

If you have access to the server, please first verify that the response is in the correct "jsonp" format

For such a response coming from the server, you would need to specify something in the ajax call as well, something like

jsonpCallback: "jsonpCallback",  in your ajax call

Please note that the name of the callback does not need to be "jsonpCallback" its just a name picked as an example but it needs to match the name(wrapping) done on the server side.

My first guess to your problem is that the response from the server is not what it should be.

KishanCS
  • 1,357
  • 1
  • 19
  • 38
PJR
  • 443
  • 4
  • 9
  • I dont have any access to the server, Whether I can do anything with my ajax script. – Miqdad Ali Jun 07 '13 at 17:25
  • If your response is just {"AuthenticateUserResult":"{\"PKPersonId\":1234,\"Salutation\":null,\"FirstName\":\"Miqdad\",\"LastName\":\"Kumar\",\"Designation\":null,\"Profile\":\"\",\"PhotoPath\":\"\/UploadFiles\/\"}"} and is not wrapped in a callback, I don't think you can use it. "jsonp" is just leveraging the script tag behind the scene and without a "callback", I don't think you can get hold of the response in your code. – PJR Jun 07 '13 at 17:28
  • I have tried with removing jsonp. but that time ajax error method is triggering and am not getting any response also. – Miqdad Ali Jun 07 '13 at 17:35
  • Your main problem is that the server is not sending the response in a format that can be called cross-domain (using jsonp). You cannot use json, as its cross-domain. Unless the server's response has a 'callback' name associated with it, I don't think you can use it when making a cross-domain call – PJR Jun 07 '13 at 17:40
  • There are 3 ways I can think of that can be used to make the cross-domain call you want. JSONP,CORS and using a proxy In your cases, it looks like “jsonp” cannot be used because the response is not in a format that “jsonp” supports (having the response wrapped up in a callback) – PJR Jun 11 '13 at 15:15
  • CORS can be used using “Access-Control-Allow-Origin” header and specifying the domain that can make the cross-domain call something like Access-Control-Allow-Origin: http://mydomain.com “*” can be used to allow all domains but is not recommended Please have a look at [link] https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS for more details. I think sites like http://enable-cors.org/ provide a test page to see if you/your domain can make a cross domain call to a server using CORS. You can also inspect the request/response headers and check this. – PJR Jun 11 '13 at 15:17
  • Your last option I believe is to use a proxy. You can write a proxy that would make the cross-domain call and then receive the response and process it as desired. You could potentially just make a call using a server-side language like php and then just wrap the response in a callback function so that “jsonp” can be used. Then instead of the original url, you can call your proxy in the ajax call and get the desired response. – PJR Jun 11 '13 at 15:17
  • I can't use any server side language. – Miqdad Ali Jun 12 '13 at 05:02
0

You just have to parse the string using JSON.parse like this :

var json_result = {"AuthenticateUserResult":"{\"PKPersonId\":1234,\"Salutation\":null,\"FirstName\":\"Miqdad\",\"LastName\":\"Kumar\",\"Designation\":null,\"Profile\":\"\",\"PhotoPath\":\"\/UploadFiles\/\"}"};

var parsed = JSON.parse(json_result.AuthenticateUserResult);
console.log(parsed);

Here you will have something like this :

Designation
null

FirstName
"Miqdad"

LastName
"Kumar"

PKPersonId
1234

PhotoPath
"/UploadFiles/"

Profile
""

Salutation
null

And for the request, don't forget to set dataType:'jsonp' and to add a file in the root directory of your site called crossdomain.xml and containing :

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<!-- Read this: www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html -->

<!-- Most restrictive policy: -->
<site-control permitted-cross-domain-policies="none"/>

<!-- Least restrictive policy: -->
<!--
<site-control permitted-cross-domain-policies="all"/>
<allow-access-from domain="*" to-ports="*" secure="false"/>
<allow-http-request-headers-from domain="*" headers="*" secure="false"/>
-->
</cross-domain-policy>

EDIT to take care of Sanjay Kumar POST

So you can set the callback function to be called in the JSONP using jsonpCallback!

$.Ajax({
    jsonpCallback : 'your_function_name',
    //OR with anonymous function
    jsonpCallback : function(data) {
        //do stuff
    },
    ...
});
Community
  • 1
  • 1
JoDev
  • 6,633
  • 1
  • 22
  • 37
  • Dude, my ajax success method not triggering – Miqdad Ali Jun 19 '13 at 13:02
  • Yes, in fact you will have to use a [callback function](http://stackoverflow.com/questions/3506208/jquery-ajax-cross-domain), but in your case, you can't because you don't have the hand on the other hand site! I'll search a bit more... – JoDev Jun 20 '13 at 09:13
0

Here is the snippets from my code.. If it solves your problems..

Client Code :

Set jsonpCallBack : 'photos' and dataType:'jsonp'

 $('document').ready(function() {
            var pm_url = 'http://localhost:8080/diztal/rest/login/test_cor?sessionKey=4324234';
            $.ajax({
                crossDomain: true,
                url: pm_url,
                type: 'GET',
                dataType: 'jsonp',
                jsonpCallback: 'photos'
            });
        });
        function photos (data) {
            alert(data);
            $("#twitter_followers").html(data.responseCode);
        };

Server Side Code (Using Rest Easy)

@Path("/test_cor")
@GET
@Produces(MediaType.TEXT_PLAIN)
public String testCOR(@QueryParam("sessionKey") String sessionKey, @Context HttpServletRequest httpRequest) {
    ResponseJSON<LoginResponse> resp = new ResponseJSON<LoginResponse>();
    resp.setResponseCode(sessionKey);
    resp.setResponseText("Wrong Passcode");
    resp.setResponseTypeClass("Login");
    Gson gson = new Gson();
    return "photos("+gson.toJson(resp)+")"; // CHECK_THIS_LINE
}
Community
  • 1
  • 1
Sanjay Kumar
  • 1,474
  • 14
  • 22