AngularJs $ http.post () sendet keine Daten

337

Kann mir jemand sagen, warum die folgende Erklärung die Post-Daten nicht an die angegebene URL sendet? Die URL wird aufgerufen, aber auf dem Server, wenn ich $ _POST drucke - ich erhalte ein leeres Array. Wenn ich eine Nachricht in der Konsole drucke, bevor ich sie zu den Daten hinzufüge, wird der richtige Inhalt angezeigt.

$http.post('request-url',  { 'message' : message });

Ich habe es auch mit den Daten als Zeichenfolge versucht (mit dem gleichen Ergebnis):

$http.post('request-url',  "message=" + message);

Es scheint zu funktionieren, wenn ich es im folgenden Format verwende:

$http({
    method: 'POST',
    url: 'request-url',
    data: "message=" + message,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'}
});

Aber gibt es eine Möglichkeit, dies mit $ http.post () zu tun - und muss ich immer den Header einfügen, damit es funktioniert? Ich glaube, dass der obige Inhaltstyp das Format der gesendeten Daten angibt, aber kann ich sie als Javascript-Objekt senden?

Spencer Mark
quelle
Ist die URL im selben Ursprung?
fmquaglia
Entschuldigung - ja für alle Beispiele ist es die gleiche URL
Spencer Mark
@SpencerMark sorry .. ich habe versucht über Ihrem Arbeitscode .. es funktioniert nicht für mich.
Arul Sidthan

Antworten:

345

Ich hatte das gleiche Problem mit asp.net MVC und fand hier die Lösung

AngularJS- Neulinge sind sehr verwirrt darüber, warum die $httpService-Kurzschriftfunktionen ( $http.post()usw.) nicht mit den jQuery- Äquivalenten ( jQuery.post()usw.) austauschbar zu sein scheinen .

Der Unterschied besteht darin, wie jQuery und AngularJS die Daten serialisieren und übertragen. Grundsätzlich liegt das Problem darin, dass die Serversprache Ihrer Wahl die Übertragung von AngularJS nicht nativ verstehen kann ... Standardmäßig überträgt jQuery Daten mit

Content-Type: x-www-form-urlencoded

und die bekannte foo=bar&baz=moeSerialisierung.

AngularJS überträgt jedoch Daten mit

Content-Type: application/json 

und { "foo": "bar", "baz": "moe" }

JSON-Serialisierung, die leider von einigen Webserversprachen - insbesondere PHP - nicht nativ unserialisiert wird.

Klappt wunderbar.

CODE

// Your app's root module...
angular.module('MyModule', [], function($httpProvider) {
  // Use x-www-form-urlencoded Content-Type
  $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';

  /**
   * The workhorse; converts an object to x-www-form-urlencoded serialization.
   * @param {Object} obj
   * @return {String}
   */ 
  var param = function(obj) {
    var query = '', name, value, fullSubName, subName, subValue, innerObj, i;

    for(name in obj) {
      value = obj[name];

      if(value instanceof Array) {
        for(i=0; i<value.length; ++i) {
          subValue = value[i];
          fullSubName = name + '[' + i + ']';
          innerObj = {};
          innerObj[fullSubName] = subValue;
          query += param(innerObj) + '&';
        }
      }
      else if(value instanceof Object) {
        for(subName in value) {
          subValue = value[subName];
          fullSubName = name + '[' + subName + ']';
          innerObj = {};
          innerObj[fullSubName] = subValue;
          query += param(innerObj) + '&';
        }
      }
      else if(value !== undefined && value !== null)
        query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&';
    }

    return query.length ? query.substr(0, query.length - 1) : query;
  };

  // Override $http service's default transformRequest
  $httpProvider.defaults.transformRequest = [function(data) {
    return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data;
  }];
});
Felipe Miosso
quelle
7
Ich habe dieses Skript zu bower hinzugefügt, um bower install angular-post-fix --save-deves hinzuzufügen.
Billy Blaze
Gibt es also eine Möglichkeit, die Übertragungsdatenmethode von PHP zu ändern? Denn das ist das Problem, das ich derzeit habe.
Demodave
1
Dieser Code funktioniert größtenteils hervorragend, aber ich hatte Probleme damit, wenn ich eine Hierarchie von leeren Objekten oder sogar flachen leeren Werten übermittelte. Zum Beispiel werden {a: 1, b: {c: {d: {}}}, e: undefiniert, f: null, g: 2} nicht richtig codiert und PHP erhält es als ["a" = > "1", "g" => "2"]. Die gesamte Struktur unter "b" sowie "e" und "f" einschließlich der Schlüssel selbst würde verloren gehen. Ich habe unten alternativen Code gepostet, mit dem die obige Struktur wie folgt dekodiert wird: ["a" => "1", "b" => ["c" => ["d" => ""]], "e" => "", "f" => "", "g" => "2"].
obe
1
Wie soll ich das für mehrteilige / Formulardaten implementieren?
Davidlee
Hervorragend :) In der Tat wie ein Zauber funktioniert. Ich stand vor dem Problem mit Spring MVC
SKaul
115

