Jquery - Wie kann $ .post () contentType = application / json verwenden?

309

Ich habe festgestellt, dass bei Verwendung von $ .post () in jquery der Standard-Inhaltstyp application / x-www-form-urlencoded ist - wenn mein asp.net-MVC-Code contentType = application / json haben muss

(In dieser Frage erfahren Sie, warum ich application / json verwenden muss: ASPNET MVC - Warum ist ModelState.IsValid false "Das x-Feld ist erforderlich", wenn dieses Feld einen Wert hat? )

Wie kann ich $ .post () veranlassen, contentType = application / json zu senden? Ich habe bereits eine große Anzahl von $ .post () -Funktionen, daher möchte ich nicht zu $ ​​.ajax () wechseln, da dies zu lange dauern würde

Wenn ich es versuche

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

ContentType = application / x-www-form-urlencoded ist weiterhin vorhanden. Was genau macht der Parameter "json", wenn er den Inhaltstyp nicht in json ändert?

Wenn ich es versuche

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

Das funktioniert, betrifft aber jedes einzelne $ .get und $ .post, das ich habe, und führt dazu, dass einige kaputt gehen.

Gibt es also eine Möglichkeit, das Verhalten von $ .post () zu ändern, um contentType = application / json zu senden?

JK.
quelle

Antworten:

71

Ich denke, Sie müssen vielleicht

1. Ändern Sie die Quelle so, dass $ .post immer den JSON-Datentyp verwendet, da dies nur eine Verknüpfung für einen vorkonfigurierten $.ajaxAufruf ist

Oder

2. Definieren Sie Ihre eigene Dienstprogrammfunktion, die eine Verknüpfung für die $.ajaxKonfiguration darstellt, die Sie verwenden möchten

Oder

3. Sie können die $.post functionmit Ihrer eigenen Implementierung über Affen-Patches überschreiben .

Der JSON-Datentyp in Ihrem Beispiel bezieht sich auf den vom Server zurückgegebenen Datentyp und nicht auf das an den Server gesendete Format .

Russ Cam
quelle
5
+1, ich würde eine neue Methode definieren oder eine Methode überschreiben jQuery.post, es ist eine wirklich einfache Funktion ...
CMS
3
Es ist keine schlechte Idee, erstellen Sie einfach eine Methode namens $ .mvcpost (), die dasselbe tut wie $ .post (durch Kopieren des verknüpften Codes) und den Inhaltstyp ändert. Dann muss ich für alle $ .post () s, die geändert werden müssen, nur 3 zusätzliche Zeichen vor mir eingeben. Es ist viel schneller als sie als $ .ajax () umzuschreiben.
JK.
9
@ PavelRepin, ich musste JSON.stringify () für die Nutzlast aufrufen.
Ustaman Sangat
2
@dragon - hier sind 3 Lösungen für "Gibt es eine Möglichkeit, das Verhalten von $ .post () zu ändern, um contentType = application / json zu senden?". Welcher Teil ist keine Antwort?
Russ Cam
2
Es ist auch wichtig zu wissen: $ .ajax und seine verschiedenen Methoden versuchen anhand der von Ihnen angegebenen Daten zu erraten, wie der contentType aussehen soll (sofern nicht anders angegeben). "mystring data"wird sein, application/x-www-form-urlencoded;wo als Objekt sein { anyKey: "anyvalue and type" }wird application/json. Viele Server, die json lesen, lassen nur ein Objekt oder Array zu, keine Zeichenfolge. Deshalb sagt jquery die Dinge so voraus. Wenn Sie einen Server haben, der Zeichenfolgen, Zahlen usw. liest, ohne in ein Objekt eingeschlossen zu sein, müssen Sie den Inhaltstyp wie in dieser Antwort angeben.
Bzuillsmith
395
$.ajax({
  url:url,
  type:"POST",
  data:data,
  contentType:"application/json; charset=utf-8",
  dataType:"json",
  success: function(){
    ...
  }
})

