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:
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).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>
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>
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) {
});
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>