How to add cross domain support to WCF service
Solution 1
This worked better for me than the Web.config version:
Create a Global.asax
Add this method to the Global.asax.cs
:
using System.Web;
namespace StackOverflow
{
public class Global : System.Web.HttpApplication
{
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("Access-Control-Allow-Methods", "GET, POST");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}
}
}
Solution 2
Add these nodes to your Web.config:
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*"/>
<add name="Access-Control-Allow-Headers" value="Content-Type, Accept" />
<add name="Access-Control-Allow-Methods" value="POST,GET,OPTIONS" />
<add name="Access-Control-Max-Age" value="1728000" />
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>
Solution 3
Enabling CORS for non-GET requests requires more than just setting the Access-Control-Allow-Origin
header - it also needs to deal with preflight requests, which are OPTIONS
requests which ask the server whether it's safe to perform operations which can potentially change data (e.g., POST, PUT, DELETE) before the actual request is sent.
I've written a blog post about adding CORS support for WCF. It's not the simplest of the implementations, but hopefully the code in the post can be simply copied / pasted into your project. The post can be found at http://blogs.msdn.com/b/carlosfigueira/archive/2012/05/15/implementing-cors-support-in-wcf.aspx.
mike_hornbeck
Updated on March 09, 2021Comments
-
mike_hornbeck about 3 years
I'm trying to allow POST requests from my javascript app hosted at localhost:80 to a WCF REStful service hosted at a different port, but somehow it doesn't work. I've tried adding custom properties to the header, as well as adding it programatically in my service's
JSONData
method but I'm still getting '405 Method not allowed' in my response. What is the proper approach here ?This is my interface :
namespace RestService { public class RestServiceImpl : IRestServiceImpl { #region IRestServiceImpl Members public string JSONData() { HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*"); return "Your POST request"; } #endregion } }
and the service code :
using System.ServiceModel; using System.ServiceModel.Web; using System.Web.Script.Services; namespace RestService { [ServiceContract] public interface IRestServiceImpl { [OperationContract] [ScriptMethod] [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "export")] string JSONData(); } }
And finally the config :
<?xml version="1.0"?> <configuration> <system.web> <compilation debug="true" targetFramework="4.0" /> </system.web> <system.serviceModel> <services> <service name="RestService.RestServiceImpl" behaviorConfiguration="ServiceBehaviour"> <endpoint address ="" binding="webHttpBinding" contract="RestService.IRestServiceImpl" behaviorConfiguration="web"> </endpoint> </service> </services> <behaviors> <serviceBehaviors> <behavior name="ServiceBehaviour"> <serviceMetadata httpGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="false"/> </behavior> </serviceBehaviors> <endpointBehaviors> <behavior name="web"> <webHttp/> </behavior> </endpointBehaviors> </behaviors> <serviceHostingEnvironment multipleSiteBindingsEnabled="true" /> </system.serviceModel> <system.webServer> <modules runAllManagedModulesForAllRequests="true"/> <httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origin" value="*" /> </customHeaders> </httpProtocol> </system.webServer> </configuration>
-
mike_hornbeck over 11 yearsThat's almost what I need. But I've noticed that it doesn't work if you send the data as a json. Your exabple page sends a single string value with the POST request. Or maybe it's because ExtJS handles the request data differently than jQuery :/
-
carlosfigueira over 11 yearsThe example does send data as JSON - the inputs to the POST / PUT methods are JSON strings (notice that the input is wrapped in
"
's). It works for objects as well, it's just that in the example the operation takes a string as a parameter. -
mike_hornbeck over 11 yearsI've changed the data in the test page to ` var data = { foo: "bar" };` and I'm getting 400 Bad request. I've checked the logs but nothing helpful there. So should I make changes also in the WCF itself to support it ?
-
carlosfigueira over 11 yearsYes - in that case the operation must take a parameter of a user type, with a string field named 'foo'. If the operation takes a string, you should pass a string; you can only pass an object if the operation takes an object as a parameter.
-
mike_hornbeck over 11 yearsI've tried changing argument type to Object but the same happens. Have you tried your example with objects in place of strings ? Though JSON is stringified anyway so this should work with a string. Or am I wrong?
-
carlosfigueira over 11 yearsIt shouldn't be
Object
, but a data type which maps to the JSON you want to send. For example, if your class has a string property called "Foo", it should be able to accept the JSON object{"Foo":"hello world"}
as input. -
mike_hornbeck over 11 yearsOk, it was enough to just assign each property from the json to a new argument for the operation.
-
Vikrant about 9 yearsThanks a lot! finally got the exact solution, after searching a lot.
-
Jav T about 9 yearsGreat this finally worked after a couple of hours researching. Thanks bru!
-
khichar.anil about 8 yearsYou saved my lot of R&D hours. I really wanted to vote up more than one time :)..Thank you
-
FranP over 6 yearsWorked perfect for me!
-
Itération 122442 almost 6 yearsAs usual: What are the namespaces used? Please be specific, because my VS does not find it itslef.
-
Robert over 5 yearsnamespace: System.Web
-
ni3.net over 5 years+1 Solution Worked for me. Earlier I have defined all CORS setting in web config but sometimes it works and sometimes not.