Siehe: jQuery.ajax ()

Adrien
quelle
13
Der ursprüngliche Beitrag fragt: "Gibt es also eine Möglichkeit, das Verhalten von $ .post () zu ändern, um contentType = application / json zu senden?" ABER es heißt auch "Das funktioniert, wirkt sich aber auf jedes einzelne $ .get und $ .post aus, das ich habe, und führt dazu, dass einige kaputt gehen." Ich verstehe die Frage als "Wie kann ich das Gleiche erreichen wie $ .post, aber den richtigen contentType senden, ohne die anderen Vorkommen von $ .get und $ .post zu beschädigen?". Ist das falsch
Adrien
5
@ x1a4 versteht eindeutig nicht, dass .ajax der Anruf ist, nicht ajaxSetup
Walker
39
@Adrien, für das, was es zwei Jahre später wert ist, ist deine die Antwort, nach der ich gesucht habe, als ich das gegoogelt habe.
AwesomeTown
74
musste verwendet werden JSON.stringify(data), da der Server eine JSON-Zeichenfolge erwartet und jQuery die Schlüssel-Wert-Paare einfach mit kaufmännischem Und verkettet, formul-urlencodiert.
Drache
3
Selbst vier Jahre später hat diese Antwort meine stundenlangen Suchvorgänge mit weniger als zehn Codezeilen gelöst.
Pieter VDE
86

Endlich habe ich die Lösung gefunden, die für mich funktioniert:

jQuery.ajax ({
    url: myurl,
    type: "POST",
    data: JSON.stringify({data:"test"}),
    dataType: "json",
    contentType: "application/json; charset=utf-8",
    success: function(){
        //
    }
});
vvkatwss vvkatwss
quelle
8
Konnte nicht herausfinden, warum ich immer wieder Fehler bekam, es stellte sich heraus, dass Sie die Daten stringifizieren müssen.
FriendlyGuy
5
Ich weiß, dass dies funktioniert, aber WARUM, WARUM, müssen Sie eine Zeichenkette erstellen? Ist es ein jQuery-Fehler? Es scheint vollkommen glücklich zu sein, Ihr dataArgument zu serialisieren x-www-form-urlencoded, aber wenn Sie angeben, dass der Anforderungsinhaltstyp JSON ist, besteht es weiterhin darauf, datain einem nicht übereinstimmenden Format zu senden .
Pavel Repin
Gut. Ich habe nicht viel gegraben. Ich war froh, dass es funktionierte. ;) Mein Server benötigt JSON.
vvkatwss vvkatwss
Hier gilt das gleiche. Ohne JSON.stringify funktioniert es nicht, ich frage mich warum.
John Simoes
42

Am Ende habe ich jQuery in meinem Skript die folgende Methode hinzugefügt:

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

Und um es zu benutzen

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

Dazu wurde einfach der Code "get" und "post" aus den ursprünglichen JQuery-Quellen kopiert und einige Parameter fest codiert, um einen JSON-POST zu erzwingen.

Vielen Dank!

