Jquery - Come utilizzare $ .post () in contentType = application / json?


309

Ho notato che quando utilizzo $ .post () in jquery il contentType predefinito è application / x-www-form-urlencoded - quando il mio codice mvc asp.net deve avere contentType = application / json

(Vedi questa domanda per perché devo usare application / json: ASPNET MVC - Perché ModelState.IsValid è false "Il campo x è obbligatorio" quando quel campo ha un valore? )

Come posso fare in modo che $ .post () invii contentType = application / json? Ho già un gran numero di funzioni $ .post (), quindi non voglio passare a $ .ajax () perché ci vorrebbe troppo tempo

Se ci provo

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

Ha ancora contentType = application / x-www-form-urlencoded. Quindi cosa fa esattamente il parametro "json" se non cambia il contenttype in json?

Se ci provo

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

Funziona ma influisce su ogni singolo $ .get e $ .post che ho e ne causa la rottura.

Quindi c'è un modo in cui posso cambiare il comportamento di $ .post () per inviare contentType = application / json?

Risposte:


71

Penso che potresti doverlo fare

1.Modifica l'origine per fare in modo che $ .post utilizzi sempre il tipo di dati JSON in quanto è solo una scorciatoia per un preconfigurato $.ajax chiamata

O

2. Definire la propria funzione di utilità che è un collegamento per la $.ajaxconfigurazione che si desidera utilizzare

O

3.Potresti sovrascriverlo $.post functioncon la tua implementazione tramite patch scimmia.

Il tipo di dati JSON nel tuo esempio si riferisce al tipo di dati restituito dal server e non al formato inviato al server.


5
+1, vorrei definire un nuovo metodo o un jQuery.postmetodo di sovrascrittura , è una funzione davvero semplice ...
CMS

3
Non è una cattiva idea, basta creare un metodo chiamato $ .mvcpost () che fa lo stesso di $ .post (copiando il codice collegato) più cambia il tipo di contenuto. Quindi per tutti i $ .post () che devono essere cambiati, devo solo digitare 3 caratteri extra di fronte. È molto più veloce che riscriverli come $ .ajax ().
JK.

9
@PavelRepin, ho dovuto chiamare JSON.stringify () sul payload.
Ustaman Sangat,

2
@dragon: ecco 3 soluzioni per "esiste un modo per modificare il comportamento di $ .post () per inviare contentType = application / json?". Quale parte non è una risposta?
Russ Cam

2
È anche importante sapere: $ .ajax ed i suoi vari metodi tenteranno di indovinare quale dovrebbe essere il contentType (a meno che non sia specificato) in base ai dati che gli dai. "mystring data"sarà application/x-www-form-urlencoded;dove come oggetto { anyKey: "anyvalue and type" }sarà application/json. Molti server che leggono json, consentiranno solo un oggetto o un array, non una stringa, quindi perché jquery predice le cose in questo modo. Se si dispone di un server che legge stringhe, numeri, ecc. Senza essere racchiuso in un oggetto, è necessario specificare il tipo di contenuto come in questa risposta.
bzuillsmith,

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

Vedi: jQuery.ajax ()


13
Il post originale chiede: "Quindi c'è un modo per cambiare il comportamento di $ .post () per inviare contentType = application / json?" MA afferma anche "Funziona ma influisce su ogni singolo $ .get e $ .post che ho e ne causa la rottura.". Comprendo la domanda "come posso ottenere la stessa cosa usando $ .post ma inviando il giusto contentType senza interrompere le altre occorrenze di $ .get e $ .post". È sbagliato?
Adrien,

5
@ x1a4 chiaramente non capisce che .ajax è la chiamata, non ajaxSetup
Walker

39
@Adrien, per quello che vale due anni dopo, la tua è la risposta che stavo cercando quando ho cercato su Google.
AwesomeTown,

74
doveva usare JSON.stringify(data), poiché il server si aspetta una stringa JSON e jQuery semplicemente concatenerebbe le coppie chiave-valore usando e commerciali, codificate in forma.
drago,

3
Anche quattro anni dopo, questa risposta ha risolto le mie ore di ricerca con meno di dieci righe di codice.
Pieter VDE