Es ist oben nicht sehr klar, aber wenn Sie die Anfrage in PHP erhalten, können Sie verwenden:

$params = json_decode(file_get_contents('php://input'),true);

Zugriff auf ein Array in PHP über einen AngularJS-POST.

Don F.
quelle
3
Ich musste true hinzufügen, um es einem Array zu erzwingen, wenn ich das $ _POST-Array damit überschrieb. json_decode(file_get_contents('php://input'), true);
Jon
4
@Zalaboza, ich würde zustimmen, dass es schwierig ist, eine Lösung als "universell" zu betrachten, aber ich stimme nicht zu, dass sie "hacky" ist --- php.net sagt: "file_get_contents () ist die bevorzugte Methode zum Lesen des Inhalts einer Datei in eine Zeichenfolge. Es werden Speicherzuordnungstechniken verwendet, wenn dies von Ihrem Betriebssystem unterstützt wird, um die Leistung zu verbessern. " Zugegeben, wir lesen in dieser Situation keine Datei, aber wir lesen trotzdem gepostete JSON-Daten. Es wäre großartig, wenn Sie eine neue Antwort beitragen oder neue Informationen bereitstellen könnten, um den Lesern (einschließlich mir) zu helfen, eine bessere Entscheidung darüber zu treffen.
Don F
78

Sie können den Standard "Inhaltstyp" wie folgt festlegen:

$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";

Über das dataFormat:

Die Methoden $ http.post und $ http.put akzeptieren alle JavaScript-Objektwerte (oder Zeichenfolgen) als Datenparameter. Wenn Daten ein JavaScript-Objekt sind, werden sie standardmäßig in eine JSON-Zeichenfolge konvertiert.

Versuchen Sie, diese Variante zu verwenden

function sendData($scope) {
    $http({
        url: 'request-url',
        method: "POST",
        data: { 'message' : message }
    })
    .then(function(response) {
            // success
    }, 
    function(response) { // optional
            // failed
    });
}
Denison Luz
quelle
9
Es scheint nicht zu funktionieren. Ich habe gerade versucht, die Variation mit den Daten als Zeichenfolge und: headers: {'Content-Type': 'application / x-www-form-urlencoded'} - und das scheint zu funktionieren, aber gibt es eine bessere Möglichkeit es?
Spencer Mark
2
Stellen Sie den Standardinhaltstyp wie oben beschrieben ein und verwenden Sie für Daten kein js-Objekt. Verwenden Sie eine Zeichenfolge wie
folgt
58

Ich hatte ein ähnliches Problem und frage mich, ob dies auch nützlich sein kann: https://stackoverflow.com/a/11443066

var xsrf = $.param({fkey: "key"});
$http({
    method: 'POST',
    url: url,
    data: xsrf,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})

