AngularJs $ http.post () n'envoie pas de données

337

Quelqu'un pourrait-il me dire pourquoi la déclaration suivante n'envoie pas les données de publication à l'URL désignée? L'URL est appelée mais sur le serveur lorsque j'imprime $ _POST - j'obtiens un tableau vide. Si j'imprime un message dans la console avant de l'ajouter aux données, il affiche le contenu correct.

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

Je l'ai également essayé avec les données sous forme de chaîne (avec le même résultat):

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

Il semble fonctionner lorsque je l'utilise dans le format suivant:

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

mais existe-t-il un moyen de le faire avec $ http.post () - et dois-je toujours inclure l'en-tête pour que cela fonctionne? Je crois que le type de contenu ci-dessus spécifie le format des données envoyées, mais puis-je les envoyer en tant qu'objet javascript?

Spencer Mark
la source
L'URL a-t-elle la même origine?
fmquaglia
Désolé - oui pour tous les exemples, c'est la même URL
Spencer Mark
@SpencerMark désolé .. j'ai essayé au-dessus de votre code de travail .. ça ne fonctionne pas pour moi.
Arul Sidthan

Réponses:

346

J'ai eu le même problème en utilisant asp.net MVC et j'ai trouvé la solution ici

Il y a beaucoup de confusion parmi les nouveaux arrivants à AngularJS quant à la raison pour laquelle les $httpfonctions de raccourci de service ( $http.post(), etc.) ne semblent pas être échangeables avec les équivalents jQuery (jQuery.post() , etc.)

La différence réside dans la façon dont jQuery et AngularJS sérialisent et transmettent les données. Fondamentalement, le problème réside dans le fait que la langue de votre serveur de choix est incapable de comprendre la transmission d'AngularJS de manière native ... Par défaut, jQuery transmet les données en utilisant

Content-Type: x-www-form-urlencoded

et la foo=bar&baz=moesérialisation familière .

AngularJS , cependant, transmet des données en utilisant

Content-Type: application/json 

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

La sérialisation JSON, qui malheureusement, certains langages de serveur Web - notamment PHP - ne désérialisent pas nativement.

Fonctionne comme un charme.

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
la source
7
J'ai ajouté ce script à Bower, utilisez-le bower install angular-post-fix --save-devpour l'ajouter.
Billy Blaze
existe-t-il donc un moyen de changer la méthode de transmission des données de php. Parce que c'est le problème que j'ai actuellement.
Demodave
1
Ce code fonctionne très bien dans la plupart des cas, mais j'ai eu des problèmes avec lui lors de la soumission d'une hiérarchie d'objets vides ou même de valeurs vides à plat. Par exemple, {a: 1, b: {c: {d: {}}}, e: undefined, f: null, g: 2} ne seront pas encodés correctement, et PHP les obtiendra comme ["a" = > "1", "g" => "2"]. La structure entière sous "b", ainsi que "e" et "f", y compris les clés elles-mêmes - serait perdue. J'ai posté un code alternatif ci-dessous, avec lequel la structure ci-dessus est décodée comme: ["a" => "1", "b" => ["c" => ["d" => ""]], "e" => "", "f" => "", "g" => "2"].
obe
1
comment dois-je l'implémenter pour les données en plusieurs parties / formulaires?
davidlee
Superbe :) En effet a fonctionné comme un charme. J'ai rencontré le problème avec Spring MVC
SKaul
115

Ce n'est pas très clair ci-dessus, mais si vous recevez la demande en PHP, vous pouvez utiliser:

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

Pour accéder à un tableau en PHP à partir d'un POST AngularJS.

Don F
la source
3
J'avais besoin d'ajouter true pour le forcer à un tableau lors de l'écrasement du tableau $ _POST avec lui. json_decode(file_get_contents('php://input'), true);
Jon
4
@Zalaboza, je conviens qu'il est difficile d'avoir une solution considérée comme "universelle" mais je ne suis pas d'accord pour dire qu'elle est "hacky" --- php.net déclare: "file_get_contents () est la façon préférée de lire le contenu d'un fichier dans une chaîne. Il utilisera des techniques de mappage de la mémoire s'il est pris en charge par votre système d'exploitation pour améliorer les performances. " Certes, nous ne lisons pas un fichier dans cette situation, mais nous lisons néanmoins les données json publiées. Ce serait formidable si vous pouviez apporter une nouvelle réponse ou fournir de nouvelles informations pour aider les lecteurs (y compris moi-même) à prendre une meilleure décision à ce sujet.
Don F
78

Vous pouvez définir le "Content-Type" par défaut comme ceci:

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

À propos du dataformat:

