1

I'm executing the following AJAX call to another domain.

  $.ajax({
    url: "http://.../MyService.svc/Ping",
    dataType: 'jsonp',
    jsonp: 'callback',
    processData: false,
    jsonpCallback: 'jsonCallback',
    success: function (a, b, c) { notify("Wheee..."); },
    error: function (a, b, c) { notify("Buuu... " + a + "-" + b + "-" + c); }
  });

I get the connection and the status is 200 OK. However, I get the call to error method that notifies me that parsererror and jsonCallback was not called. The URL I see being called looks like this.

[12:29:55.807] GET =1371724195683">http://.../MyService.svc/Ping?callback=jsonCallback&=1371724195683 [HTTP/1.1 200 OK 1912ms]

The service is configured to serve JSON format. If I manually enter the call in the URL line of my browser, the response on the screen says this.

"jsonCallback(pong @ 10:38:46 20-Jun-2013)"

I'm out of ideas on what I'm missing. (It's probably something straight-forward but I've got agitated and my annoyance hinders me from realizing what that might be.)

EDIT:

After being pointed out that the validity of the returned JSON object is mandatory, I tested a few different outputs via the browser's URL line, as listed below. None of these seemed to change the parsererror problem though when making the call from JS. What more can I be doing wrong?

"{result: \"pong at 12:42:06 20-Jun-2013\"}"
"jsonCallback('{result: \"pong at 12:49:54 20-Jun-2013\"}')"

EDIT:

The parser of @.ajax is actually very forgiving. However, on needs to activate the cross domain scripting access in web.config as shown below. ANd make sure you do that on the correct endpoint.

<webHttpBinding>
  <binding name="UrlHttpBindingJsonP" 
           crossDomainScriptAccessEnabled="true"/>
</webHttpBinding>

See this article.

Konrad Viltersten
  • 36,151
  • 76
  • 250
  • 438
  • 1
    Is the output a valid json string? "pong @ 10:38:46 20-Jun-2013" is not json. – Ankit Jaiswal Jun 20 '13 at 10:44
  • @AnkitJaiswal Thanks. Point taken. Format corrected. Two new strings returned. Problem still not dead. :) – Konrad Viltersten Jun 20 '13 at 12:52
  • @AnkitJaiswal: For JSONP, it needs to be a valid JS literal. But indeed, `pong @ 10:38:46 20-Jun-2013` is not a valid JS expression. – Bergi Jun 20 '13 at 13:03
  • @Bergi Would you take a look at my edit? Especially the last line seems to me like a valid JS expression, doesn't it? What more am I missing there? – Konrad Viltersten Jun 20 '13 at 13:08
  • @KonradViltersten: not sure. Are the outermost quotes in your response, or just in the displaying? With them, it's just a (valid) string literal but not invoking the callback function. – Bergi Jun 20 '13 at 13:10
  • @Bergi Not sure, neither, hehe. I only return a *String* from my C# code. Why the escape characters show and why the outer quotation marks are shown - beats me... Konrad not happy. I'm sitting at a client's place so I can't install stuff. How can I check the exact response contents (I'm on FF, Cr and IE only)? – Konrad Viltersten Jun 20 '13 at 13:17
  • See my updated answer. It should be `jsonCallback({"result": "pong @ 10:38:46 20-Jun-2013"})`. Quotes around "result" and leave out single quotes around the whole expression. – Patrick McElhaney Jun 20 '13 at 14:10
  • That's what should be in the body of the response. You might still need backslashes to escape quotes in your server side script. – Patrick McElhaney Jun 20 '13 at 14:11

1 Answers1

1
jsonCallback(pong @ 10:38:46 20-Jun-2013)

That's not valid JavaScipt. First, the argument should be wrapped in quotes so it's a string.

jsonCallback("pong @ 10:38:46 20-Jun-2013")

Not sure if it really matters, but a plain old string is still not valid JSON*. You may need to wrap it in an object or an array. Try this:

jsonCallback({"result": "pong @ 10:38:46 20-Jun-2013"})

*If you accept Crockford's definition. See the comments.

