tags:

views:

1018

answers:

3

Hi All, Been doing some playing call my service which is on a different domain using jQuery. The call to the service is successfully made (my debug point gets tripped), and the correct response is returned (I sniff the traffic).

My problem is mainly that the success and failure callbacks don't get fired. I have read some other posts on SO that indicate the error event is not fired when using JSONP. Is that the case with the success event (perhaps because it is assumed that I am providing my own callback function), as well, or is there a way to fire my success callback. Thanks in advance.

$.ajax({
  type: "GET",
  url: urlOnDiffDomain,
  async: false,
  cache: false,
  dataType: 'jsonp',
  data: {},
  success: function(data, textStatus) {
    alert('success...');
  },
  error: function(xhr, ajaxOptions, thrownError) {
   alert('failed....');
  }
}); 
A: 

Try

$.getJSON(urlOnDiffDomain, function(data, textStatus){
    alert('success...');
});

Works for me, usally. You need to add &callback=? to urlOnDiffDomain, where jQuery automatically replaces the callback used in JSONP.

The error callback is not triggered, but you can use the global $.ajaxError, like this

$('.somenode').ajaxError(function(e, xhr, settings, exception) {
    alert('failed');
});
codecandies
SanjayU
A: 

The success callback method is called when the server responds. The $.ajax method sets up a function that handles the response by calling the success callback method.

The most likely reason that the success method is not called, is that the response from the server is not correct. The $.ajax method sends a value in the callback query string that the server should use as function name in the JSONP response. If the server is using a different name, the function that the $.ajax method has set up is never called.

If the server can not use the value in the callback query string to set the function name in the response, you can specify what function name the $.ajax method should expect from the server. Add the property jsonpCallback to the option object, and set the value to the name of the function that the server uses in the response.

If for example the $.ajax method is sending a request to the server using the URL http://service.mydomain.com/getdata?callback=jsonp12345, the server should respond with something looking like:

jsonp12345({...});

If the server ignores the callback query string, and instead responds with something like:

mycallback({...});

Then you will have to override the function name by adding a property to the options object:

$.ajax({
  url: urlOnDiffDomain,
  dataType: 'jsonp',
  data: {},
  success: function(data, textStatus) {
    alert('success...');
  },
  jsonpCallback: 'mycallback'
});
Guffa
I've changed the value returned from my service. It now looks like this: string qs = HttpContext.Current.Request.QueryString["callback"]; return qs + "({'d':'s'})";Given the following client-side code:var url = 'http://some.other.domain/service/serviceName.svc/param1/1/param2/2'; $.ajax({ url: url, dataType: 'jsonp', data: {}, jsonpCallback: 'mycallback', success: function(data, textStatus) { alert(data); }})The content from the response looks like:"jsonp1267721964115({'d':'s'})" Seems like it's attaching a callback func despite the property?
SanjayU
Ugh. Sorry about that formatting
SanjayU
@rhythmaddict: What version of jQuery are you using? You need version 1.4 or later for the jsonpCallback property to be used. However, as you changed the server code to correctly use the callback query string, you don't need to use the jsonpCallback property.
Guffa
A: 

Alright. In case anyone needs to know in the future...In hindsight, the solution probably should have been more obvious than it was, but you need to have the web-response write directly to the response stream. Simply returning a string of JSON doesn't do it, you need to someone construct it and stream it back. The code in my original post will work fine if you do indeed do that.

Example of service code:

public void DoWork()
{
  //it will work without this, but just to be safe
  HttpContext.Current.Response.ContentType = "application/json"; 
  string qs = HttpContext.Current.Request.QueryString["callback"];
  HttpContext.Current.Response.Write(qs + "( [{ \"x\": 10, \"y\": 15}] )");
}

Just for the sake of being explicit, this is the client-side code.

function localDemo(){
  $.getJSON("http://someOtherDomain.com/Service1.svc/DoWork?callback=?",
    function(data){
      $.each(data, function(i,item){            
        alert(item.x);
      });
  });
}

If there is a better way to do this, I am all ears. For everyone else, I know there is some concept of native support in WCF 4.0 for JSONP. Also, you may want to do a little checking for security purposes - though I have not investigated much.

SanjayU
The easiest way to make a JSONP service in .NET is to use an HTTP Handler, then there is no page markup to suppress, you just write to the response stream.
Guffa
Out of curiosity: How did you "return" the string when you didn't write it to the response stream?
Guffa
Agreed Guffa. It also doesn't help it's tricky to remove the default JSON wrapper that WCF gives you..You can work around it, but it's just _one more thing_ to keep in mind. A: By naively doing a return "stuff";
SanjayU