views:

2354

answers:

2

I'm trying to do a cross domain POST request and have hit a wall (or two).

I can't put a proxy page on the server - so that is not an option.

I have researched getJSON, which works great except that I need to POST not GET.

Is it possible to do this? If it is not, can someone explain to me how getJSON works and why I cannot make a POST alternative.

+2  A: 

You can do a post, but what you want is a JSONP request to get around the cross domain issues. Essentially you provide a callback function and the request comes back as script content and your callback gets called with the JSON data from the request. Your server side script will need to provide the data back as a function call using the callback function wrapped around the JSON object.

See the documentation on the post function.

$.post( '/example.com/controller/action?callback=?',
        { param: "data" }, 
        function(data) {
             ...do something with the data...
        }, 'jsonp' );

ASP.NET MVC action for this:

[AcceptVerbs( HttpVerbs.Post )]
public ActionResult Action( string param, string callback )
{
     var jsonData = ...do something and construct some data in JSON...

     return Content( callback + "(" + jsonData + ");" );
}
tvanfosson
For future reference: it seems Google Chrome 6.0.472.63 doesn't like this too much. In Safari it processes the returned JSON but Chrome just shows the "Origin null is not allowed by Access-Control-Allow-Origin." message.
Cimm
+10  A: 

You CANNOT make a cross-domain request (GET / POST / etc.) with an XMLHttpRequest (aka AJAX).

What you can do, when the server supports it, is make a JSONP request. A JSONP request works as follows:

  • jQuery creates a globally accessible function out of the callback function you provide as an argument
  • Instead of using XMLHttpRequest (AJAX) to make the HTTP request, jQuery dynamically inserts a SCRIPT tag into the DOM
  • The SRC of the script tag is the request URL to which you are trying to communicate
  • jQuery adds a callback param to the query string like so: example.com/someurl.js?callback=someDynamicallyGeneratedMethodName
  • It is then up to the SERVER to return JavaScript that your client can use by passing the JSON result as an argument to someDynamicallyGeneratedMethodName

If you have no control of the server that you are posting to, then you are out of luck, JSONP won't do you much good. Whatever the server returns will be in a SCRIPT tag, and will most likely throw an error if it isn't formatted correctly.

For more info on this, I suggest you look at the base $.ajax function instead of the shortcuts. (In the jQuery documentation under Ajax. Sorry I can't post more links)

Again, if you don't have control of the server you are posting to, you might want to look into a proxy if possible. Otherwise, an IFRAME may be your only other option. There is also a method to accomplish this with a SWF (flash) object. I have tried neither, but they are workarounds to the limitations of the XMLHttpRequest object.

Hope I could help!

Stephen Delano
+1. Great post, and welcome to SO!
Manticore
Thanks for the explanation. It's a lot clearer after that than an hour Googling. I have access to the server that I'm posting to so it's all good.
Mr. Flibble
Err, how is this comment related to the topic? It doesn't cover POST which the OT is specifically asking!
HRJ
@HRJ, take a look at the $.ajax function in the jQuery API. You can set the options for any type of request you like by setting the type variable. If you want a POST request returning JSONP then you would code:$.ajax({type:'POST', dataType:'jsonp', ... more options ...})I apologize for not coding the entire problem out for you initially. Let me know if I can help you any further.-Stephen
Stephen Delano
this is right except for this: http://ha.ckers.org/blog/20090720/xmlhttpreqest-ping-sweeping-in-firefox-35/
Dan Beam
This is not correct. It's not possible to do SYNCHRONOUS cross-domain JSONP or script requests -- only asynchronous (really, it's dependent on the browser, but most are async nowadays). Setting async: false will still run the cross-domain request asynchronously.
zachleat