Kontinuität
quelle
2
Wie üblich - die beste Antwort kommt als letzte zur Party und hat am wenigsten positive Stimmen (
nikib3ro
Tolle Antwort - es dauert eine Weile, bis klar wird, dass $ .post dies nicht "out of the box" tut.
Markp3rry
21

benutze nur

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

UPDATED @JK: Wenn Sie in Ihre Frage nur ein Codebeispiel mit $ .post schreiben , finden Sie in der Antwort ein entsprechendes Beispiel. Ich möchte nicht dieselben Informationen wiederholen, die Sie bereits studiert haben, bis Sie wissen: $ .post und $ .get sind Kurzformen von $ .ajax. Verwenden Sie also einfach $ .ajax und Sie können den gesamten Satz seiner Parameter verwenden, ohne globale Einstellungen ändern zu müssen.

Übrigens würde ich nicht empfehlen, den Standard $ .post zu überschreiben. Es ist meine persönliche Meinung , aber für mich ist es wichtig, dass nicht nur das Programm funktioniert, sondern dass alle, die Ihr Programm lesen, es auf die gleiche Weise verstehen. Das Überschreiben von Standardmethoden ohne einen sehr wichtigen Grund kann zu Missverständnissen beim Lesen des Programmcodes führen. Deshalb wiederhole ich meine Empfehlung noch einmal: Verwenden Sie einfach das Original-Formular $ .ajax jQuery anstelle von jQuery.getund jQuery.postund Sie erhalten Programme, die nicht nur perfekt funktionieren, sondern auch von Menschen ohne Missverständnisse gelesen werden können.

Oleg
quelle
1
Tolle Erklärung und Richtlinie
Ved Prakash
8

Der Datentyp "json", den Sie als letzten Parameter an post () übergeben können, gibt an, welchen Datentyp die Funktion in der Antwort des Servers erwartet und nicht, welchen Typ sie in der Anforderung sendet. Insbesondere wird der Header "Akzeptieren" festgelegt.

Ehrlich gesagt ist es am besten, zu einem Ajax () -Aufruf zu wechseln. Die Funktion post () ist als Annehmlichkeit gedacht. Eine vereinfachte Version des Aufrufs von ajax (), wenn Sie nur ein einfaches Formular veröffentlichen. Das bist du nicht.

Wenn Sie wirklich nicht wechseln möchten, können Sie eine eigene Funktion namens xpost () erstellen und die angegebenen Parameter einfach in Parameter für einen Aufruf von jQuery ajax () umwandeln, wobei der Inhaltstyp festgelegt ist. Auf diese Weise müssen Sie nicht alle diese post () - Funktionen in ajax () - Funktionen umschreiben, sondern nur alle von post in xpost (oder was auch immer) ändern.

Jacob Mattison
quelle
Es sind nur die $ .post () -Methoden, die eine asp.net-MVC-Controller-Methode aufrufen, die geändert werden muss. Die reinen Abfragen sollten unverändert bleiben (Autocomplete, Diaplog, JQGRID usw.). Ich hatte gehofft, dass es eine einfache Änderung geben würde, die ich an den relevanten $ .post () s vornehmen könnte. Aber es sieht so aus, als müsste ich sie in $ .ajax () konvertieren. Es ist eine große und sehr ajaxlastige App, daher gibt es viele zu ändern.
JK.
6

Diese einfache jquery API-Erweiterung (von: https://benjamin-schweizer.de/jquerypostjson.html ) für $ .postJSON () macht den Trick. Sie können postJSON () wie jeden anderen nativen Ajax-Aufruf von jquery verwenden. Sie können Ereignishandler usw. anhängen.

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

Wie andere Ajax-APIs (wie $ http von AngularJS) setzt es den richtigen contentType auf application / json. Sie können Ihre JSON-Daten (Javascript-Objekte) direkt übergeben, da sie hier stringifiziert werden. Der erwartete zurückgegebene Datentyp ist auf JSON festgelegt. Sie können die Standardereignishandler von jquery für Versprechen anhängen, zum Beispiel:

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

Ich weiß, dass dies eine späte Antwort ist. Ich habe tatsächlich eine Verknüpfungsmethode, die ich zum Posten / Lesen in / von MS-basierten Diensten verwende. Sie funktioniert sowohl mit MVC als auch mit ASMX usw.

Verwenden:

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

HINWEIS: Ich habe auch eine JSON.parseAjax-Methode, die aus der JS-Datei von json.org geändert wurde und die Behandlung für die MS "/Date(...)/" -Daten hinzufügt ...

Die geänderte Datei json2.js ist nicht enthalten, verwendet im Fall von IE8 den skriptbasierten Parser, da es Fälle gibt, in denen der native Parser unterbrochen wird, wenn Sie den Prototyp eines Arrays und / oder Objekts usw. erweitern.

Ich habe überlegt, diesen Code zu überarbeiten, um die Versprechen-Schnittstellen zu implementieren, aber es hat wirklich gut für mich funktioniert.

Tracker1
quelle
4

Im Mittelpunkt steht die Tatsache, dass JQuery zum Zeitpunkt des Schreibens keine postJSON-Methode hat, während getJSON existiert und das Richtige tut.

Eine postJSON-Methode würde Folgendes tun:

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

und kann wie folgt verwendet werden:

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
    });
