web-dev-qa-db-fra.com

Impossible de définir le type de contenu sur 'application/json' dans jQuery.ajax

Quand j'ai ce code

$.ajax({
    type: 'POST',
    //contentType: "application/json",
    url: 'http://localhost:16329/Hello',
    data: { name: 'norm' },
    dataType: 'json'
});

dans Fiddler, je peux voir la requête brute suivante

POST http://localhost:16329/Hello HTTP/1.1
Host: localhost:16329
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://localhost:14693/WebSite1/index.html
Content-Length: 9
Origin: http://localhost:14693
Pragma: no-cache
Cache-Control: no-cache

name=norm

Mais ce que j'essaie, c'est de définir le type de contenu de application/x-www-form-urlencoded à application/json . Mais ce code

$.ajax({
    type: "POST",
    contentType: "application/json",
    url: 'http://localhost:16329/Hello',
    data: { name: 'norm' },
    dataType: "json"
});

Génère une requête étrange (que je peux voir dans Fiddler)

OPTIONS http://localhost:16329/Hello HTTP/1.1
Host: localhost:16329
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Origin: http://localhost:14693
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Pragma: no-cache
Cache-Control: no-cache

Pourquoi donc? Que sont les options quand il devrait y avoir POST ici? Et où mon type de contenu est-il défini sur application/json? Et les paramètres de demande ont disparu pour une raison quelconque.

MISE À JOUR 1

Du côté du serveur, j'ai un service RESTful très simple.

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class RestfulService : IRestfulService
{
    [WebInvoke(
        Method = "POST",
        UriTemplate = "Hello",
        ResponseFormat = WebMessageFormat.Json)]
    public string HelloWorld(string name)
    {
        return "hello, " + name;
    }
}

Mais pour une raison quelconque, je ne peux pas appeler cette méthode avec des paramètres.

MISE À JOUR 2

Désolé de ne pas répondre si longtemps. 

J'ai ajouté ces en-têtes à la réponse de mon serveur

 Access-Control-Allow-Origin: *
 Access-Control-Allow-Headers: Content-Type
 Access-Control-Allow-Methods: POST, GET, OPTIONS

Cela n'a pas aidé, j'ai Méthode non autorisée erreur du serveur.

Voici ce que dit mon violoniste

enter image description here

Donc, je peux maintenant être sûr que mon serveur accepte POST, GET, OPTIONS (si les en-têtes de réponse fonctionnent comme prévu). Mais pourquoi "Méthode non autorisée"?

Dans WebView, la réponse du serveur (vous pouvez voir la réponse de Raw sur l'image ci-dessus) ressemble à ceci

enter image description here

83
Vitalii Korsakov

Il semblerait que la suppression de http:// de l'option url garantisse que l'en-tête HTTP POST correct est envoyé.

Je ne pense pas que vous ayez besoin de qualifier complètement le nom de l'hôte, utilisez simplement une URL relative comme ci-dessous.

   $.ajax({
      type: "POST",
      contentType: "application/json",
      url: '/Hello',
      data: { name: 'norm' },
      dataType: "json"
   });

Un exemple de moi qui fonctionne:

        $.ajax({
            type: "POST",
            url: siteRoot + "api/SpaceGame/AddPlayer",
            async: false,
            data: JSON.stringify({ Name: playersShip.name, Credits: playersShip.credits }),
            contentType: "application/json",
            complete: function (data) {
            console.log(data);
            wait = false;
        }
    });

Peut-être liée: jQuery $ .ajax (), $ .post envoyant "OPTIONS" comme REQUEST_METHOD dans Firefox

Edit: Après quelques recherches supplémentaires, j'ai découvert que l'en-tête OPTIONS est utilisé pour déterminer si la requête du domaine d'origine est autorisée. En utilisant fiddler, j’ai ajouté ce qui suit aux en-têtes de réponse de mon serveur.

 Access-Control-Allow-Origin: *
 Access-Control-Allow-Headers: Content-Type
 Access-Control-Allow-Methods: POST, GET, OPTIONS

Une fois que le navigateur a reçu cette réponse, il a ensuite envoyé la bonne demande POST avec les données JSON. Il semblerait que le type de contenu par défaut basé sur un code de formulaire soit considéré comme sûr et ne soit donc pas soumis aux vérifications supplémentaires entre domaines.

Il semble que vous deviez ajouter les en-têtes mentionnés précédemment à la réponse de votre serveur à la demande OPTIONS. Vous devez bien sûr les configurer pour autoriser les demandes de domaines spécifiques plutôt que de tous.

J'ai utilisé le jQuery suivant pour tester cela.

$.ajax({
   type: "POST",
   url: "http://myDomain.com/path/AddPlayer",
   data: JSON.stringify({
      Name: "Test",
       Credits: 0
   }),
   //contentType: "application/json",
   dataType: 'json',
   complete: function(data) {
       $("content").html(data);
  }
});​

Références:

75
Mike Wade

Je peux vous montrer comment je l'ai utilisé 

  function GetDenierValue() {
        var denierid = $("#productDenierid").val() == '' ? 0 : $("#productDenierid").val();
        var param = { 'productDenierid': denierid };
        $.ajax({
            url: "/Admin/ProductComposition/GetDenierValue",
            dataType: "json",
            contentType: "application/json;charset=utf-8",
            type: "POST",
            data: JSON.stringify(param),
            success: function (msg) {
                if (msg != null) {
                    return msg.URL;
                }
            }
        });
    }
31
Amritpal Singh

Donc, tout ce que vous avez à faire pour que cela fonctionne est d’ajouter:

headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json'
}

