AngularJS-N'importe quel moyen pour $http.post pour envoyer des paramètres de requête au lieu de JSON?

j'ai un vieux code qui fait une requête AJAX POST à travers la méthode de post de jQuery et ressemble à quelque chose comme ceci:

$.post("/foo/bar", requestData,
    function(responseData)
    {
        //do stuff with response
    }

requestData est juste un objet javascript avec quelques propriétés de base de chaîne de caractères.

je suis en train de déplacer nos affaires pour utiliser Angular, et je veux remplacer cet appel avec $http.post. J'ai trouvé ce qui suit:

$http.post("/foo/bar", requestData).success(
    function(responseData) {
        //do stuff with response
    }
});

quand j'ai fait cela, j'ai eu une erreur 500 du serveur. En utilisant Firebug, j'ai trouvé que cela envoyait le corps de la requête comme ceci:

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

jQuery $.post envoie le corps comme ceci:

param1=value1&param2=value2&param3=value3

le point final que je frappe est les paramètres de requête attendus et non JSON. Donc, ma question Est de toute façon de dire à $http.post d'envoyer l'objet javascript comme paramètres de requête au lieu de JSON? Oui, je sais que je pourrais construire le je me pends à l'objet, mais je veux savoir si Angular fournit quoi que ce soit pour ça.

115
demandé sur dnc253 2012-08-30 08:59:51

13 réponses

je pense que le paramètre de configuration params ne fonctionnera pas ici car il ajoute la chaîne à l'url au lieu du corps, mais pour ajouter à ce Qu'Infeligo a suggéré ici est un exemple de surpassement global d'une transformation par défaut (en utilisant jQuery param comme exemple pour convertir les données en chaîne param).

configurer la fonction global transformRequest:

var app = angular.module('myApp');

app.config(function ($httpProvider) {
    $httpProvider.defaults.transformRequest = function(data){
        if (data === undefined) {
            return data;
        }
        return $.param(data);
    }
});

ainsi tous les appels à $http.post transformera automatiquement le corps au format param utilisé par l'appel jQuery $.post .

Note Vous pouvez également définir l'en-tête Content-Type par appel ou globalement comme ceci:

$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';

exemple de transformrequête Non globale par appel:

    var transform = function(data){
        return $.param(data);
    }

    $http.post("/foo/bar", requestData, {
        headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
        transformRequest: transform
    }).success(function(responseData) {
        //do stuff with response
    });
140
répondu Gloopy 2013-08-19 01:12:58

si vous utilisez angulaire > = 1,4 , voici la solution la plus propre que j'ai trouvé qui ne repose sur rien de personnalisé ou externe:

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 alors vous pouvez 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 comme param1=value1&param2=value2 et l'enverra à /requesturl avec l'en-tête de type de contenu application/x-www-form-urlencoded; charset=utf-8 comme il est normalement prévu avec les requêtes POST sur les endpoints.

20
répondu Saeb Amini 2016-05-18 09:50:01

From AngularJS documentation:

params - {Object.} – Carte de chaînes ou d'objets qui sera transformé ?cle1=valeur1&cle2=valeur2 après l'url. si la la valeur n'est pas une chaîne , elle sera Jsonifiée.

ainsi, fournir chaîne comme paramètres. Si vous ne le voulez pas, utilisez les transformations. Encore une fois, à partir de la documentation:

pour outrepasser ces transformation localement, spécifier les fonctions de transformation comme les propriétés transformRequest et/ou transformResponse de la configuration objet. Pour outrepasser globalement les transformations par défaut, Outrepasser le $ httpProvider.défaut.transformRequest et $ httpProvider.défaut.propriétés de transformResponse de la $ httpProvider.

Consultez documentation pour plus de détails.

17
répondu Infeligo 2012-08-30 06:36:58

utilisez la fonction $.param de jQuery pour sérialiser les données JSON dans requestData.

en bref, en utilisant le même code que le vôtre:

$http.post("/foo/bar",
$.param(requestData),
{
    headers:
    {
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
    }
}
).success(
    function(responseData) {
        //do stuff with response
    }
});

pour utiliser ceci, vous devez inclure jQuery dans votre page avec AngularJS.

15
répondu Sagar Bhosale 2013-04-23 17:27:34

notez qu'à partir de L'angle 1.4, vous pouvez sérialiser les données du formulaire sans utiliser jQuery.

