web-dev-qa-db-fra.com

Jquery - Comment faire en sorte que $ .post () utilise contentType = application / json?

J'ai remarqué que lorsque $ .post () est utilisé dans jQuery, le type de contenu par défaut est application/x-www-form-urlencoded - lorsque mon code asp.net mvc doit contenir contentType = application/json.

(Voir cette question pour savoir pourquoi je dois utiliser application/json: ASPNET MVC - Pourquoi ModelState.IsValid est-il faux "Le champ x est requis" lorsque ce champ a une valeur? )

Comment faire en sorte que $ .post () envoie contentType = application/json? J'ai déjà un grand nombre de fonctions $ .post (), donc je ne veux pas passer à $ .ajax () car cela prendrait trop de temps

Si j'essaye

$.post(url, data, function(), "json") 

Il a toujours contentType = application/x-www-form-urlencoded. Alors, que fait exactement le paramètre "json" s'il ne change pas le type de contenu en json?

Si j'essaye

$.ajaxSetup({
  contentType: "application/json; charset=utf-8"
});

Cela fonctionne mais affecte chacun des $ .get et des $ .post que j'ai et provoque la cassure de certains.

Donc, est-il possible de modifier le comportement de $ .post () pour envoyer contentType = application/json?

284
JK.

Je pense que vous devrez peut-être

1. Modifiez la source pour que $ .post utilise toujours le type de données JSON car il s’agit en réalité d’un raccourci pour un appel pré-configuré $.ajax

Ou

2. Définissez votre propre fonction utilitaire qui est un raccourci pour la configuration $.ajax que vous souhaitez utiliser

Ou

3.Vous pouvez écraser le $.post function avec votre propre implémentation via un patch de singe.

Le type de données JSON dans votre exemple fait référence au type de données renvoyé par le serveur et non au format envoyé au serveur.

67
Russ Cam
$.ajax({
  url:url,
  type:"POST",
  data:data,
  contentType:"application/json; charset=utf-8",
  dataType:"json",
  success: function(){
    ...
  }
})

Voir: jQuery.ajax ()

371
Adrien

Finalement j'ai trouvé la solution, ça marche pour moi:

jQuery.ajax ({
    url: myurl,
    type: "POST",
    data: JSON.stringify({data:"test"}),
    dataType: "json",
    contentType: "application/json; charset=utf-8",
    success: function(){
        //
    }
});
79
vvkatwss vvkatwss

J'ai fini par ajouter la méthode suivante à jQuery dans mon script:

jQuery["postJSON"] = function( url, data, callback ) {
    // shift arguments if data argument was omitted
    if ( jQuery.isFunction( data ) ) {
        callback = data;
        data = undefined;
    }

    return jQuery.ajax({
        url: url,
        type: "POST",
        contentType:"application/json; charset=utf-8",
        dataType: "json",
        data: data,
        success: callback
    });
};

Et pour l'utiliser

$.postJSON('http://url', {data: 'goes', here: 'yey'}, function (data, status, xhr) {
    alert('Nailed it!')
});

Cela a été fait en copiant simplement le code "get" et "post" à partir des sources JQuery d'origine et en codant en dur quelques paramètres pour forcer un POST JSON.

Merci!

41
kontinuity

juste utiliser

jQuery.ajax ({
    url: myurl,
    type: "POST",
    data: mydata,
    dataType: "json",
    contentType: "application/json; charset=utf-8",
    success: function(){
        //
    }
});

UPDATED @JK: Si vous écrivez uniquement dans votre question n exemple de code avec $ .post, vous trouvez un exemple correspondant dans la réponse. Je ne veux pas répéter les mêmes informations que vous avez déjà étudiées jusqu'à ce que vous sachiez: $ .post et $ .get sont des formes abrégées de $ .ajax. Il suffit donc d’utiliser $ .ajax pour pouvoir utiliser l’ensemble complet de ses paramètres sans modifier aucun paramètre global.

