2012-12-26 7 views
15

Próbuję zezwolić na żądania POST z mojej aplikacji javascript hostowanej na localhost: 80 do usługi WCT REStful hostowanej na innym porcie, ale jakoś to nie działa. Próbowałem dodawać niestandardowe właściwości do nagłówka, a także dodawać go programowo w metodzie mojej usługi JSONData, ale wciąż otrzymuję w odpowiedzi "Metoda niedozwolona 405". Jakie jest właściwe podejście?Jak dodać obsługę wielu domen do usługi WCF

To mój interfejs:

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 
    } 
} 

i kod serwisowy:

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

I wreszcie 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> 
+0

Bardzo dobrze byłoby opisać, co oznacza "ale jakoś to nie działa". –

+0

Zaktualizowałem opis. –

Odpowiedz

17

Ten pracował dla mnie lepiej niż wersja Web.config:

Tworzenie Global.asax

Dodaj ten kod do t on Global.asax.cs:

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

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

+0

Fajnie, dziękuję, że wciąż tu jesteś! –

+0

Wielkie dzięki! wreszcie dostałem dokładne rozwiązanie, po wielu poszukiwaniach. – Vikrant

+0

Wspaniale to w końcu zadziałało po kilku godzinach badań. Dzięki, Bru! –

7

Włączenie CORS dla non-GET żądania wymaga więcej niż wystarczy ustawić nagłówek Access-Control-Allow-Origin - musi on również zajmować się preflight żądań, które są żądaniami, które pytają serwer, czy można bezpiecznie wykonywać operacje, które mogą potencjalnie zmienić dane (np. POST, PUT, DELETE) zanim faktyczne żądanie zostanie wysłane.

Napisałem post na blogu o dodaniu obsługi CORS dla WCF. To nie jest najprostsza z implementacji, ale mam nadzieję, że kod w poście można po prostu skopiować/wkleić do projektu. Post można znaleźć pod adresem http://blogs.msdn.com/b/carlosfigueira/archive/2012/05/15/implementing-cors-support-in-wcf.aspx.

+0

To prawie to, czego potrzebuję. Ale zauważyłem, że to nie działa, jeśli przesyłasz dane jako json. Twoja strona exabple wysyła pojedynczą wartość ciągu z żądaniem POST. A może dlatego, że ExtJS obsługuje dane żądania inaczej niż jQuery:/ –

+0

Przykład wysyła dane jako JSON - dane wejściowe do metod POST/PUT są * ciągami JSON * (zauważ, że dane wejściowe są zawijane w '' '') Działa również dla obiektów, po prostu w przykładzie operacja przyjmuje ciąg jako parametr – carlosfigueira

+0

Zmieniłem dane na stronie testowej na 'var data = { foo:" bar " };' i dostaję 400 Złych żądań. Sprawdziłem dzienniki, ale nic nie jest pomocne, więc czy powinienem wprowadzić zmiany również w samym WCF, aby je obsłużyć? –

4

UPDATE:

Dodaj te węzły do ​​Twojej 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> 

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

+0

Pracowałem idealnie dla mnie! – FranP

0

następujący kod .NET (Global.asax) posiada ważną różnicą, że zamiast *, może lepiej byłoby echo domenę pochodzenia, ponieważ pozwala to na uwierzytelnienie CORS (np NTLM/Kerberos), a także Preflight.

void Application_BeginRequest(object sender, EventArgs e) 
{ 
    if (Request.HttpMethod == "OPTIONS") 
    { 
     Response.AddHeader("Access-Control-Allow-Methods", "GET, POST"); 
     Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept"); 
     Response.AddHeader("Access-Control-Max-Age", "1728000"); 
     Response.End(); 
    } 
    else 
    { 
     Response.AddHeader("Access-Control-Allow-Credentials", "true"); 

     if (Request.Headers["Origin"] != null) 
      Response.AddHeader("Access-Control-Allow-Origin" , Request.Headers["Origin"]); 
     else 
      Response.AddHeader("Access-Control-Allow-Origin" , "*"); 
    } 
}