Going nuts with this issue. I have a solution with 2 projects, one of them is a plain old html with jquery ajax call while the other is a WCF service. The html page will iss
You need to use JSONP for a cross-domain call to get round the browser restrictions, and to update your web.config with crossDomainScriptAccessEnabled
set to true to get round server ones. There's a good example in the answer here: how to avoid cross domain policy in jquery ajax for consuming wcf service?
You may also have a problem with GET requests. Try the fixes outlined here: Making a WCF Web Service work with GET requests
Altogether, you want a web.config that looks something like this:
<bindings>
<webHttpBinding>
<binding name="crossDomain" crossDomainScriptAccessEnabled="true" />
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehavior>
<behavior name="restBehavior">
<webHttp />
</behavior>
</endpointBehavior>
<serviceBehavior>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehavior>
</behaviors>
<services>
<service name="..." behaviorConfiguration="MyServiceBehavior">
<endpoint address="" binding="webHttpBinding" bindingConfiguration="crossDomain"
contract="..." behaviorConfigurations="restBehavior" />
</service>
</services>
(Note that both the service and the endpoint have behaviours attached, allowing webHttp calls and httpGet calls respectively, and that the binding has crossDomain access explicitly enabled).
... a service method decorated like this:
[ServiceContract]
public interface IMyService
{
[WebGet] // Required Attribute to allow GET
[OperationContract]
string MyMethod(string MyParam);
}
... and a client call using JSONP:
<script type="text/javascript">
$(document).ready(function() {
var url = "...";
$.getJSON(url + "?callback=?", null, function(result) { // Note crucial ?callback=?
// Process result
});
});
</script>
Just wanted to append some issues with the CORS rework at the bottom - The problem with it is that if your input does not support the GET and POST method, the OPTIONS request is not actually returning the correct allowed headers. It really isn't looking at which methods are actually allowed on the WCF endpoint - its just artificially saying "GET, POST" are allowed for every single endpoint in the application when a client performs an OPTIONS request (which is really the client asking what is supported).
This is probably OK, if you aren't really relying on the information in the OPTIONS method to return you a valid list of methods (as is the case with some CORS requests) - but if you are, you will need to do something like the solution on this question: How to handle Ajax JQUERY POST request with WCF self-host
Basically, each endpoint should implement:
Webinvoke(Method="OPTIONS", UriTemplate="")
and call an appropriate method which loads the proper headers to the response (including the proper "Access-Control-Allow-Method" list for that endpoint) to the caller. It kind of sucks that hosted WCF endpoints don't do this for us automatically, but this is a workaround that allows finer control over the endpoint. In that solution the proper response headers are loaded at the endpoint implementation:
public void GetOptions()
{
// The data loaded in these headers should match whatever it is you support on the endpoint
// for your application.
// For Origin: The "*" should really be a list of valid cross site domains for better security
// For Methods: The list should be the list of support methods for the endpoint
// For Allowed Headers: The list should be the supported header for your application
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Accept, Authorization");
}
try to use.
WebInvoke(Method = "POST")
instead of WebInvoke(Method = "GET")
However its an old thread, but I would like add my comment about the problems I faced and the solution I got for working of CORS. I am developing a web service in the following environment:
Most of the people mentioned about adding the crossDomainScriptAccessEnabled
attribute in tag under <webHttpBinding>
in web.config. I am not sure this works or not but its not available in 3.5 version, so I had no choice. I also found that adding the following tags in web.config will work...
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET" />
<add name="Access-Control-Allow-Headers" value="Content-Type, Accept" />
</customHeaders>
</httpProtocol>
but no luck...kept getting 405 method not allowed errors
After struggling a lot with these options I found another solution to add these headers in global.asax file dynamically as per the given below...
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept, Authorization");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}
And remove the from web.config. Publish the website and continue to client side jquery/ajax...and you will get the data from api calls. Good Luck!