4

I have just created my first WCF service and I would like to share it with other clients. I have added the Access-Control-Allow-Origin header in IIS, in Web.config, and in Global.asax, but remote clients are still not allowed to access the service. I have tested in Chrome and IE (our org's supported browsers). My error is "Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource."

In Web.config:

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Headers" value="Content-Type"/>
    <add name="Access-Control-Allow-Methods" value="POST,GET,OPTIONS"/>
  </customHeaders>
</httpProtocol>

In Global.asax:

protected void Application_BeginRequest(object sender, EventArgs e)
{
    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");

    if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
    {
        //These headers are handling the "pre-flight" OPTIONS call sent by the browser
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
        HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
        HttpContext.Current.Response.End();
    }
}

And here they are in IIS:

Screen shot of IIS

Here's the JavaScript trying to access the service. It works locally but not remotely:

$.ajax({
    type: "POST",
    url: "http://localhost/wsSamwise/Service1.svc/GetTime",
    data: '{"UserName": "' + userName + '"}',
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function(data) {
        $("#results").html(data.GetTimeResult);
        console.log(data);
    }
});

All of these ideas came from various Stackoverflow threads, but none of them are working for me. What have I missed?

EDIT: I just checked out the headers for the response in my localhost vs. the remote browser. I see the Access-Control-Allow-Origin header in the response for my localhost, but not in the response on the remote browser. It's like it's not being sent.

The response headers from my localhost:

Access-Control-Allow-Headers:Content-Type
Access-Control-Allow-Methods:POST,GET,OPTIONS
Access-Control-Allow-Origin:*
Access-Control-Allow-Origin:*
Cache-Control:private
Content-Length:82
Content-Type:application/json; charset=utf-8
Date:Thu, 05 May 2016 16:01:28 GMT
Server:Microsoft-IIS/7.5
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET

The response from the remote browser:

Allow:OPTIONS, TRACE, GET, HEAD, POST
Content-Length:0
Date:Thu, 05 May 2016 16:00:09 GMT
Public:OPTIONS, TRACE, GET, HEAD, POST
Server:Microsoft-IIS/7.5
X-Powered-By:ASP.NET

EDIT 2: Guys, maybe it's an IIS issue totally. I just added a custom header to IIS. It's showing up in the localhost browser, but not on the client. The Body-Count header is missing from remote browser, but I see it on the local browser.

custom header

mrcoulson
  • 1,331
  • 6
  • 20
  • 35
  • How, specifically, is it not working? Does it time out? Give an error message? Empty response? – Brian May 05 '16 at 14:55
  • Edited to included error. – mrcoulson May 05 '16 at 15:14
  • Have you checked [this link](http://www.productiverage.com/wcf-cors-plus-json-rest-complete-example)? – Daniel J.G. May 05 '16 at 15:40
  • I hadn't seen that one. It seems to add a lot of complexity to what appears to be a simple solution in a lot of other tutorials and threads. I'm not even sure where to begin implementing it in my service. – mrcoulson May 05 '16 at 16:13
  • But your other clients use JQuery client ? Or is juste for your test. Because is not the same problem if your client use Java Or C# etc... – ArDumez May 05 '16 at 19:27
  • The clients will be using jQuery. We have several existing web services that are consumed from ASP.NET applications, but we need to publish some new services for wider client-side access. – mrcoulson May 05 '16 at 22:55
  • Ugh. I just answered my own question. Someone please revoke my permission to write code ever again. I had the URLs for the services in my HTML page pointing to `http://localhost...` Of course that won't work on another machine where there is no service hosted! I changed the URLs to point to the FQDN of the test machine where the services are hosted and everything is fine. So, should I post that as an answer to my own question? So embarrassed... – mrcoulson May 05 '16 at 23:14

2 Answers2

2

Make sure the Ajax URL is correct.

In the original code posted, the URL of my Ajax request is looking at localhost instead of the FQDN of the machine hosting the service. That was the problem. Of course the Ajax request will not work if the service is not hosted at the URL. I was so distracted by the error message that I missed the obvious and easy solution.

mrcoulson
  • 1,331
  • 6
  • 20
  • 35
1

Use JSONP is most classic and standard for working from differente domaine (Cross-Origin Request Sharing). And after look to Access-Control-Allow-Origin for add specifique restriction.

Use JSONP like this : The new JSONP feature is exposed via the WebHttpBinding. The configuration for the CustomersService would looks like this:

 <bindings>
    <webHttpBinding>
      <binding name="webHttpBindingWithJsonP" crossDomainScriptAccessEnabled="true" />
    </webHttpBinding>
  </bindings>
  <services>
    <service name="ServiceSite.CustomersService">
      <endpoint address="" binding="webHttpBinding"
                bindingConfiguration="webHttpBindingWithJsonP" contract="ServiceSite.CustomersService"
                behaviorConfiguration="webHttpBehavior"/>
    </service>
  </services>

Consuming JSONP with jQuery

 // Get the JsonP data
 $.getJSON('http://localhost:65025/CustomersService.svc/GetCustomers?callback=?', null, function (customers) {
      alert('Received ' + customers.length + ' Customers');
 });

Source: How to natively enable JSONP for existing WCF service?

Community
  • 1
  • 1
ArDumez
  • 931
  • 6
  • 24
  • This would replace `$.ajax({})` in client applications? I thought `$.ajax({})` is the preferred way to interact with a web service. – mrcoulson May 05 '16 at 17:36
  • When I try this, I get the error that the `'webHttpBehavior' is invalid according to its datatype 'endpointBehaviorConfugurationType'. When I run it, I get a JS error "method not allowed". – mrcoulson May 05 '16 at 18:14
  • Try with this documentation: http://www.bendewey.com/index.php/186/using-jsonp-with-wcf-and-jquery – ArDumez May 05 '16 at 19:19
  • Post your code of web service and web.config. $.ajax is most verbose. https://learn.jquery.com/ajax/working-with-jsonp/ – ArDumez May 05 '16 at 19:21
  • I'm concerned about over-stuffing the original post with 14 tons of code. Is there a specific part of the service which would be good to show? – mrcoulson May 05 '16 at 22:57
  • Upvote because I had never considered JSONP. Thanks! – mrcoulson May 09 '16 at 18:20