Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling WCF/JSON/REST WebService from JavaScript using jQuery/Ajax

I know there are a lot of questions out there about this - believe me I've read a lot of them and tried the answers out.

(This project is for an internal company lan, not the internet)

We have a WCF webservice which is RESTFUL and sends/receives JSON, it requires NTLM (Kerb would also be good) auth/credentials to ensure that the calling user (from the browser is who they say they are), and this is negotiated between the browser/client and the service by the WCF bindings:

 <bindings>
  <webHttpBinding>
    <binding name="webHttpBindingAuth">
      <security mode="TransportCredentialOnly">
        <transport clientCredentialType="Ntlm"/>
      </security>
    </binding>
  </webHttpBinding>
</bindings>

Using Fiddler, I can call the methods on the service GET and POST successfully and provided I adjust the JSON we're sending to the webservice (to include the session ID for example) it trundles along happily.

The problems started when we tried to use JavaScript/jQuery to call the webservice; the idea is that a web server will supply the HTML/JS to the client browser, the browser should then call the WCF webservice to get a session and allow a user to perform a few actions (we have 3 methods in total).

Firstly, we ran into the X-Domain issue, which we tried to resolve by getting the web server to return the correct headers (Access-Control-Allow-Origin). This didn't prevent browsers like SRIron from telling us that;

XMLHttpRequest cannot load http://{webServiceUri}/InstantMessagingService/chat/start/{username}. Origin http://{web**Server**Uri} is not allowed by Access-Control-Allow-Origin.

Following this, I investigated the possibility of using Silverlight (doesn't seem to support NTLM auth over WebHttpBinding), reverse proxy is out, as the IIS server being used in dev won't be used in prod (I believe it is WebSphere, but not under our control); next I looked at this:

http://msmvps.com/blogs/paulomorgado/archive/2007/04/27/wcf-building-an-http-user-agent-message-inspector.aspx

Which left me under the impression that the WCF web service was in fact the thing that needed to tell the browser where it was allowed be called from (if that makes sense). Having implemented all the code from the example, I found that the ApplyClientBehavior was never called to attempt to return the headers to the client (monitoring this in Fiddler too). Some more Googling led me to:

http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/707aa031-f4ff-47ab-ba5b-730f7930605e/

Since we're accessing the web service using jQuery and not some .NET client/service reference/proxy/app.. blah, I'm thinking that it's not possible to pre-request-send these headers to allow access to the service. Also, Fiddler seems to think that it's getting a 401 Unauthorized when it does make the attempt to call the http://../chat/start/.. method.

Here's the jQuery I'm using to attempt to make the call (I supplied a few settings in the hope it was going to work):

var url = webserviceUrl + "chat/start/" + remoteUserUri;

$.ajax({
    type: 'GET',   
    url: url,
    crossDomain: true,
    beforeSend: function(xhr){ xhr.withCredentials = true; },
    contentType: "application/json; charset=utf-8",               
    success: function (data) { conversationStarted(data); },
    dataType: 'json'
}); 

Ok, if anyone has helpful hints or ideas, please fire away. I'll reply and edit etc. to make sure this is kept up to date, I hope I haven't missed anything (but my heads spinning a little from my Googling).

Also, I know that there might be better ways to do this, but I'd like to do it in the cleanest/quickest way from where I am now - i.e. not a lot of code changes, rewrites etc. I can also post up configs if people think they really are useful.

like image 227
peteski Avatar asked Jun 01 '11 16:06

peteski


2 Answers

In the end I had to kind of work around, we got the guys in charge of the web server to agree to serving up an IFrame which points to our IIS hosted page (the one containing the JS etc.)

Then using the magic of WCF/Windows we host the WCF services on port 80 which gets around the X-Domain origin stuff. So I can then have REST/JSON without having to use JSONP.

I know it's not the answer to the question given the criteria I specified, but I think I ran out of options completely in the end.

like image 86
peteski Avatar answered Oct 16 '22 16:10

peteski


Can you use JSONP? It'll solve your cross-domain problem in a heartbeat.

like image 45
jvenema Avatar answered Oct 16 '22 14:10

jvenema