4

I have a webpage at localhost:63342 with a jQuery ajax call in that webpage, to my webservice server at localhost:55000. In the webservice I set the Access-Control headers.

In Chrome's developer tools, Network tab, I can see that the OPTIONS preflight thing is sent, and the response header has the following, which looks great.

Access-Control-Allow-Headers:x-requested-with, X-Auth-Token, Content-Type, Accept, Authorization
Access-Control-Allow-Methods:POST, OPTIONS, GET
Access-Control-Allow-Origin:*
Cache-Control:private
Content-Length:0
Date:Fri, 06 Jun 2014 13:30:58 GMT
Server:Microsoft-IIS/8.0

However, the response to the OPTIONS request hits the error function of my jQuery ajax call. Developer tools shows me that the browser prepares the POST, but fails it because it thinks the resource does not have the Access-Control-Allow-Origin header set. The browser does not try to send the POST. Here is the error message from the console of the browser:

XMLHttpRequest cannot load http://localhost:55000/webservice/ws.svc/CreateOuting. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63342' is therefore not allowed access. 

Its as though jQuery is interfering in the OPTIONS, POST process. Any ideas on what I should do to make this work?

Here is my ajax call

    $.ajax({
        type: 'POST',
        data: JSON.stringify(obj),
        headers: { "Content-type": "application/json" },
        url: base_url + 'CreateOuting',
        crossDomain: true,
        success: function (an_outing) {
                $('#listviewOutings').listview('refresh', true);
                $('#boxOutingName')[0].value = '';
                myLib.OpenBasicPopup('Success', 'The outing name was saved.')
        },
        error: function (err) {
            alert(err.statusText); // response to OPTIONS request ends up here
        }
    });

Here is how I set the headers in the method on the server (.NET C#):

public bh_Outing CreateOuting(string strOuting) {
    try
    {
        //for all cors requests  
        WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");
        //identify preflight request and add extra headers  
         if (WebOperationContext.Current.IncomingRequest.Method == "OPTIONS")
          {
            WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Methods", "POST, OPTIONS, GET");
            WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Headers", "x-requested-with, X-Auth-Token, Content-Type, Accept, Authorization");
            return null;
          }

        // do stuff

Here is the interface for that method. I dont think its perfect yet, but I dont think its the problem either.

[WebInvoke(UriTemplate = "*", Method = "*", ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
bh_Outing CreateOuting(string strOuting);

Thanks for taking a look at this. I am truly stuck.

Update, 6/17/14, 5:38 PM EST

I added a element to my webconfig as in this post, and this made no change to my results.

Community
  • 1
  • 1
pdschuller
  • 584
  • 6
  • 26
  • What does the request look like? Does it contain some sort of authentication credentials? If so you may have to include the `Access-Control-Allow-Credentials` header in the preflight response. See [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) – user1429080 Jun 16 '14 at 11:12
  • Set the `Access-Control-Allow-Credentials` on the server `localhost:50000` – GuyT Jun 16 '14 at 14:34
  • * I mean the `Access-Control-Allow-Origin` header ofcourse. – GuyT Jun 17 '14 at 09:02
  • Thanks user1429080 and GuyT but 1.) there are no credentials involved and 2.) the first code box above shows that the Access-Control-Allow-Origin header is fine in the response to the OPTIONS request. The problem is that the POST never gets sent. Its like the browser doesn't see that the OPTIONS request was successful. Any more ideas? – pdschuller Jun 17 '14 at 15:40
  • What is your jQuery version? – Paul Jun 17 '14 at 15:40
  • jQuery version is jquery-1.10.2.min.js – pdschuller Jun 17 '14 at 19:20
  • have you considered JSONP? Its born for cross domain ajax request – HypeZ Jun 18 '14 at 12:58
  • Thanks HypeZ, but jsonp doesn't work with POST. I have to use POST cause I have a large amount of data. – pdschuller Jun 18 '14 at 13:21

2 Answers2

0

This may be not the reason, but have you tried enabling cors in jQuery? Before any cors ajax request:

jQuery.support.cors = true;

Ilya Luzyanin
  • 7,910
  • 4
  • 29
  • 49
  • The results are unchanged. Thanks though. – pdschuller Jun 18 '14 at 16:55
  • Well, since server response looks good and you think it's jQuery problem, I'd suggest debugging it - I mean putting a breakpoint in error callback and then following the callstack to figure out, what is the cause. Have you tried this already? – Ilya Luzyanin Jun 18 '14 at 18:38
  • this does not enable CORS. Please read the [documentation on jquery's site](http://api.jquery.com/jquery.support/) before suggesting this again. – Ray Nicholus Jun 19 '14 at 11:44
  • Well, excuse me for this misunderstanding. I've read documentation before, thank you. Yes, it doesn't enable cors, but lets jQuery think that cors is supported. Strangely enough, that helped sometimes with similar issues, at least on old versions. That's why I specifically noted, that this may be not the reason. Please, give your suggestions on this issue. – Ilya Luzyanin Jun 19 '14 at 12:47
  • Yep Ilya your specific recommendation did not solve the problem, but your, "following the callstack to figure out" got me moving in the right direction - trying to look at the call stack. – pdschuller Jun 23 '14 at 19:31
  • Good. Please post the answer once you'll solve this, it's interesting to know the source of the problem. – Ilya Luzyanin Jun 24 '14 at 10:35
0

The cause of the problem that made me post the above question, seems to be that Chrome was incorrectly representing what was really happening. As I wrote above, what was happening was:

... the response to the OPTIONS request hits the error function of my jQuery ajax call. Developer tools shows me that the browser prepares the POST, but fails it because it thinks the resource does not have the Access-Control-Allow-Origin header set. The browser does not try to send the POST.

To try to get more detail, I installed and used Microsoft Message Analyzer. It showed that the OPTIONS request was being sent; the OPTIONS response was being sent; the POST request was being sent back to the webservice (!!!) and a POST response was being sent.

This was a huge breakthrough because now, instead of trying to solve a CORS problem (the error message that Chrome developer tools showed) I started working to solve a "Not Found" and then a "Bad Request" error (the error messages that MS Message Analyzer showed).

The other technique I used that helped a lot was that I set up tracing in my webservice. Tracing wrote stuff to a log file which default-opens in an event viewer and provided the details that I needed to figure out the (real) issues. Here is what I put in the webconfig to enable tracing.

  <system.diagnostics>
    <trace autoflush="true" />
    <sources>
      <source name="System.ServiceModel"
              switchValue="Critical, Error, Warning"
              propagateActivity="true">
        <listeners>
          <add name="myListener"
              type="System.Diagnostics.XmlWriterTraceListener"
              initializeData= "c:\logs\ServiceModelExceptions.svcLog" />
        </listeners>
      </source>
    </sources>
  </system.diagnostics>

I made no changes to the CORS settings (jQuery and web.config) and its running fine in Chrome now. Also, I have the webservice out on the www, so it is truly cross-domain, not just localhost:63342 to localhost:55000.

pdschuller
  • 584
  • 6
  • 26