web-dev-qa-db-fra.com

Comment appeler un service WCF à partir de javascript?

J'essaie d'appeler un service WCF à partir d'un appel ajax avec jQuery . Je parviens à appeler la WCF à partir de SOAP-UI et d'Excel/VBA . Mon problème provient de la requête OPTIONS envoyée et non POST suit:

  • si je règle l'URL sur http://mywcf/service.svc, OPTIONS est envoyé, le statut 400 Bad Request est obtenu et la demande POST n'est pas envoyée. HTTP/1.1 manque dans l'en-tête (comparaison avec les en-têtes SOAP-UI).
  • si je règle l'URL sur http://mywcf/service.svc HTTP/1.1, OPTIONS est envoyé et j'obtiens un statut 200 OK mais la demande POST n'est pas envoyée. Dans ce cas, HTTP/1.1 semble être interprété comme un nom de fichier.

Quelqu'un peut-il me dire comment appeler une action POST sur une WCF à partir de javascript et ajouter l'en-tête HTTP/1.1 sans corrompre l'URL du service?

Voici un extrait de mon appel ajax:

var soapData = ''
        +'<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:mic="http://Microsoft.wcf.documentation">'
        +'    <soap:Header xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:wsrm="http://docs.oasis-open.org/ws-rx/wsrm/200702">'
        +'        <wsrm:Sequence>'
        +'            <wsrm:Identifier>s:Sender a:ActionNotSupported</wsrm:Identifier>'
        +'            <wsrm:MessageNumber>1</wsrm:MessageNumber>'
        +'        </wsrm:Sequence>'
        +'        <wsa:Action>http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequence</wsa:Action>'
        +'        <wsa:ReplyTo>'
        +'            <wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>'
        +'        </wsa:ReplyTo>'
        +'        <wsa:MessageID>uuid:'+ MsgUid +'</wsa:MessageID>'
        +'        <wsa:To>'+ Url +'</wsa:To>'
        +'    </soap:Header>'
        +'    <soap:Body xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm">'
        +'        <wsrm:CreateSequence>'
        +'            <wsrm:AcksTo xmlns:wsa="http://www.w3.org/2005/08/addressing">'
        +'                <wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>'
        +'            </wsrm:AcksTo>'
        +'            <wsrm:Offer>'
        +'                <wsrm:Identifier>urn:soapui:'+ SeqUid +'</wsrm:Identifier>'
        +'            </wsrm:Offer>'
        +'        </wsrm:CreateSequence>'
        +'    </soap:Body>'
        +'</soap:Envelope>';

$.ajax({
    type: 'POST',
    url: 'http://mywcf/service.svc', // with or without +' HTTP/1.1'
    data: soapData,
    contentType: 'application/soap+xml;charset=UTF-8',
    dataType: 'xml'
});

Valeurs dans mon WCF web.config:

<system.webServer>
    <httpProtocol>
        <customHeaders>
            <add name="Access-Control-Allow-Origin" value="*" />
            <add name="Access-Control-Allow-Methods" value="POST, OPTIONS" />
            <add name="Access-Control-Allow-Headers" value="*" />
        </customHeaders>
    </httpProtocol>
</system.webServer>
6
sinsedrix

Pour utiliser un service Web utilisant jQuery, c’est-à-dire appeler le service WCF, vous devez utiliser jQuery.ajax () ou jQuery.getJSON (). Dans cet article, j'ai utilisé la méthode jQuery.ajax ().

Pour définir la demande, commencez par définir une variable. Cela sera utile lorsque vous appelez plusieurs méthodes et créez un fichier js différent pour appeler le service WCF.

<script type="text/javascript">

    var Type;
    var Url;
    var Data;
    var ContentType;
    var DataType;
    var ProcessData;

La fonction suivante initialise les variables définies ci-dessus pour appeler le service.

function WCFJSON() {
    var userid = "1";
    Type = "POST";
    Url = "Service.svc/GetUser";
    Data = '{"Id": "' + userid + '"}';
    ContentType = "application/json; charset=utf-8";
    DataType = "json"; varProcessData = true; 
    CallService();
}

La fonction CallService envoie des demandes au service en définissant les données dans $ .ajax.

// Function to call WCF  Service       
function CallService() {
    $.ajax({
        type: Type, //GET or POST or PUT or DELETE verb
        url: Url, // Location of the service
        data: Data, //Data sent to server
        contentType: ContentType, // content type sent to server
        dataType: DataType, //Expected data format from server
        processdata: ProcessData, //True or False
        success: function(msg) {//On Successfull service call
            ServiceSucceeded(msg);
        },
        error: ServiceFailed// When Service call fails
    });
}

function ServiceFailed(result) {
    alert('Service call failed: ' + result.status + '' + result.statusText);
    Type = null;
    varUrl = null;
    Data = null; 
    ContentType = null;
    DataType = null;
    ProcessData = null;
}

Remarque: Le code suivant vérifie l'instruction result.GetUserResult afin que votre objet result reçoive la propriété votre nom de méthode de service + Result. Sinon, cela donnera une erreur comme un objet introuvable en Javascript.

function ServiceSucceeded(result) {
    if (DataType == "json") {
        resultObject = result.GetUserResult;

        for (i = 0; i < resultObject.length; i++) {
            alert(resultObject[i]);
        }

    }

}

function ServiceFailed(xhr) {
    alert(xhr.responseText);

    if (xhr.responseText) {
        var err = xhr.responseText;
        if (err)
            error(err);
        else
            error({ Message: "Unknown server error." })
    }

    return;
}

$(document).ready(
    function() {
        WCFJSON();
    }
);
</script>
1
Farhad Bagherlo

Ajouter un point de terminaison webHttpBinding

    <services>
  <service name="Contract">
    <endpoint address="json" binding="webHttpBinding"  contract="IContract" bindingConfiguration="ActionsHttpBinding" behaviorConfiguration="ActionrestfulBehavior"/>
  </service>

appelez ensuite le noeud final depuis ajax en tant que post ou get, voir l'exemple ci-dessous:

    var data = JSON.stringify({
    param1: val1,
    param2: val2
});
$.ajax({
    url: "http://mywcf/service.svc/json/FunctionName",
    type: "POST",
    data: data,
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    processData: true
}).then(function (rsutlt) {

}).fail(function (fail) {
});
1
Ron

Ajoutez le code ci-dessous à votre fichier global.asax.cs et supprimez customHeaders de votre configuration Web.

protected void Application_BeginRequest(object sender, EventArgs e)
    {
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");

        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", "GET, POST, PUT, DELETE");
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
            HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
            HttpContext.Current.Response.End();
        }

    }

Vous devez également supprimer OPTIONSVerbHandler pour activer cors.

 <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
</system.webServer>
0
Mehmet Otkun