Patrick McElhaney
  • 57,901
  • 40
  • 134
  • 167
  • Hmm... I thought that it didn't matter for the *success* and *error* method. I assumed that it was yay/ney for the **communication** not the parsing. I'll stand corrected (for my laziness, hehe). Still, I'm unclear - should I only return the JSON formatted string *{someKey: "someVal"}* or should I include the method call as *jsonCallback('{someKey: "someVal"}')*? I'd guess it's the latter but I still get the same error (plus my quotes seem to have the escape character displayed in the output which was a bit unexpected). The nested quotations marks are a bit confusing... – Konrad Viltersten Jun 20 '13 at 12:32
  • a) JSONP *is not* valid JSON. b) a string literal *is* valid JSON. c) your last snippet is still a string, not an object literal. – Bergi Jun 20 '13 at 13:06
  • @KonradViltersten: neither. It should be `jsonCallback({someKey: "someVal"})`. Read http://en.wikipedia.org/wiki/JSONP on how it is supposed to work. – Bergi Jun 20 '13 at 13:06
  • @Bergi Thanks for the info. I've read the article and I get the concept. Now I get stuck on the fact that my *Ping* method server-side **will** return a *String* typed response. Are you implying that I'll need **another** method that exposes a *Stream* typed response? I hardly slept last night because I was so PO-ed at this so I'm a bit dense in the head right now. :) – Konrad Viltersten Jun 20 '13 at 13:13
  • @KonradViltersten: not sure what you mean by *Stream*. However, to send the result string you will need to JS-escape it (unless it already is). Just `jsonCallback("pong @ 10:38:46 20-Jun-2013")` would be valid as well. – Bergi Jun 20 '13 at 13:16
  • @Bergi I'm starting to see where I get stuck. It's a WCF exposing a string. It's not converted to a JS-literal, despite the attribute on the method (set to JSON). Getting back to google... – Konrad Viltersten Jun 20 '13 at 13:21
  • 1
    @Bergi You're right. I guess JSONP is a bit of a misnomer, since the code inside the parentheses is an object literal, [not necessarily JSON](http://stackoverflow.com/questions/2904131/what-is-the-difference-between-json-and-object-literal-notation). – Patrick McElhaney Jun 20 '13 at 13:57
  • @Bergi Okay, according to the spec, it does have to be valid JSON. Technically `jsonCallback({someKey: "someVal"})` is not valid because the key isn't enclosed in quotes. `jsonCallback("pong @ 10:38:46 20-Jun-2013")` and `jsonCallback('{"someKey": "someVal"}')` are also not valid according to the strict definition because a string literal by itself is not valid JSON. – Patrick McElhaney Jun 20 '13 at 14:08
  • @Patrick: Both are valid JSON*P*, I meant. It doesn't matter to javascript whether you delimit your strings with quotes or apostrophes. Btw, plain strings (with quotes) are also valid JSON values – Bergi Jun 20 '13 at 15:54
  • @Bergi ["A JSON text is a serialized object or array."](http://www.ietf.org/rfc/rfc4627.txt?number=4627) According to http://json-p.org the inside of the parentheses "must be a strictly valid and parseable JSON object". I'm not aware of any authoritative standard that defines JSONP, but figure it's better to be safe than sorry. – Patrick McElhaney Jun 20 '13 at 16:05
  • Ah, I see. At least `JSON.parse`/`.stringify` do accept non-object/array values. – Bergi Jun 20 '13 at 16:23
  • @Bergi Actually, as it turns out, the *@.ajax* call is very tolerant and you might put in pretty much anything in there (which I thought in the beginning but got uncertain of later). The issue was that I didn't activate cross domain script access on the correct endpoint, which was entirely someone else's fault (read: entirely mine). Once I've added it to the *web.config*, the rainbow appeared. Nevertheless - great discussion on the validity on JSON(P) format and **huge thanks** to both of you. – Konrad Viltersten Jun 20 '13 at 17:52
  • @Bergi This has been a fascinating tangent. It turns out that while according to Crockford, only an array or object can be at the top level of a JSON string, [ECMAScript 5.1](http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf) is more liberal (see section 15.12.1.2). – Patrick McElhaney Jun 20 '13 at 17:58