Dans l'app.js:

module.run(function($http, $httpParamSerializerJQLike) {
  $http.defaults.transformRequest.unshift($httpParamSerializerJQLike);
});

puis dans votre contrôleur:

$http({
    method: 'POST',
    url: myUrl',
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    data: myData
});
7
répondu Thomas Graziani 2015-12-23 19:50:16

cela pourrait être un peu un piratage, mais j'ai évité le problème et converti le JSON en post array de PHP du côté du serveur:

$_POST = json_decode(file_get_contents('php://input'), true);
5
répondu TimoSolo 2013-11-13 13:41:35

j'ai aussi des problèmes avec la configuration de l'authentification http personnalisée parce que $resource cache la requête.

pour que cela fonctionne, vous devez écraser les en-têtes existants en faisant ceci

var transformRequest = function(data, headersGetter){
  var headers = headersGetter();
  headers['Authorization'] = 'WSSE profile="UsernameToken"';
  headers['X-WSSE'] = 'UsernameToken ' + nonce
  headers['Content-Type'] = 'application/json';
};

return $resource(
  url,
    {
    },
    {
      query: {
        method: 'POST',
        url: apiURL + '/profile',
        transformRequest: transformRequest,
        params: {userId: '@userId'}
      },
    }
);

j'espère que j'ai pu aider quelqu'un. Il m'a fallu 3 jours pour celui-ci.

5
répondu Frank Marcelo 2016-06-16 17:13:32

Modifier les en-têtes par défaut:

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

puis utiliser la méthode $.param de JQuery:

var payload = $.param({key: value});
$http.post(targetURL, payload);
4
répondu Zags 2014-11-30 19:58:07
   .controller('pieChartController', ['$scope', '$http', '$httpParamSerializerJQLike', function($scope, $http, $httpParamSerializerJQLike) {
        var data = {
                TimeStamp : "2016-04-25 12:50:00"
        };
        $http({
            method: 'POST',
            url: 'serverutilizationreport',
            headers: {'Content-Type': 'application/x-www-form-urlencoded'},
            data: $httpParamSerializerJQLike(data),
        }).success(function () {});
    }
  ]);
3
répondu Rohit Luthra 2016-05-04 10:01:48

ajustement rapide - pour ceux qui ont des problèmes avec la configuration globale de la fonction transformRequest, voici l'extrait que j'utilise pour me débarrasser de l'erreur Cannot read property 'jquery' of undefined :

$httpProvider.defaults.transformRequest = function(data) {
        return data != undefined ? $.param(data) : null;
    }
2
répondu kshep92 2013-01-21 00:43:19

vous pouvez également résoudre ce problème sans changer de code dans le serveur, en changeant l'en-tête dans $http.post appeler et utiliser $_POST de la manière régulière. Expliqué ici: http://victorblog.com/2012/12/20/make-angularjs-http-service-behave-like-jquery-ajax /

1
répondu vikramaditya234 2015-02-12 01:17:19

j'ai trouvé plusieurs fois le comportement problématique de cet ensemble. Je l'ai utilisé depuis express (sans fautes de frappe) et le bodyParser (avec les fautes de frappe dt~body-parser).

Je n'ai pas essayé de télécharger un fichier, mais simplement d'interpréter un JSON donné dans une chaîne de caractères.

le request.body était simplement un json vide ( {} ).

après beaucoup d'enquête finalement cela a fonctionné pour moi:

import { json } from 'body-parser';
...
app.use(json()); <-- should be defined before the first POST handler!

It peut être aussi important de donner le type de contenu application/json dans la chaîne de requête du côté client.

0
répondu peterh 2016-09-02 14:39:39

syntaxe pour AngularJS v1.4.8 + (v1.5.0)

       $http.post(url, data, config)
            .then(
                    function (response) {
                        // success callback
                    },
                    function (response) {
                        // failure callback
                    }
            );

par exemple:

    var url = "http://example.com";

    var data = {
        "param1": "value1",
        "param2": "value2",
        "param3": "value3"
    };

    var config = {
        headers: {
            'Content-Type': "application/json"
        }
    };

    $http.post(url, data, config)
            .then(
                    function (response) {
                        // success callback
                    },
                    function (response) {
                        // failure callback
                    }
            );
0
répondu Pranav V R 2018-06-28 18:54:31