En passant, je ne recommanderais pas de remplacer le .post standard $. C'est mon opinion personnelle , mais pour moi, il est important que le programme fonctionne non seulement, mais que tous ceux qui le lisent le comprennent de la même manière. . Remplacer les méthodes standard sans avoir une raison très importante peut suivre jusqu'à incompréhension en lecture du code du programme. Je répète donc ma recommandation une fois de plus: utilisez simplement le formulaire original $ .ajax jQuery au lieu de jQuery.get et jQuery.post et vous recevez des programmes qui fonctionnent parfaitement, mais qui peuvent être lus sans aucune incompréhension. .

20
Oleg

Le type de données "json" que vous pouvez transmettre en tant que dernier paramètre de post () indique le type de données attendu par la fonction dans la réponse du serveur, et non le type qu'il envoie dans la demande. Plus précisément, il définit l'en-tête "Accepter".

Honnêtement, votre meilleur choix est de passer à un appel ajax (). La fonction post () est conçue comme une commodité; une version simplifiée de l’appel ajax () lorsque vous écrivez simplement un formulaire. Vous n'êtes pas.

Si vous ne voulez vraiment pas changer, vous pouvez créer votre propre fonction appelée, disons, xpost (), et lui demander simplement de transformer les paramètres donnés en paramètres pour un appel jQuery ajax (), avec le type de contenu défini. De cette façon, plutôt que de réécrire toutes ces fonctions post () en fonctions ajax (), il vous suffit de toutes les changer de post en xpost (ou autre).

8
Jacob Mattison

Je sais que c'est une réponse tardive, j'ai en fait une méthode de raccourci que j'utilise pour poster/lire vers/à partir de services basés sur MS .. cela fonctionne avec MVC ainsi qu'avec ASMX, etc.

Utilisation:

$.msajax(
  '/services/someservice.asmx/SomeMethod'
  ,{}  /*empty object for nothing, or object to send as Application/JSON */
  ,function(data,jqXHR) {
    //use the data from the response.
  }
  ,function(err,jqXHR) {
    //additional error handling.
  }
);
//sends a json request to an ASMX or WCF service configured to reply to JSON requests.
(function ($) {
  var tries = 0; //IE9 seems to error out the first ajax call sometimes... will retry up to 5 times

  $.msajax = function (url, data, onSuccess, onError) {
    return $.ajax({
      'type': "POST"
      , 'url': url
      , 'contentType': "application/json"
      , 'dataType': "json"
      , 'data': typeof data == "string" ? data : JSON.stringify(data || {})
      ,beforeSend: function(jqXHR) {
        jqXHR.setRequestHeader("X-MicrosoftAjax","Delta=true");
      }
      , 'complete': function(jqXHR, textStatus) {
        handleResponse(jqXHR, textStatus, onSuccess, onError, function(){
          setTimeout(function(){
            $.msajax(url, data, onSuccess, onError);
          }, 100 * tries); //try again
        });
      }
    });
  }

  $.msajax.defaultErrorMessage = "Error retreiving data.";


  function logError(err, errorHandler, jqXHR) {
    tries = 0; //reset counter - handling error response

    //normalize error message
    if (typeof err == "string") err = { 'Message': err };

    if (console && console.debug && console.dir) {
      console.debug("ERROR processing jQuery.msajax request.");
      console.dir({ 'details': { 'error': err, 'jqXHR':jqXHR } });
    }

    try {
      errorHandler(err, jqXHR);
    } catch (e) {}
    return;
  }


  function handleResponse(jqXHR, textStatus, onSuccess, onError, onRetry) {
    var ret = null;
    var reterr = null;
    try {
      //error from jqXHR
      if (textStatus == "error") {
        var errmsg = $.msajax.defaultErrorMessage || "Error retreiving data.";

        //check for error response from the server
        if (jqXHR.status >= 300 && jqXHR.status < 600) {
          return logError( jqXHR.statusText || msg, onError, jqXHR);
        }

        if (tries++ < 5) return onRetry();

        return logError( msg, onError, jqXHR);
      }

      //not an error response, reset try counter
      tries = 0;

      //check for a redirect from server (usually authentication token expiration).
      if (jqXHR.responseText.indexOf("|pageRedirect||") > 0) {
        location.href = decodeURIComponent(jqXHR.responseText.split("|pageRedirect||")[1].split("|")[0]).split('?')[0];
        return;
      }

      //parse response using ajax enabled parser (if available)
      ret = ((JSON && JSON.parseAjax) || $.parseJSON)(jqXHR.responseText);

      //invalid response
      if (!ret) throw jqXHR.responseText;  

      // d property wrap as of .Net 3.5
      if (ret.d) ret = ret.d;

      //has an error
      reterr = (ret && (ret.error || ret.Error)) || null; //specifically returned an "error"

      if (ret && ret.ExceptionType) { //Microsoft Webservice Exception Response
        reterr = ret
      }

    } catch (err) {
      reterr = {
        'Message': $.msajax.defaultErrorMessage || "Error retreiving data."
        ,'debug': err
      }
    }

    //perform final logic outside try/catch, was catching error in onSuccess/onError callbacks
    if (reterr) {
      logError(reterr, onError, jqXHR);
      return;
    }

    onSuccess(ret, jqXHR);
  }

} (jQuery));

