How to add cross domain support to WCF service

42,053

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();
            }
        }
    }
}

Ref: http://www.dotnet-tricks.com/Tutorial/wcf/X8QN260412-Calling-Cross-Domain-WCF-Service-using-Jquery.html

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>

Ref: http://theagilecoder.wordpress.com/2014/07/07/wcf-and-cors-no-access-control-allow-origin-header-is-present-on-the-requested-resource/

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.

Share:
42,053
mike_hornbeck
Author by

mike_hornbeck

Updated on March 09, 2021

Comments

  • mike_hornbeck
    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
    mike_hornbeck over 11 years
    That'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
    carlosfigueira over 11 years
    The 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
    mike_hornbeck over 11 years
    I'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
    carlosfigueira over 11 years
    Yes - 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
    mike_hornbeck over 11 years
    I'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
    carlosfigueira over 11 years
    It 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
    mike_hornbeck over 11 years
    Ok, it was enough to just assign each property from the json to a new argument for the operation.
  • Vikrant
    Vikrant about 9 years
    Thanks a lot! finally got the exact solution, after searching a lot.
  • Jav T
    Jav T about 9 years
    Great this finally worked after a couple of hours researching. Thanks bru!
  • khichar.anil
    khichar.anil about 8 years
    You saved my lot of R&D hours. I really wanted to vote up more than one time :)..Thank you
  • FranP
    FranP over 6 years
    Worked perfect for me!
  • Itération 122442
    Itération 122442 almost 6 years
    As usual: What are the namespaces used? Please be specific, because my VS does not find it itslef.
  • Robert
    Robert over 5 years
    namespace: System.Web
  • ni3.net
    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.