86

Finalmente ho trovato la soluzione che funziona per me:

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

8
Non riesco a capire perché ho continuato a ricevere errori, risulta che devi stringere i dati.
zastrowm,

5
So che funziona, ma PERCHÉ oh PERCHÉ devi stringere? È un bug di jQuery? Sembra essere perfettamente felice di serializzare il tuo dataargomento x-www-form-urlencoded, ma se indichi che il tipo di contenuto della richiesta è JSON, insiste ancora sull'invio datain un formato non corrispondente.
Pavel Repin,

Bene. Non l'ho scavato molto. Ero felice che funzionasse. ;) Il mio server richiede JSON.
vvkatwss vvkatwss

Anch'io. Senza JSON.stringify non funziona, mi chiedo perché.
John Simoes,

42

Ho finito per aggiungere il seguente metodo a jQuery nel mio 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
    });
};

E usarlo

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

Ciò è stato fatto semplicemente copiando il codice di "get" e "post" dai sorgenti JQuery originali e codificando alcuni parametri per forzare un POST JSON.

Grazie!


2
Come al solito - la migliore risposta arriva per ultima alla festa e ha meno voti; (
nikib3ro

Ottima risposta - ci vuole un po 'di tempo per capire che $ .post non lo fa "fuori dagli schemi".
markp3rry

21

usare solo

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

AGGIORNATO @JK: se scrivi nella tua domanda solo un esempio di codice con $ .post, troverai un esempio corrispondente nella risposta. Non voglio ripetere le stesse informazioni che hai già studiato fino a che non sai: $ .post e $ .get sono forme brevi di $ .ajax. Quindi basta usare $ .ajax e puoi usare l'intero set dei suoi parametri senza dover cambiare alcuna impostazione globale.

A proposito, non consiglierei di sovrascrivere lo standard $ .post. È la mia opinione personale , ma per me è importante non solo che il programma funzioni, ma anche che tutti coloro che leggono il tuo programma lo capiscano allo stesso modo. Sovrascrivere i metodi standard senza avere un motivo molto importante può seguire l' incomprensione nella lettura del codice del programma. Quindi ripeto la mia raccomandazione ancora una volta: basta usare l'originale $ .ajax da jQuery invece di jQuery.gete jQuery.poste si ricevono programmi che non solo funzionano perfettamente, ma possono essere letti dalle persone senza fraintendimenti.


1
Grande spiegazione e linee guida
Ved Prakash il

8

Il tipo di dati "json" che è possibile passare come ultimo parametro da pubblicare () indica quale tipo di dati si aspetta la funzione nella risposta del server, non quale tipo sta inviando nella richiesta. In particolare imposta l'intestazione "Accetta".

Onestamente, la soluzione migliore è passare a una chiamata ajax (). La funzione post () è intesa come una comodità; una versione semplificata della chiamata ajax () per quando stai semplicemente facendo un semplice invio di moduli. Non lo sei.

Se davvero non vuoi cambiare, puoi creare la tua funzione chiamata, diciamo, xpost (), e farla semplicemente trasformare i parametri dati in parametri per una chiamata jQuery ajax (), con il set di tipi di contenuto. In questo modo, invece di riscrivere tutte quelle funzioni post () in funzioni ajax (), devi solo cambiarle tutte da post a xpost (o qualsiasi altra cosa).


Sono solo i metodi $ .post () che chiamano un metodo controller aspvc mvc che deve cambiare. Quelli jquery puri dovrebbero essere invariati (completamento automatico, diaplog, jqgrid ecc.) Speravo che ci sarebbe stato un semplice cambiamento che avrei potuto apportare ai relativi $ .post () s. Ma sembra che devo convertirli in $ .ajax (). È un'app grande e molto ajax pesante, quindi ce ne sono molte da cambiare.
JK.

6

Questa semplice estensione dell'API di jquery (da: https://benjamin-schweizer.de/jquerypostjson.html ) per $ .postJSON () fa il trucco. Puoi usare postJSON () come ogni altra chiamata Ajax nativa jquery. È possibile collegare gestori di eventi e così via.

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

Come altre API Ajax (come $ http di AngularJS) imposta il contentType corretto su application / json. Puoi passare direttamente i tuoi dati json (oggetti javascript), dal momento che qui vengono stringiti. Il tipo di dati restituito previsto è impostato su JSON. È possibile collegare i gestori di eventi predefiniti di jquery per promesse, ad esempio:

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

5

So che questa è una risposta tardiva, in realtà ho un metodo di scelta rapida che utilizzo per pubblicare / leggere su / da servizi basati su MS .. funziona con MVC e ASMX ecc ...

Uso:

$.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));