REMARQUE: j'ai également une méthode JSON.parseAjax modifiée à partir du fichier JS de json.org, qui ajoute la gestion des dates MS "/Date(...)/" ...

Le fichier json2.js modifié n'est pas inclus, il utilise l'analyseur basé sur un script dans le cas d'IE8, car il existe des cas où l'analyseur natif se rompt lorsque vous étendez le prototype de tableau et/ou d'objet, etc.

J'ai envisagé de réorganiser ce code pour implémenter les interfaces promesses, mais cela a très bien fonctionné pour moi.

5
Tracker1

Au cœur du problème se trouve le fait que JQuery au moment de la rédaction n’a pas de méthode postJSON alors que getJSON existe et fait ce qui est juste.

une méthode postJSON ferait ce qui suit:

postJSON = function(url,data){
    return $.ajax({url:url,data:JSON.stringify(data),type:'POST', contentType:'application/json'});
};

et peut être utilisé comme ceci:

postJSON( 'path/to/server', my_JS_Object_or_Array )
    .done(function (data) {
        //do something useful with server returned data
        console.log(data);
    })
    .fail(function (response, status) {
        //handle error response
    })
    .always(function(){  
      //do something useful in either case
      //like remove the spinner
    });
4
dbrin

Cette extension de l'API jQuery simple (à partir de: https://benjamin-schweizer.de/jquerypostjson.html ) pour $ .postJSON () fait l'affaire. Vous pouvez utiliser postJSON () comme tout autre appel natif jquery Ajax. Vous pouvez attacher des gestionnaires d’événements, etc.

$.postJSON = function(url, data, callback) {
  return jQuery.ajax({
    'type': 'POST',
    'url': url,
    'contentType': 'application/json; charset=utf-8',
    'data': JSON.stringify(data),
    'dataType': 'json',
    'success': callback
  });
};

Comme d'autres API Ajax (comme $ http de AngularJS), il définit le contentType correct sur application/json. Vous pouvez transmettre vos données json (objets javascript) directement, car elles sont ici stringifiées. Le type de données attendu attendu est défini sur JSON. Vous pouvez attacher les gestionnaires d’événements par défaut de jquery pour les promesses, par exemple:

$.postJSON(apiURL, jsonData)
 .fail(function(res) {
   console.error(res.responseText);
 })
 .always(function() {
   console.log("FINISHED ajax post, hide the loading throbber");
 });