dbrin
quelle
1

Die Dokumentation zeigt derzeit, dass $ .post ab 3.0 das Einstellungsobjekt akzeptiert, was bedeutet, dass Sie die $ .ajax-Optionen verwenden können. 3.0 ist noch nicht veröffentlicht und beim Commit geht es darum, den Verweis darauf in den Dokumenten zu verbergen, aber suchen Sie in Zukunft danach!

Ben Creasy
quelle
1

Ich hatte ein ähnliches Problem mit dem folgenden JavaScript-Code:

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

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

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

Wo im Fiddler konnte ich die Anfrage sehen mit:

  • Header: Content-Type: application/x-www-form-urlencoded; charset=UTF-8
  • Körper: {"value":"5","maxValue":"5"}

Infolgedessen konnte mein Server ein Objekt keinem serverseitigen Typ zuordnen.

Nachdem Sie die letzte Zeile in diese geändert haben:

$.post(url, rating, showSavedNotification);

Im Fiddler konnte ich noch sehen:

  • Header: Content-Type: application/x-www-form-urlencoded; charset=UTF-8
  • Körper: value=5&maxValue=10

Der Server gab jedoch das zurück, was ich erwartet hatte.

Oleg Burov
quelle
0

Wie wäre es mit Ihrem eigenen Adapter / 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;
    }
  }
})();

Und extrem einfache Bedienung:

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... }
});
Schwärzung
quelle
Versucht, aber immer noch nicht die erwarteten Ergebnisse zu erhalten. Ich habe Spring Boot Rest API.
Suraj Shingade
0

Aus irgendeinem Grund funktionierte das Festlegen des Inhaltstyps für die Ajax-Anforderung, wie von @Adrien vorgeschlagen, in meinem Fall nicht. Sie können den Inhaltstyp jedoch mithilfe von $ .post ändern, indem Sie Folgendes tun:

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

Dann $.postrufen Sie an:

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

Ich hatte Probleme mit jQuery + IIS, und dies war die einzige Lösung, die jQuery dabei half, die Verwendung der Windows-1252-Codierung für Ajax-Anforderungen zu verstehen.

Johannes
quelle
0

Wir können den Inhaltstyp wie folgt in $ .post ändern

$ .post (URL, Daten, Funktion (Daten, Status, xhr) {xhr.setRequestHeader ("Inhaltstyp", "Anwendung / x-www-Formular-urlencodiert; Zeichensatz = utf-8");});

Snziv Gupta
quelle
-1

$ .post funktioniert nicht, wenn Sie ein CORS-Problem (Cross Origin Resource Sharing) haben. Versuchen Sie, $ .Ajax im folgenden Format zu verwenden: "$ .ajax ({url: someurl, contentType: 'application / json', data: requestInJSONFormat, headers : {'Access-Control-Allow-Origin': '*'}, dataType: 'json', type: 'POST', async: false, success: function (Data) {...}}); "

Soma Sarkar
quelle
-19

Sie können nicht application/jsondirekt senden - es muss ein Parameter einer GET / POST-Anforderung sein.

Also so etwas wie

$.post(url, {json: "...json..."}, function());
Amy B.
quelle
Diese Antwort ist möglicherweise falsch, aber nicht von geringer Qualität, und es ist ein Versuch, die Frage zu beantworten. Aus der Überprüfung .
Wai Ha Lee