Reputation:
Heyya,
I know this question has been asked before and I have read each and every answer of every single question here but still can't seem to get my project working properly. My scenario is a bit different than other questions though, not sure if this makes any difference but here we go.
I have a project made of web services. Services alone works fine, there is no problem with that. And there is this another project which handles the UI part of things and call these services through jquery ajax. It has been working fine because I haven't tested this case on Google Chrome before. Everything works perfectly on Internet Explorer.
Now; my web service application runs on port 40000 (localhost:40000) and the UI project runs on some other random port but still in the localhost. Like I said, my ajax calls etc works perfectly on Internet explorer but when it comes to Google Chrome it fails. The console shows the following error:
XMLHttpRequest cannot load http://127.0.0.1:40000/abc.asmx/TheMethodName. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:17256' is therefore not allowed access. The response had HTTP status code 400.
By the way, it was like "localhost:40000" before so some post on the internet suggested that I should change it to an IP address instead of localhost.
Anyway, I have also edited my web.config file on my web service project and added the following (which doesn't make any sense)
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="crossDomain" crossDomainScriptAccessEnabled="true">
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="http://localhost:17256" />
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS" />
<add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
<add name="Access-Control-Max-Age" value="1728000" />
</customHeaders>
</httpProtocol>
</system.webServer>
BTW, if I use the first line: it completely fails and says the response header messages do not match and I can't even start the service invoke.
And yes, I have also edited my ajax call, added the following parameter:
crossDomain: true,
Now, what am I missing here? I have been on this for days now and I am about to lose my mind :) It is kinda too late to change the whole structure of the project (service - UI style I mean) since loads of code have been written to the services and UI projects. Please help I'm desperate! :)
Cheers
Edit:
So it turns out I need to use JSONP, not JSON - since it doesn't get stuck with Access Control thing, which is fine. I can convert my ajax calls into JSONP ones. But I need another help :)
I have written a global ajax method that is called from each operation on seperate pages and it works like charm (on Internet Explorer again of course). Now what should I do to convert this wrapper function into a jsonp thingy?
function RemoteCall(WebService, RemoteMethod, RemoteParameters, callbackResult) {
if (RemoteParameters == null || RemoteParameters == "") {
RemoteParameters = "{ }";
}
var remoteCall = $.ajax({
type: "POST",
url: ProvideService(WebService, RemoteMethod),
data: RemoteParameters,
contentType: ajaxContentType,
dataType: ajaxDataType,
async: true,
crossDomain: true,
success: function (msg) {
msg.header("Access-Control-Allow-Origin", "*");
callbackResult(msg.d);
},
error: function (xhr, ajaxOptions, thrownError) {
callbackResult(xhr.status + '\r\n' + thrownError + '\r\n' + xhr.responseText);
}
});
}
I saw some posts that I should add a property as jsonp: 'jsonp_callback' with the callback method (this is where I am confused). What about this?
Another thing; I have been sending my json parameters as a text in a variable like
var jSONParams = '{ UserID: "1", EmailAddress: "[email protected]" }';
Should I keep sending this as the same format or should it be converted to some sort of JSON object or something?
BTW: my global ajax function is in a completely seperate JS file - not sure if it makes any difference though...
Cheers
Upvotes: 9
Views: 19906
Reputation: 1489
add below code in web.config file.
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Credentials" value="true" />
</customHeaders>
</httpProtocol>
Upvotes: 0
Reputation:
Thank you all for your answers;
I found the solution to my problem. Seems like I haven't been paying full attention of the error message properly :)
After I added the Access-Control-Allow-Origin header into my web.config file, it turns out I started getting some other error, which was content-type custom header was missing and I thought I was still getting the CORS error.
So, adding the <add name="Access-Control-Allow-Origin" value="*" />
definition into my web.config actually solved my cross-origin problem in the first place! And I also have tested to allow specific domains or requests from ports with the following web.config header entry and it also worked like charm - since I think it is the best option to use since I will not be publishing my services publicly.
<add name="Access-Control-Allow-Origin" value="http://localhost:17256" />
Cheers to all, problem solved :)
Upvotes: 0
Reputation: 7281
The key to solving CORS errors is paying attention to the headers in the server response(s). You need to download an http traffic monitor like Fiddler to examine these headers. Then, you can use it in conjunction with the browser console errors to figure out exactly what's going wrong.
Here's what a typical/successful 200 OK CORS response looks like (taken directly from Fiddler):
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Vary: Accept-Encoding
Server: Microsoft-IIS/7.5
Access-Control-Allow-Origin: http://localhost:1234
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET,POST,OPTIONS
X-AspNet-Version: 4.0.30319
X-UA-Compatible: IE=edge
Persistent-Auth: false
WWW-Authenticate: Negotiate oYG2MIGzoAMKAQChCwYJKoZIgvcSAQIC...etc.
Date: Fri, 08 May 2015 01:14:37 GMT
Connection: close
Content-Length: 4711
...response body etc. etc.
In the case where you're getting the
No 'Access-Control-Allow-Origin' header is present on the requested resource
, the header is either missing from the response or being delivered in a way that violates Chrome's implementation of the W3C spec.
By looking at your web.config file, I'm willing to bet its the latter. For example, this is a valid Access Control Allow Origin header with multiple entries:
Access-Control-Allow-Origin: http://domain1.com,http://domain2.com
whereas the way your web.config headers section is configured will deliver multiple entries, which is generally invalid
Access-Control-Allow-Origin: http://localhost:17256
Access-Control-Allow-Origin: *
... especially in scenarios where authentication and the Access-Control-Allow-Credentials headers are being passed to secured endpoints:
Upvotes: 1
Reputation: 1711
I will prefer to just enable CORS than changing all your AJAX call.
Do you try to modified the web.config for the webservice to add the following line yet ?
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
Check also this questions for if CORS / JSONP is better for you So, JSONP or CORS?
Upvotes: 5
Reputation: 1
Welcome to the not so cool land of CORS issue in the browserland, i have the following recommendations:
I Hope it helps
Regards, Arif Imran
Upvotes: 0