Les méthodes $ http.post et $ http.put acceptent toute valeur d'objet JavaScript (ou une chaîne) comme paramètre de données. Si les données sont un objet JavaScript, elles seront, par défaut, converties en chaîne JSON.

Essayez d'utiliser cette variation

function sendData($scope) {
    $http({
        url: 'request-url',
        method: "POST",
        data: { 'message' : message }
    })
    .then(function(response) {
            // success
    }, 
    function(response) { // optional
            // failed
    });
}
Denison Luz
la source
9
Cela ne semble pas fonctionner. Je viens d'essayer la variation avec les données sous forme de chaîne et: headers: {'Content-Type': 'application / x-www-form-urlencoded'} - et cela semble fonctionner, mais y a-t-il une meilleure façon de faire il?
Spencer Mark
2
Définissez le type de contenu par défaut comme décrit ci-dessus et pour les données, n'utilisez pas d'objet js. Utilisez une chaîne comme celle-ci: 'message =' + message Works for me
gSorry
58

J'ai eu un problème similaire, et je me demande si cela peut aussi être utile: 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'}
})

Cordialement,

ericson.cepeda
la source
Il semble que les en-têtes étaient le seul changement dont nous avions besoin. Je vous remercie!
Ben Guthrie
Merci, ça l'a fait pour moi :) Le problème était l'encodage des données POST.
Daan
33

J'aime utiliser une fonction pour convertir des objets en paramètres de publication.

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
la source
30

Cela a finalement été résolu dans angular 1.4 en utilisant $ httpParamSerializerJQLike

Voir 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
la source
Je suis confronté au problème POST 192.168.225.75:7788/procure/p/search 400 (Bad Request)
Anuj
19

J'utilise jQuery param avec AngularJS post requrest. Voici un exemple ... créer le module d'application AngularJS, où myappest défini avec ng-appdans votre code HTML.

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

Créons maintenant un contrôleur de connexion et un e-mail et un mot de passe POST.

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

Je n'aime pas expliquer le code, il est assez simple à comprendre :) Notez que cela paramvient de jQuery, vous devez donc installer à la fois jQuery et AngularJS pour le faire fonctionner. Voici une capture d'écran.

entrez la description de l'image ici

J'espère que cela vous sera utile. Merci!

Madan Sapkota
la source
10

J'ai eu le même problème avec AngularJS et Node.js + Express 4 + Router

Le routeur attend les données de la demande du message dans le corps. Ce corps était toujours vide si je suivais l'exemple de Angular Docs

Notation 1

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

Mais si je l'ai utilisé dans les données

Notation 2

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

Modifier 1:

Sinon, le routeur node.js attendra les données dans req.body si utilisé la notation 1:

req.body.msg

Qui envoie également les informations sous forme de charge utile JSON. C'est mieux dans certains cas où vous avez des tableaux dans votre json et x-www-form-urlencoded donnera quelques problèmes.

ça a marché. J'espère que ça aide.

alknows
la source
10

Contrairement à JQuery et pour des raisons de pédanterie, Angular utilise le format JSON pour le transfert de données POST d'un client vers le serveur (JQuery applique x-www-form-urlencoded vraisemblablement, bien que JQuery et Angular utilise JSON pour l'imputation de données). Il y a donc deux parties de problème: dans la partie client js et dans la partie serveur. Il vous faut donc:

  1. mettre la partie client js Angular comme ceci:

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

ET

  1. écrivez dans votre partie serveur pour recevoir des données d'un client (si c'est php).

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

Remarque: $ _POST ne fonctionnera pas!

La solution fonctionne bien pour moi, je l'espère, et pour vous.

romain
la source
8

Pour envoyer des données via la méthode Post avec $httpangularjs, vous devez modifier

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

BERGUIGA Mohamed Amine
la source
1
pourquoi les données: $ .param sont-elles requises lors de l'envoi des données de publication AngularJS?
ciel bleu
7

Pour s'appuyer sur la réponse de @ felipe-miosso:

  1. Téléchargez-le en tant que module AngularJS à partir d' ici ,
  2. Installez-le
  3. Ajoutez-le à votre application:

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

Je n'ai pas la réputation de commenter, mais en réponse / ajout à la réponse de Don F:

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

Un deuxième paramètre de truedoit être ajouté à la json_decodefonction afin de renvoyer correctement un tableau associatif:

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

Esten
la source
6

Angulaire

  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
la source
5

Ce code a résolu le problème pour moi. Il s'agit d'une solution au niveau de l'application:

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
la source
5

Ajoutez ceci dans votre fichier js:

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

et ajoutez ceci à votre fichier serveur:

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

Cela devrait fonctionner.