Grüße,

ericson.cepeda
quelle
Es sieht so aus, als ob die Header die einzige Änderung waren, die wir brauchten. Vielen Dank!
Ben Guthrie
Danke, das hat es für mich getan :) Das Problem war die Codierung der POST-Daten.
Daan
33

Ich verwende gerne eine Funktion, um Objekte in Post-Parameter umzuwandeln.

myobject = {'one':'1','two':'2','three':'3'}

Object.toparams = function ObjecttoParams(obj) {
    var p = [];
    for (var key in obj) {
        p.push(key + '=' + encodeURIComponent(obj[key]));
    }
    return p.join('&');
};

$http({
    method: 'POST',
    url: url,
    data: Object.toparams(myobject),
    headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
Rômulo Collopy
quelle
30

Dies wurde schließlich in Winkel 1.4 mit $ httpParamSerializerJQLike behoben

Siehe https://github.com/angular/angular.js/issues/6039

.controller('myCtrl', function($http, $httpParamSerializerJQLike) {
$http({
  method: 'POST',
  url: baseUrl,
  data: $httpParamSerializerJQLike({
    "user":{
      "email":"[email protected]",
      "password":"123456"
    }
  }),
  headers:
    'Content-Type': 'application/x-www-form-urlencoded'
})})
Stetzon
quelle
Ich stehe vor dem Problem POST 192.168.225.75:7788/procure/p/search 400 (Bad Request)
Anuj
19

Ich verwende jQuery param mit AngularJS post requrest. Hier ist ein Beispiel ... erstellen AngularJS Anwendungsmodul, in dem myappmit definiert ist ng-appin Ihrem HTML - Code.

var app = angular.module('myapp', []);

Lassen Sie uns nun einen Login-Controller sowie eine POST-E-Mail und ein Passwort erstellen.

app.controller('LoginController', ['$scope', '$http', function ($scope, $http) {
    // default post header
    $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
    // send login data
    $http({
        method: 'POST',
        url: 'https://example.com/user/login',
        data: $.param({
            email: $scope.email,
            password: $scope.password
        }),
        headers: {'Content-Type': 'application/x-www-form-urlencoded'}
    }).success(function (data, status, headers, config) {
        // handle success things
    }).error(function (data, status, headers, config) {
        // handle error things
    });
}]);

Ich möchte den Code nicht erklären, er ist einfach zu verstehen :) Beachten Sie, dass er paramvon jQuery stammt. Sie müssen also sowohl jQuery als auch AngularJS installieren, damit er funktioniert. Hier ist ein Screenshot.

Geben Sie hier die Bildbeschreibung ein

Hoffe das ist hilfreich. Vielen Dank!

Madan Sapkota
quelle
10

Ich hatte das gleiche Problem mit AngularJS und Node.js + Express 4 + Router

Der Router erwartet die Daten von der Anforderung des Posts im Hauptteil. Dieser Körper war immer leer, wenn ich dem Beispiel von Angular Docs folgte

Notation 1

$http.post('/someUrl', {msg:'hello word!'})

Aber wenn ich es in den Daten verwendet habe

Notation 2

$http({
       withCredentials: false,
       method: 'post',
       url: yourUrl,
       headers: {'Content-Type': 'application/x-www-form-urlencoded'},
       data: postData
 });

Bearbeiten 1:

Andernfalls erwartet der Router von node.js die Daten in req.body, wenn Notation 1 verwendet wird:

req.body.msg

Welches sendet die Informationen auch als JSON-Nutzdaten. Dies ist in einigen Fällen besser, in denen Sie Arrays in Ihrem json haben und x-www-form-urlencoded einige Probleme verursacht.

es funktionierte. Ich hoffe es hilft.

weiß
quelle
10

Im Gegensatz zu JQuery und aus Gründen der pedantry, Angular verwendet JSON Format für POST Datenübertragung von einem Client an den Server (JQuery vermutlich x-www-form-urlencoded gilt, obwohl JQuery und winklige JSON verwendet für die Daten imput). Daher gibt es zwei Teile des Problems: im js-Client-Teil und im Server-Teil. Deswegen brauchst du:

  1. Setzen Sie js Angular Client-Teil wie folgt:

    $http({
    method: 'POST',
    url: 'request-url',
    data: {'message': 'Hello world'}
    });

UND

  1. Schreiben Sie in Ihren Serverteil, um Daten von einem Client zu erhalten (wenn es PHP ist).

            $data               = file_get_contents("php://input");
            $dataJsonDecode     = json_decode($data);
            $message            = $dataJsonDecode->message;
            echo $message;     //'Hello world'

Hinweis: $ _POST funktioniert nicht!

Die Lösung funktioniert hoffentlich gut für mich und für Sie.

römisch
quelle
8

So senden Sie Daten per Post-Methode mit $http Angularjs müssen Sie diese ändern

data: "message=" + messagemit data: $.param({message:message})

BERGUIGA Mohamed Amine
quelle
1
Warum sind beim Senden von AngularJS-Postdaten Daten: $ .param erforderlich?
blauer Himmel
7

Um auf der Antwort von @ felipe-miosso aufzubauen:

  1. Laden Sie es als AngularJS Modul von hier ,
  2. Es installieren
  3. Fügen Sie es Ihrer Anwendung hinzu:

    var app = angular.module('my_app', [ ... , 'httpPostFix']);
Renaud
quelle
6

Ich habe nicht den Ruf zu kommentieren, aber als Antwort / Ergänzung zu Don Fs Antwort:

$params = json_decode(file_get_contents('php://input'));

Ein zweiter Parameter von truemuss zur json_decodeFunktion hinzugefügt werden, um ein assoziatives Array ordnungsgemäß zurückzugeben:

$params = json_decode(file_get_contents('php://input'), true);

Esten
quelle
6

Winkelig

  var payload = $.param({ jobId: 2 });

                this.$http({
                    method: 'POST',
                    url: 'web/api/ResourceAction/processfile',
                    data: payload,
                    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
                });

WebAPI 2

public class AcceptJobParams
        {
            public int jobId { get; set; }
        }

        public IHttpActionResult ProcessFile([FromBody]AcceptJobParams thing)
        {
            // do something with fileName parameter

            return Ok();
        }
Malcolm Swaine
quelle
5

Dieser Code hat das Problem für mich gelöst. Es ist eine Lösung auf Anwendungsebene:

moduleName.config(['$httpProvider',
  function($httpProvider) {
    $httpProvider.defaults.transformRequest.push(function(data) {
        var requestStr;
        if (data) {
            data = JSON.parse(data);
            for (var key in data) {
                if (requestStr) {
                    requestStr += "&" + key + "=" + data[key];
                } else {
                    requestStr = key + "=" + data[key];
                }
            }
        }
        return requestStr;
    });
    $httpProvider.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
  }
]);
Spartak Lalaj
quelle
5

Fügen Sie dies in Ihre js-Datei ein:

$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";

und fügen Sie dies Ihrer Serverdatei hinzu:

$params = json_decode(file_get_contents('php://input'), true);

Das sollte funktionieren.

Jesus Erwin Suarez
quelle
4

Ich hatte auch ein ähnliches Problem und ich machte so etwas und das hat nicht funktioniert. Mein Spring-Controller konnte die Datenparameter nicht lesen.

var paramsVal={data:'"id":"1"'};
  $http.post("Request URL",  {params: paramsVal});  

Aber als ich dieses Forum und das API-Dokument gelesen habe, habe ich versucht, den folgenden Weg zu gehen, und das hat bei mir funktioniert. Wenn jemand auch ein ähnliches Problem hat, können Sie es auch unten versuchen.

$http({
      method: 'POST',
      url: "Request URL",           
      params: paramsVal,
      headers: {'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'}
            });

Bitte überprüfen Sie https://docs.angularjs.org/api/ng/service/ $ http # post, was param config tut. {data: '"id": "1"'} - Zuordnung von Zeichenfolgen oder Objekten, die in URL umgewandelt werden? data = "id: 1"

Viraj
quelle
4

Dies ist wahrscheinlich eine späte Antwort, aber ich denke, der beste Weg ist, denselben Code-Winkel zu verwenden, wenn Sie eine "get" -Anforderung ausführen. Sie $httpParamSerializermüssen ihn in Ihren Controller einspeisen, damit Sie einfach die folgenden Schritte ausführen können, ohne dies tun zu müssen benutze Jquery überhaupt, $http.post(url,$httpParamSerializer({param:val}))

app.controller('ctrl',function($scope,$http,$httpParamSerializer){
    $http.post(url,$httpParamSerializer({param:val,secondParam:secondVal}));
}
oneLeggedChicken
quelle
4

In meinem Fall löse ich das Problem folgendermaßen:

var deferred = $q.defer();

$http({
    method: 'POST',
    url: 'myUri', 
    data: $.param({ param1: 'blablabla', param2: JSON.stringify(objJSON) }),
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(
    function(res) {
        console.log('succes !', res.data);
        deferred.resolve(res.data);
    },
    function(err) {
        console.log('error...', err);
        deferred.resolve(err);
    }
);
return deferred.promise;

Sie müssen JSON.stringify für jeden Parameter verwenden, der ein JSON-Objekt enthält, und dann Ihr Datenobjekt mit "$ .param" erstellen :-)

NB: Mein "objJSON" ist ein JSON-Objekt, das Array-, Integer-, String- und HTML-Inhalte enthält. Seine Gesamtgröße beträgt> 3500 Zeichen.

bArraxas
quelle
3

Ich weiß, hat die Antwort akzeptiert . Das Folgen kann jedoch zukünftigen Lesern helfen, wenn die Antwort aus irgendeinem Grund nicht zu ihnen passt.

Angular macht Ajax nicht wie jQuery. Während ich versuchte, der Anleitung zum Ändern des Winkels zu folgen $httpprovider, stieß ich auf andere Probleme. ZB verwende ich einen Codeigniter, bei dem die $this->input->is_ajax_request()Funktion immer fehlgeschlagen ist (der von einem anderen Programmierer geschrieben und global verwendet wurde, also nicht geändert werden kann) und der besagt, dass dies keine echte Ajax-Anfrage war.

Um es zu lösen, nahm ich Hilfe von aufgeschobenen Versprechen . Ich habe es in Firefox und ie9 getestet und es hat funktioniert.

Ich habe folgende Funktion außerhalb eines der Winkelcodes definiert . Diese Funktion führt einen regelmäßigen jquery ajax-Aufruf durch und gibt ein zurückgestelltes / versprochenes Objekt (ich lerne noch) zurück.

function getjQueryAjax(url, obj){
    return $.ajax({
        type: 'post',
        url: url,
        cache: true,
        data: obj
    });
}

Dann nenne ich es Winkelcode mit dem folgenden Code. Bitte beachten Sie, dass wir das $scopemanuell mit aktualisieren müssen $scope.$apply().

    var data = {
        media: "video",
        scope: "movies"
    };
    var rPromise = getjQueryAjax("myController/getMeTypes" , data);
    rPromise.success(function(response){
        console.log(response);
        $scope.$apply(function(){
            $scope.testData = JSON.parse(response);
            console.log($scope.testData);
        });
    }).error(function(){
        console.log("AJAX failed!");
    });

Dies ist möglicherweise nicht die perfekte Antwort, aber es ermöglichte mir, jquery ajax-Aufrufe mit Winkel zu verwenden und die zu aktualisieren $scope.

Nis
quelle
2
Angular hat seit 1.3 einen eigenen Versprechensdienst namens $ q. Sie müssen JQuery nicht für einen Beitrag verwenden.
mbokil
3

Ich hatte das gleiche Problem in Express .. um zu lösen, müssen Sie Bodyparser verwenden, um JSON-Objekte zu analysieren, bevor Sie http-Anfragen senden ..

app.use(bodyParser.json());
Muhammad Soliman
quelle
3

Ich verwende asp.net WCF-Webservices mit eckigem js und der folgende Code hat funktioniert:

 $http({
        contentType: "application/json; charset=utf-8",//required
        method: "POST",
        url: '../../operation/Service.svc/user_forget',
        dataType: "json",//optional
        data:{ "uid_or_phone": $scope.forgettel, "user_email": $scope.forgetemail },
        async: "isAsync"//optional

       }).success( function (response) {

         $scope.userforgeterror = response.d;                    
       })

Ich hoffe es hilft.

Mehdi Rostami
quelle
3

Es wurde kein vollständiger Codeausschnitt gefunden, wie die Methode $ http.post zum Senden von Daten an den Server verwendet wird und warum dies in diesem Fall nicht funktioniert.

Erläuterungen zum folgenden Codeausschnitt ...

  1. Ich verwende die Funktion jQuery $ .param, um die JSON-Daten in www post-Daten zu serialisieren
  2. Festlegen des Inhaltstyps in der Konfigurationsvariablen, die zusammen mit der Anforderung von angleJS $ http.post übergeben wird, die den Server anweist, dass wir Daten im WWW-Post-Format senden.

  3. Beachten Sie die $ htttp.post-Methode, bei der ich den ersten Parameter als URL, den zweiten Parameter als Daten (serialisiert) und den dritten Parameter als Konfiguration sende.

Der verbleibende Code ist selbstverständlich.

$scope.SendData = function () {
           // use $.param jQuery function to serialize data from JSON 
            var data = $.param({
                fName: $scope.firstName,
                lName: $scope.lastName
            });

            var config = {
                headers : {
                    'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8;'
                }
            }

            $http.post('/ServerRequest/PostDataResponse', data, config)
            .success(function (data, status, headers, config) {
                $scope.PostDataResponse = data;
            })
            .error(function (data, status, header, config) {
                $scope.ResponseDetails = "Data: " + data +
                    "<hr />status: " + status +
                    "<hr />headers: " + header +
                    "<hr />config: " + config;
            });
        };

Schauen Sie sich hier das Codebeispiel der $ http.post-Methode an .

Sheo Narayan
quelle
3

Wenn Sie PHP verwenden, ist dies eine einfache Möglichkeit, über einen AngularJS-POST auf ein Array in PHP zuzugreifen.

$params = json_decode(file_get_contents('php://input'),true);
Luis Felipe Barnett V.
quelle
Dieser Artikel kann Menschen helfen .
Stphane
3

Wenn Sie Angular> = 1.4 verwenden , finden Sie hier die sauberste Lösung mit dem von Angular bereitgestellten Serializer :

angular.module('yourModule')
  .config(function ($httpProvider, $httpParamSerializerJQLikeProvider){
    $httpProvider.defaults.transformRequest.unshift($httpParamSerializerJQLikeProvider.$get());
    $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
});

Und dann können Sie dies einfach überall in Ihrer App tun:

$http({
  method: 'POST',
  url: '/requesturl',
  data: {
    param1: 'value1',
    param2: 'value2'
  }
});

Die Daten werden dann korrekt serialisiert param1=value1&param2=value2und /requesturlmit dem application/x-www-form-urlencoded; charset=utf-8Content-Type-Header an gesendet, wie dies normalerweise bei POST-Anforderungen auf Endpunkten zu erwarten ist.

TL; DR

Während meiner Recherche fand ich heraus, dass die Antwort auf dieses Problem in vielen verschiedenen Geschmacksrichtungen vorliegt. Einige sind sehr kompliziert und hängen von benutzerdefinierten Funktionen ab, andere von jQuery und andere weisen unvollständig darauf hin, dass Sie nur den Header festlegen müssen.

Wenn Sie nur den Content-TypeHeader festlegen , werden auf dem Endpunkt die POST-Daten angezeigt, jedoch nicht im Standardformat, es sei denn, Sie geben eine Zeichenfolge als Ihre andata alle Daten als JSON serialisiert werden, es an oder serialisieren Ihr Datenobjekt manuell Standard und kann am Endpunkt falsch interpretiert werden.

Wenn im obigen Beispiel beispielsweise nicht der richtige Serializer festgelegt wurde, wird dies im Endpunkt wie folgt angezeigt:

{"param1":"value1","param2":"value2"}

Dies kann zu unerwartetem Parsen führen, z. B. wird es von ASP.NET als nullParametername mit einem {"param1":"value1","param2":"value2"}Wert behandelt. oder Fiddler interpretiert es andersherum, {"param1":"value1","param2":"value2"}als Parameternamen und nullals Wert.

Saeb Amini
quelle
3

Ähnlich wie das vom OP vorgeschlagene Arbeitsformat und die Antwort von Denison, außer dass $http.poststatt nur verwendet wird$http und immer noch von jQuery abhängig ist.

Das Gute an der Verwendung von jQuery ist, dass komplexe Objekte ordnungsgemäß übergeben werden. gegen die manuelle Konvertierung in URL-Parameter, die die Daten beschädigen können.

$http.post( 'request-url', jQuery.param( { 'message': message } ), {
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});
Benjamin Intal
quelle
2

Als ich dieses Problem hatte, stellte sich heraus, dass der Parameter, den ich veröffentlichte, ein Array von Objekten anstelle eines einfachen Objekts war.

D. Kermott
quelle
2

Gerade von Winkel 1.2 auf 1.3 aktualisiert, habe ein Problem im Code gefunden. Das Transformieren einer Ressource führt zu einer Endlosschleife, weil (glaube ich) das $ -Versprechen wieder dasselbe Objekt enthält. Vielleicht hilft es jemandem ...

Ich könnte das beheben durch:

[...]
  /**
 * The workhorse; converts an object to x-www-form-urlencoded serialization.
 * @param {Object} obj
 * @return {String}
 */
var param = function (obj) {
var query = '', name, value, fullSubName, subName, subValue, innerObj, i;

angular.forEach(obj, function(value, name) {
+    if(name.indexOf("$promise") != -1) {
+        return;
+    }

    value = obj[name];
    if (value instanceof Array) {
        for (i = 0; i < value.length; ++i) {
[...]
tom_w
quelle
2

Ich habe den Code der akzeptierten Antwort (Felipes Code) für eine Weile verwendet und er hat großartig funktioniert (danke, Felipe!).

Kürzlich habe ich jedoch festgestellt, dass es Probleme mit leeren Objekten oder Arrays gibt. Zum Beispiel beim Senden dieses Objekts:

{
    A: 1,
    B: {
        a: [ ],
    },
    C: [ ],
    D: "2"
}

PHP scheint B und C überhaupt nicht zu sehen. Es bekommt das:

[
    "A" => "1",
    "B" => "2"
]

Ein Blick auf die aktuelle Anfrage in Chrome zeigt Folgendes:

A: 1
:
D: 2

Ich habe ein alternatives Code-Snippet geschrieben. Es scheint gut mit meinen Anwendungsfällen zu funktionieren, aber ich habe es nicht ausgiebig getestet. Verwenden Sie es daher mit Vorsicht.

Ich habe TypeScript verwendet, weil ich starkes Tippen mag, aber es wäre einfach, in reines JS zu konvertieren:

angular.module("MyModule").config([ "$httpProvider", function($httpProvider: ng.IHttpProvider) {
    // Use x-www-form-urlencoded Content-Type
    $httpProvider.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8";

    function phpize(obj: Object | any[], depth: number = 1): string[] {
        var arr: string[] = [ ];
        angular.forEach(obj, (value: any, key: string) => {
            if (angular.isObject(value) || angular.isArray(value)) {
                var arrInner: string[] = phpize(value, depth + 1);
                var tmpKey: string;
                var encodedKey = encodeURIComponent(key);
                if (depth == 1) tmpKey = encodedKey;
                else tmpKey = `[${encodedKey}]`;
                if (arrInner.length == 0) {
                    arr.push(`${tmpKey}=`);
                }
                else {
                    arr = arr.concat(arrInner.map(inner => `${tmpKey}${inner}`));
                }
            }
            else {
                var encodedKey = encodeURIComponent(key);
                var encodedValue;
                if (angular.isUndefined(value) || value === null) encodedValue = "";
                else encodedValue = encodeURIComponent(value);

                if (depth == 1) {
                    arr.push(`${encodedKey}=${encodedValue}`);
                }
                else {
                    arr.push(`[${encodedKey}]=${encodedValue}`);
                }
            }
        });
        return arr;
    }

    // Override $http service's default transformRequest
    (<any>$httpProvider.defaults).transformRequest = [ function(data: any) {
        if (!angular.isObject(data) || data.toString() == "[object File]") return data;
        return phpize(data).join("&");
    } ];
} ]);

Es ist weniger effizient als Felipes Code, aber ich denke nicht, dass es wichtig ist, da es im Vergleich zum Gesamtaufwand der HTTP-Anfrage selbst sofort erfolgen sollte.

Jetzt zeigt PHP:

[
    "A" => "1",
    "B" => [
        "a" => ""
    ],
    "C" => "",
    "D" => "2"
]

Soweit ich weiß, ist es nicht möglich, PHP dazu zu bringen, zu erkennen, dass Ba und C leere Arrays sind, aber zumindest die Schlüssel erscheinen, was wichtig ist, wenn es Code gibt, der auf einer bestimmten Struktur beruht, selbst wenn er im Wesentlichen leer ist.

Beachten Sie auch, dass undefinierte s und null s in leere Zeichenfolgen konvertiert werden .

gehorche
quelle
TypeScript ist der beste Weg, um POO mit JavaScript zu codieren!
Entstellen Sie den
2

Geben Sie einfach die Daten, die Sie senden möchten, als zweiten Parameter ein:

$http.post('request-url',  message);

Eine andere Form, die auch funktioniert, ist:

$http.post('request-url',  { params: { paramName: value } });

Stellen Sie sicher, dass paramNameder Name des Parameters der aufgerufenen Funktion genau übereinstimmt.

Quelle: AngularJS-Post-Shortcut-Methode

Marco Lackovic
quelle
5
Kann jemand erklären, warum diese Antwort abgelehnt wurde?
Marco Lackovic
1
Es gibt keine Möglichkeit, dass diese Lösung abgelehnt
ainasiart
1

Ich habe dies durch folgende Codes gelöst:

Client Side (Js):

     $http({
                url: me.serverPath,
                method: 'POST',
                data: data,
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
            }).
                success(function (serverData) {
                    console.log("ServerData:", serverData);
    ......

Beachten Sie, dass Daten ein Objekt sind.

Auf dem Server (ASP.NET MVC):

[AllowCrossSiteJson]
        public string Api()
        {
            var data = JsonConvert.DeserializeObject<AgentRequest>(Request.Form[0]);
            if (data == null) return "Null Request";
            var bl = Page.Bl = new Core(this);

            return data.methodName;
        }

und 'AllowCrossSiteJsonAttribute' wird für domänenübergreifende Anforderungen benötigt:

public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
            base.OnActionExecuting(filterContext);
        }
    }

Hoffe das war nützlich.

pixparker
quelle