2
Ruwen

La documentation indique actuellement qu’à partir de la version 3.0, $ .post acceptera l’objet settings, ce qui signifie que vous pourrez utiliser les options $ .ajax. 3.0 n'est pas encore sorti et sur le commit il est question de cacher la référence à cette référence dans la documentation, mais cherchez-la dans le futur!

1
Ben Creasy

J'ai eu un problème similaire avec le code JavaScript suivant:

var url = 'http://my-Host-name.com/api/Rating';

var rating = { 
  value: 5,
  maxValue: 10
};

$.post(url, JSON.stringify(rating), showSavedNotification);

Où dans le Fiddler je pouvais voir la requête avec:

  • En-tête: Content-Type: application/x-www-form-urlencoded; charset=UTF-8
  • Corps: {"value":"5","maxValue":"5"}

En conséquence, mon serveur n'a pas pu mapper un objet sur un type côté serveur.

Après avoir changé la dernière ligne à celle-ci:

$.post(url, rating, showSavedNotification);

Dans le Fiddler, je pouvais encore voir:

  • En-tête: Content-Type: application/x-www-form-urlencoded; charset=UTF-8
  • Corps: value=5&maxValue=10

Cependant, le serveur a commencé à retourner ce que je pensais.

1
Oleg Burov

Que diriez-vous de votre propre adaptateur/wrapper?

//adapter.js
var adapter = (function() {

return {

    post: function (url, params) {
        adapter.ajax(url, "post", params);
        },
    get: function (url, params) {
        adapter.ajax(url, "get", params);
    },
    put: function (url, params) {
        adapter.ajax(url, "put", params);
    },
    delete: function (url, params) {
        adapter.ajax(url, "delete", params);
    },
    ajax: function (url, type, params) {
        var ajaxOptions = {
            type: type.toUpperCase(),
            url: url,
            success: function (data, status) {
                var msgType = "";
                // checkStatus here if you haven't include data.success = true in your
                // response object
                if ((params.checkStatus && status) || 
                   (data.success && data.success == true)) {
                            msgType = "success";
                            params.onSuccess && params.onSuccess(data);
                    } else {
                            msgType = "danger";
                            params.onError && params.onError(data);
                    }
            },
            error: function (xhr) {
                    params.onXHRError && params.onXHRError();
                    //api.showNotificationWindow(xhr.statusText, "danger");
            }
        };
        if (params.data) ajaxOptions.data = params.data;
        if (api.isJSON(params.data)) {
            ajaxOptions.contentType = "application/json; charset=utf-8";
            ajaxOptions.dataType = "json";
        }
        $.ajax($.extend(ajaxOptions, params.options));
    }
})();

    //api.js
var api = {
  return {
    isJSON: function (json) {
        try {
            var o = JSON.parse(json);
            if (o && typeof o === "object" && o !== null) return true;
        } catch (e) {}
        return false;
    }
  }
})();

Et une utilisation extrêmement simple:

adapter.post("where/to/go", {
    data: JSON.stringify(params),
    onSuccess: function (data) {
        //on success response...
    }
    //, onError: function(data) {  //on error response... }
    //, onXHRError: function(xhr) {  //on XHR error response... }
});
0
Blackening

Pour une raison quelconque, définir le type de contenu sur la demande ajax comme @Adrien l'avait suggéré ne fonctionnait pas dans mon cas. Cependant, vous pouvez réellement changer le type de contenu en utilisant $ .post en procédant ainsi:

$.ajaxSetup({
    'beforeSend' : function(xhr) {
        xhr.overrideMimeType('application/json; charset=utf-8');
    },
});

Ensuite, appelez votre $.post:

$.post(url, data, function(), "json")

J'ai eu des problèmes avec jQuery + IIS, et c'était la seule solution qui a aidé jQuery à comprendre l'utilisation du codage Windows-1252 pour les demandes ajax.

0
Johannes