Jesus Erwin Suarez
la source
4

J'ai également fait face à un problème similaire et je faisais quelque chose comme ça et cela n'a pas fonctionné. Mon contrôleur Spring n'a pas pu lire le paramètre de données.

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

Mais en lisant ce forum et l'API Doc, j'ai essayé de suivre la voie et cela a fonctionné pour moi. Si quelqu'un a également un problème similaire, vous pouvez également essayer ci-dessous.

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

Veuillez consulter https://docs.angularjs.org/api/ng/service/ $ http # post pour savoir ce que fait la configuration param. {data: '"id": "1"'} - Carte des chaînes ou des objets qui seront convertis en URL? data = "id: 1"

Viraj
la source
4

c'est probablement une réponse tardive mais je pense que la façon la plus appropriée est d'utiliser le même morceau de code pour une utilisation angulaire lors d'une requête "get", vous $httpParamSerializerdevrez l'injecter à votre contrôleur afin que vous puissiez simplement faire ce qui suit sans avoir à utiliser Jquery du tout, $http.post(url,$httpParamSerializer({param:val}))

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

Dans mon cas, je résous le problème comme ceci:

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;

Vous devez utiliser JSON.stringify pour chaque paramètre contenant un objet JSON, puis créer votre objet de données avec "$ .param" :-)

NB: Mon "objJSON" est un objet JSON contenant un tableau, un entier, une chaîne et du contenu html. Sa taille totale est> 3500 caractères.

bArraxas
la source
3

Je sais qu'il a accepté la réponse. Mais, suivre pourrait aider les futurs lecteurs, si la réponse ne leur convient pas pour une raison quelconque.

Angular ne fait pas ajax comme jQuery. Pendant que j'essayais de suivre le guide pour modifier angulaire $httpprovider, j'ai rencontré d'autres problèmes. Par exemple, j'utilise codeigniter dans lequel la $this->input->is_ajax_request()fonction échouait toujours (qui a été écrite par un autre programmeur et utilisée globalement, donc je ne peux pas changer) en disant que ce n'était pas une vraie demande ajax.

Pour le résoudre, j'ai pris l'aide d'une promesse différée . Je l'ai testé dans Firefox, ie9 et cela a fonctionné.

J'ai la fonction suivante définie en dehors de tout code angulaire. Cette fonction effectue un appel jquery ajax régulier et renvoie un objet différé / promis (j'apprends toujours).

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

Ensuite, je l'appelle du code angulaire en utilisant le code suivant. Veuillez noter que nous devons mettre à jour $scopemanuellement à l'aide de $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!");
    });

Ce n'est peut-être pas la réponse parfaite, mais cela m'a permis d'utiliser des appels jquery ajax avec angular et m'a permis de mettre à jour le $scope.

Nis
la source
2
Angular a son propre service de promesses appelé $ q depuis la 1.3. Pas besoin d'utiliser JQuery pour une publication.
mbokil
3

J'ai eu le même problème en express .. pour résoudre, vous devez utiliser bodyparser pour analyser les objets json avant d'envoyer des requêtes http ..

app.use(bodyParser.json());
Muhammad Soliman
la source
3

J'utilise les services Web WCF asp.net avec js angulaire et le code ci-dessous a fonctionné:

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

J'espère que ça aide.

Mehdi Rostami
la source
3

Je n'ai pas trouvé d'extrait de code complet expliquant comment utiliser la méthode $ http.post pour envoyer des données au serveur et pourquoi cela ne fonctionnait pas dans ce cas.

Explications de l'extrait de code ci-dessous ...

  1. J'utilise la fonction jQuery $ .param pour sérialiser les données JSON en www post data
  2. Définition du Content-Type dans la variable de configuration qui sera transmise avec la demande de angularJS $ http.post qui indique au serveur que nous envoyons les données au format www post.

  3. Remarquez la méthode $ htttp.post, où j'envoie le 1er paramètre comme URL, le 2ème paramètre comme données (sérialisées) et le 3ème paramètre comme config.

Le code restant est auto-compris.

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

Regardez l'exemple de code de la méthode $ http.post ici .

Sheo Narayan
la source
3

Si vous utilisez PHP, c'est un moyen facile d'accéder à un tableau en PHP à partir d'un POST AngularJS.

$params = json_decode(file_get_contents('php://input'),true);
Luis Felipe Barnett V
la source
Cet article peut aider les gens.
Stéphane
3

Si vous utilisez Angular> = 1.4 , voici la solution la plus propre utilisant le sérialiseur fourni par Angular :

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

Et vous pouvez simplement le faire n'importe où dans votre application:

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

