J'envoie une demande de publication à une application de service RESTFUL WCF. Je peux envoyer avec succès une demande POST
par Fiddler.
Cependant, lorsque je le fais par le biais de la méthode jQuery Ajax, la fonction retourne ce qui suit à la Chrome Developer Console:
OPTIONS http://www.example.com/testservice/service1.svc/GetData 405 (Method Not Allowed) jquery.min.js:6
Mais alors une seconde après les logs:
Object {d: "You entered 10"} testpost.html:16
Cela me dit que jQuery envoie une requête OPTIONS
, qui échoue, puis envoie une requête POST
qui renvoie les données attendues.
Mon code jQuery:
$.ajax() {
type: "POST", //GET or POST or PUT or DELETE verb
url: "http://www.example.com/testservice/service1.svc/GetData", // Location of the service
data: '{"value":"10"}', //Data sent to server
contentType:"application/json",
dataType: "json", //Expected data format from server
processdata: false,
success: function (msg) {//On Successfull service call
console.log(msg);
},
error: function (xhr) { console.log(xhr.responseText); } // When Service call fails
});
J'utilise jQuery version 2.0.2.
Toute aide sur la raison de cette erreur serait une aide précieuse.
Votre code tente en réalité de faire une demande interdomaine (CORS), et non pas un POST
ordinaire .
C'est-à-dire que les navigateurs modernes n'autorisent les appels Ajax aux services du même domaine que la page HTML.
Exemple: Une page en http://www.example.com/myPage.html
ne peut demander directement que des services qui se trouvent dans http://www.example.com
, comme http://www.example.com/testservice/etc
. Si le service est dans un autre domaine, le navigateur ne passe pas l'appel direct (comme vous le pensiez). Au lieu de cela, il essaiera de faire une demande CORS.
En bref, pour effectuer une demande CORS, votre navigateur:
OPTION
à l'URL cibleOPTION
contient les en-têtes adéquats (Access-Control-Allow-Origin
_ est l’un d’eux) pour autoriser la requête CORS, la navigation effectuera l’appel (presque exactement comme si la page HTML était dans le même domaine). Comment le résoudre? Le moyen le plus simple consiste à activer CORS (activer les en-têtes nécessaires) sur le serveur.
Si vous ne disposez pas d'un accès côté serveur, vous pouvez mettre en miroir le service Web ailleurs, puis activer CORS.
Vous devez ajouter ce code dans global.aspx:
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("Cache-Control", "no-cache");
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();
}
}
Vous pouvez également créer les en-têtes requis dans un filtre.
@WebFilter(urlPatterns="/rest/*")
public class AllowAccessFilter implements Filter {
@Override
public void doFilter(ServletRequest sRequest, ServletResponse sResponse, FilterChain chain) throws IOException, ServletException {
System.out.println("in AllowAccessFilter.doFilter");
HttpServletRequest request = (HttpServletRequest)sRequest;
HttpServletResponse response = (HttpServletResponse)sResponse;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT");
response.setHeader("Access-Control-Allow-Headers", "Content-Type");
chain.doFilter(request, response);
}
...
}