NOTA: ho anche un metodo JSON.parseAjax che viene modificato dal file JS di json.org, che aggiunge la gestione per le date MS "/Date(...)/" ...

Il file json2.js modificato non è incluso, utilizza il parser basato su script nel caso di IE8, in quanto vi sono casi in cui il parser nativo si interrompe quando si estende il prototipo di array e / o oggetto, ecc.

Ho pensato di rinnovare questo codice per implementare le interfacce delle promesse, ma ha funzionato davvero bene per me.


4

Al centro della questione c'è il fatto che JQuery al momento della stesura non ha un metodo postJSON mentre getJSON esiste e fa la cosa giusta.

un metodo postJSON farebbe quanto segue:

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

e può essere usato in questo modo:

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
    });

1

La documentazione attualmente mostra che a partire da 3.0, $ .post accetterà l'oggetto settings, il che significa che è possibile utilizzare le opzioni $ .ajax. 3.0 non è ancora stato rilasciato e sul commit stanno parlando di nascondere il riferimento ad esso nei documenti, ma cercarlo in futuro!


1

Ho avuto un problema simile con il seguente codice JavaScript:

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

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

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

Dove nel Fiddler ho potuto vedere la richiesta con:

  • Intestazione: Content-Type: application/x-www-form-urlencoded; charset=UTF-8
  • Corpo: {"value":"5","maxValue":"5"}

Di conseguenza, il mio server non è riuscito a mappare un oggetto su un tipo lato server.

Dopo aver cambiato l'ultima riga con questa:

$.post(url, rating, showSavedNotification);

Nel Fiddler potevo ancora vedere:

  • Intestazione: Content-Type: application/x-www-form-urlencoded; charset=UTF-8
  • Corpo: value=5&maxValue=10

Tuttavia, il server ha iniziato a restituire ciò che mi aspettavo.


0

Che ne dici del tuo adattatore / 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;
    }
  }
})();

E utilizzo estremamente semplice:

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

Provato ma ancora non ottenendo i risultati previsti. ho l'API Spring Boot Rest.
Suraj Shingade,

0

Per qualche motivo, impostare il tipo di contenuto sulla richiesta Ajax come suggerito da @Adrien non ha funzionato nel mio caso. Tuttavia, in realtà è possibile modificare il tipo di contenuto utilizzando $ .post procedendo prima:

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

Quindi effettua la $.postchiamata:

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

Ho avuto problemi con jQuery + IIS, e questa è stata l'unica soluzione che ha aiutato jQuery a comprendere l'uso della codifica windows-1252 per richieste ajax.


0

possiamo cambiare il tipo di contenuto in questo modo in $ .post

$ .post (url, data, function (data, status, xhr) {xhr.setRequestHeader ("Content-type", "application / x-www-form-urlencoded; charset = utf-8");});


-1

$ .post non funziona se si riscontra un problema CORS (Cross Origin Resource Sharing). Prova a usare $ .Ajax nel seguente formato: "$ .ajax ({url: someurl, contentType: 'application / json', data: requestInJSONFormat, header: {'Access-Control-Allow-Origin': '*'}, dataType: 'json', tipo: 'POST', asincrono: falso, successo: funzione (Dati) {...}}); "


-19

Non è possibile inviare application/jsondirettamente: deve essere un parametro di una richiesta GET / POST.

Quindi qualcosa del genere

$.post(url, {json: "...json..."}, function());

Questa risposta potrebbe essere errata, ma non è di bassa qualità ed è un tentativo di rispondere alla domanda. Dalla recensione .
Wai Ha Lee,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.