Et il sérialisera correctement les données param1=value1&param2=value2et les enverra /requesturlavec leapplication/x-www-form-urlencoded; charset=utf-8 -tête Content-Type comme cela est normalement prévu avec les requêtes POST sur les points de terminaison.

TL; DR

Au cours de mes recherches, j'ai trouvé que la réponse à ce problème se présente sous de nombreuses saveurs différentes; certains sont très compliqués et dépendent de fonctions personnalisées, certains dépendent de jQuery et et certains sont incomplets en suggérant que vous avez seulement besoin de définir l'en-tête.

Si vous venez de définir l'en- Content-Typetête, le point final verra les données POST, mais elles ne seront pas au format standard car à moins que vous ne fournissiez une chaîne commedata ou sérialisiez manuellement votre objet de données, elles seront toutes sérialisées en JSON par par défaut et peut être mal interprété au point de terminaison.

Par exemple, si le sérialiseur correct n'a pas été défini dans l'exemple ci-dessus, il serait considéré dans le noeud final comme:

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

Et cela peut conduire à une analyse inattendue, par exemple ASP.NET le traite comme un nullnom de paramètre, avec {"param1":"value1","param2":"value2"}comme valeur; ou Fiddler l'interprète dans l'autre sens, avec {"param1":"value1","param2":"value2"}comme nom de paramètre et nullcomme valeur.

Saeb Amini
la source
3

Similaire au format de travail suggéré par l'OP et à la réponse de Denison, sauf en utilisant $http.postau lieu de simplement$http et dépend toujours de jQuery.

La bonne chose à propos de l'utilisation de jQuery ici est que les objets complexes sont correctement passés; contre la conversion manuelle en paramètres d'URL qui peuvent brouiller les données.

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

Quand j'ai eu ce problème, le paramètre que je publiais s'est avéré être un tableau d'objets au lieu d'un simple objet.

D. Kermott
la source
2

Nous venons de mettre à jour angulaire 1.2 à 1.3, ont trouvé un problème dans le code. La transformation d'une ressource entraînera une boucle sans fin à cause (je pense) de la promesse $ détenant à nouveau le même objet. Peut-être que cela aidera quelqu'un ...

Je pourrais résoudre ce problème en:

[...]
  /**
 * 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
la source
2

J'utilise le code de réponse accepté (code de Felipe) depuis un certain temps et cela fonctionne très bien (merci, Felipe!).

Cependant, récemment, j'ai découvert qu'il avait des problèmes avec des objets ou des tableaux vides. Par exemple, lors de la soumission de cet objet:

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

PHP ne semble pas du tout voir B et C. Il obtient ceci:

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

Un regard sur la demande réelle dans Chrome montre ceci:

A: 1
:
D: 2

J'ai écrit un extrait de code alternatif. Il semble bien fonctionner avec mes cas d'utilisation, mais je ne l'ai pas testé de manière approfondie, donc utilisez-le avec prudence.

J'ai utilisé TypeScript parce que j'aime le typage fort mais il serait facile de le convertir en JS pur:

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("&");
    } ];
} ]);

Il est moins efficace que le code de Felipe mais je ne pense pas que cela ait beaucoup d'importance car il devrait être immédiat par rapport à la surcharge globale de la requête HTTP elle-même.

Maintenant PHP montre:

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

Pour autant que je sache, il n'est pas possible d'obtenir PHP pour reconnaître que Ba et C sont des tableaux vides, mais au moins les clés apparaissent, ce qui est important lorsqu'il y a du code qui s'appuie sur une certaine structure même lorsqu'il est essentiellement vide à l'intérieur.

Notez également qu'il convertit les s non définis et les s null en chaînes vides.

obéir
la source
TypeScript la meilleure façon de coder en POO avec JavaScript!
Défigurer
2

Mettez simplement les données que vous souhaitez envoyer comme deuxième paramètre:

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

Une autre forme qui fonctionne également est:

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

Assurez-vous que cela paramNamecorrespond exactement au nom du paramètre de la fonction que vous appelez.

Source: AngularJS post shortcut method

Marco Lackovic
la source
5
Quelqu'un peut-il expliquer pourquoi cette réponse a été rejetée?
Marco Lackovic
1
Il n'y a aucun moyen que cette solution soit rejetée, c'est la plus simple, la plus courte et la plus éprouvée dans la documentation angulaire docs.angularjs.org/api/ng/service/$http
ainasiart
1

J'ai résolu cela par les codes ci-dessous:

Côté client (Js):

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

notez que les données sont un objet.

Sur le serveur (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;
        }

et 'AllowCrossSiteJsonAttribute' est nécessaire pour les demandes interdomaines:

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

J'espère que cela a été utile.

pixparker
la source