comme un champ à votre demande de poste et ça va marcher.

9
Cody Jacques

J'ai reconnu ces écrans, j'utilise CodeFluentEntities et j'ai une solution qui fonctionne aussi pour moi.

J'utilise cette construction:

$.ajax({
   url: path,
   type: "POST",
   contentType: "text/plain",
   data: {"some":"some"}
}

comme vous pouvez le voir, si j'utilise 

contentType: "",

ou

contentType: "text/plain", //chrome

Tout fonctionne bien.

Je ne suis pas sûr à 100% que c'est tout ce dont vous avez besoin, car j'ai également modifié les en-têtes. 

4
Alexey Avdeyev

J'ai trouvé la solution à ce problème ici . N'oubliez pas d'autoriser les OPTIONS de verbe sur le gestionnaire de service d'application IIS. 

Fonctionne bien. Merci André Pedroso. :-)

2
Fanda

Si vous utilisez ceci:

contentType: "application/json"

AJAX n'enverra pas les paramètres GET ou POST au serveur .... ne sais pas pourquoi.

Cela m'a pris des heures pour l'apprendre aujourd'hui.

Juste utiliser:

$.ajax(
  { url : 'http://blabla.com/wsGetReport.php',
    data : myFormData, type : 'POST', dataType : 'json', 
    // contentType: "application/json", 
    success : function(wsQuery) { }
  }
)

J'ai eu le même problème. J'exécute une application de repos Java sur un serveur jboss. Mais je pense que la solution est similaire sur un ASP .NET webapp.

Firefox appelle préalablement votre URL serveur/reste pour vérifier quelles options sont autorisées. C’est la requête "OPTIONS" à laquelle votre serveur ne répond pas en conséquence. Si cet appel OPTIONS est répondu correctement, un deuxième appel est exécuté, qui correspond à la demande "POST" réelle avec un contenu json.

Cela se produit uniquement lors d'un appel entre domaines. Dans votre cas, appeler 'http://localhost:16329/Hello' au lieu d'appeler un chemin d'URL sous le même domaine '/ Hello'

Si vous souhaitez effectuer un appel entre domaines, vous devez améliorer votre classe de service de repos avec une méthode annotée, qui prend en charge une requête http "OPTIONS". Voici l'implémentation Java correspondante:

@Path("/rest")
public class RestfulService {

    @POST
    @Path("/Hello")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.TEXT_PLAIN)
    public string HelloWorld(string name)
    {
        return "hello, " + name;
    }

//THIS NEEDS TO BE ADDED ADDITIONALLY IF MAKING CROSS-DOMAIN CALLS

    @OPTIONS
    @Path("/Hello")
    @Produces(MediaType.TEXT_PLAIN+ ";charset=utf-8")
    public Response checkOptions(){
        return Response.status(200)
        .header("Access-Control-Allow-Origin", "*")
        .header("Access-Control-Allow-Headers", "Content-Type")
        .header("Access-Control-Allow-Methods", "POST, OPTIONS") //CAN BE ENHANCED WITH OTHER HTTP CALL METHODS 
        .build();
    }
}

Donc, je suppose que dans .NET, vous devez ajouter une méthode supplémentaire annotée avec

[WebInvoke(
        Method = "OPTIONS",
        UriTemplate = "Hello",
        ResponseFormat = WebMessageFormat.)]

où les en-têtes suivants sont définis

.header("Access-Control-Allow-Origin", "*")
        .header("Access-Control-Allow-Headers", "Content-Type")
        .header("Access-Control-Allow-Methods", "POST, OPTIONS")
1
Vincent

J'ai eu la solution pour envoyer les données JSON par POST demande via jquery ajax. J'ai utilisé le code ci-dessous

    var data = new Object();
    data.p_clientId = 4;
    data =  JSON.stringify(data);

    $.ajax({
      method: "POST",
      url: "http://192.168.1.141:8090/api/Client_Add",
      data: data,
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'text/plain'
    }
    })
      .done(function( msg ) {
        alert( "Data Saved: " + msg );
      });


        });
    });

J'ai utilisé 'Content-Type': 'text/plain' dans l'en-tête pour envoyer les données brutes JSON.
Parce que si nous utilisons Content-Type: 'application/json', les méthodes de requête converties en OPTION, mais en utilisant Content-Type: 'test/plain', la méthode n'est pas convertie et reste en POST . J'espère que cela aidera quelqu'un.

0
Rahul Aparajit