web-dev-qa-db-fra.com

Comment ajouter une prise en charge interdomaine au service WCF

J'essaie d'autoriser POST les demandes de mon application javascript hébergée sur localhost: 80 vers un service WCF hébergé sur un port différent, mais cela ne fonctionne pas. J'ai essayé d'ajouter des propriétés personnalisées à l'en-tête, ainsi que de l'ajouter par programme dans la méthode JSONData de mon service, mais je reçois toujours «405 Method not allowed» dans ma réponse. Quelle est la bonne approche ici? 

Ceci est mon 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
    }
}

et le code de service:

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

Et enfin la 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>
18
mike_hornbeck

Cela a fonctionné mieux pour moi que la version Web.config:

Créer un Global.asax

Ajoutez cette méthode au 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();
            }
        }
    }
}

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

26
Akira Yamamoto

Ajoutez ces nœuds à votre 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>

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

11
Akira Yamamoto

Activer CORS pour les requêtes non-GET nécessite plus que la définition de l'en-tête Access-Control-Allow-Origin - il doit également gérer les requêtes preflight, qui sont des requêtes OPTIONS qui demandent au serveur s'il est sûr d'effectuer des opérations susceptibles de modifier des données , POST, PUT, DELETE) avant l’envoi de la demande réelle.

J'ai écrit un article de blog sur l'ajout de la prise en charge de la CORS pour WCF. Ce n'est pas la plus simple des implémentations, mais j'espère que le code de l'article pourra être simplement copié/collé dans votre projet. Le message peut être trouvé à http://blogs.msdn.com/b/carlosfigueira/archive/2012/05/15/implementing-cors-support-in-wcf.aspx .

9
carlosfigueira

Le code .NET suivant (global.asax) présente une différence importante au lieu de *, il peut être préférable de renvoyer en écho le domaine Origin car cela permet une authentification sur CORS (par exemple, NTLM/Kerberos) ainsi que sur le contrôle en amont. 

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" , "*");
    }
}
0
QA Collective