web-dev-qa-db-fra.com

jQuery .ajax () POST Une requête renvoie 405 (méthode non autorisée) sur RESTful WCF

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.

33
Brandon Davis

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:

  • Envoie d'abord une requête OPTION à l'URL cible
  • Et ensuite uniquement si la réponse du serveur à cette OPTION 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).
    • Si les en-têtes attendus ne viennent pas, le navigateur abandonne simplement (comme il vous l'a fait).

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.

61
acdcjunior

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

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);
    }
    ...
}
3
user4227302