Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
250 views
in Technique[技术] by (71.8m points)

c# - WCF REST Service Template 40(CS) Cross domain error

Hi I have a WCF Rest service using ( WCF REST Service Template 40(CS)). I have managed to get it to return Json response. It is working fine when the project is run. But when I try to make a Ajaxcall to the service from the browser, I am getting Error:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://192.168.0.70:8001/Service/test. This can be fixed by moving the resource to the same domain or enabling CORS.

And The Ajax call:

$.ajax({
        type: "POST",
        url: "http://192.168.0.70:8001/Service/test",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        async: true,
        cache: false,
        success: function (msg) {
        var Tabels = msg.d;
        alert('success');
        }
    });

Here is the web.config:

    <?xml version="1.0"?>
    <configuration>
      <connectionStrings>

        <add name="ConString" connectionString="SERVER=localhost;DATABASE=fabapp;UID=root;PASSWORD=;"/>
      </connectionStrings>
      <system.web>
        <compilation debug="true" targetFramework="4.0" />
      </system.web>

      <system.webServer>
<httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
      </customHeaders>
    </httpProtocol>
        <modules runAllManagedModulesForAllRequests="true">
          <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
        </modules>
      </system.webServer>
      <system.serviceModel>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
        <standardEndpoints>
          <webHttpEndpoint>
            <!-- 
                Configure the WCF REST service base address via the global.asax.cs file and the default endpoint 
                via the attributes on the <standardEndpoint> element below
            -->
            <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="false" defaultOutgoingResponseFormat="Json"/>
          </webHttpEndpoint>
        </standardEndpoints>
      </system.serviceModel>

    </configuration>

I tried adding crossDomainScriptAccessEnabled="true" but when I do that the service does not work on the localhost also. I get this:

Cross domain javascript callback is not supported in authenticated services.

Anything I need to change in web.config file?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Practically speaking , i had faced this issue, i have gone one step further to check WebAPI, and same effort was required, when i analysed. So i had to fix this CORS with WCF. I will try to explain in short. Here we go. When you access WCF request with CrossOrigin, like from JS code existing in different domain, and from JS , you try to do PUT or POST request, 1st browser sends an OPTION request 405 HTTP Status, to see if this domain is in allowed list, then if your WCF respond to OPTIONS request, sends required response with header value, then browser will again do a POST or PUT request ( which ever browser issued earlier), and it will work as expected.

NOTE: you can not send ("Access-Control-Allow-Origin", "*"), because, there is a security feature , that mandates required domain name to be listed in Access-Control-Allow-Origin instead of *.

For more info -

http://social.msdn.microsoft.com/Forums/ro-RO/5613de55-2573-49ca-a389-abacb39e4f8c/wcf-rest-service-post-cross-domain-not-working?forum=wcf

https://stackoverflow.com/questions/26163802/wcf-cors-request-from-jquery-not-working

From practical experience, i have tried * in that header, it was not working. If you don't believe me, go ahead and try .

Finally the code is following. You need to put this in Global.asax.

protected void Application_BeginRequest(object sender, EventArgs e)
{
    String domainname = HttpContext.Current.Request.Headers["Origin"].ToString();
    if (IsAllowedDomain(domainname))
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", domainname);
    String allowedmethods =  "POST, PUT, DELETE, GET";
    String headers = HttpContext.Current.Request.Headers["Access-Control-Request-Headers"].ToString();
    String accesscontrolmaxage =  "1728000";
    String contenttypeforoptionsrequest = "application/json";


    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", allowedmethods);
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", headers);
        HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", accesscontrolmaxage);
        HttpContext.Current.Response.AddHeader("ContentType", contenttypeforoptionsrequest);
        HttpContext.Current.Response.End();
    }

}
private bool IsAllowedDomain(String Domain)
{
    if (string.IsNullOrEmpty(Domain)) return false;
    string[] alloweddomains = "http://192.168.0.70:8001"; // you can place comma separated domains here.
    foreach (string alloweddomain in alloweddomains)
    {
        if (Domain.ToLower() == alloweddomain.ToLower())
            return true;
    }
    return false;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...