Comment puis-je afficher des données sous forme de données au lieu d'une demande de charge utile?

dans le code ci-dessous, la méthode AngularJS $http appelle L'URL, et soumet l'objet xsrf comme" Request Payload " (comme décrit dans L'onglet Réseau du débogueur Chrome). La méthode jQuery $.ajax fait le même appel, mais soumet xsrf comme"Form Data".

Comment puis-je faire soumettre des AngularJS xsrf comme données de formulaire au lieu d'une charge utile de demande?

var url = 'http://somewhere.com/';
var xsrf = {fkey: 'xsrf key'};

$http({
    method: 'POST',
    url: url,
    data: xsrf
}).success(function () {});

$.ajax({
    type: 'POST',
    url: url,
    data: xsrf,
    dataType: 'json',
    success: function() {}
});
507
demandé sur Damjan Pavlica 2012-07-12 02:44:10

22 réponses

la ligne suivante doit être ajoutée à l'objet $http qui est passé:

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

et les données transmises doivent être converties en une chaîne de caractères encodée par URL:

> $.param({fkey: "key"})
'fkey=key'

donc vous avez quelque chose comme:

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

de: https://groups.google.com/forum/#!msg / angular/5nAedJ1LyO0/4vj_72ezcdj

UPDATE

pour utiliser de nouveaux services ajouté avec AngularJS V1.4, Voir

594
répondu mjibson 2018-08-29 06:50:09

Si vous ne voulez pas utiliser jQuery dans la solution, vous pouvez essayer ce. Solution retenue d'ici https://stackoverflow.com/a/1714899/1784301

$http({
    method: 'POST',
    url: url,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    transformRequest: function(obj) {
        var str = [];
        for(var p in obj)
        str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
        return str.join("&");
    },
    data: xsrf
}).success(function () {});
192
répondu Anthony 2017-05-23 11:55:01

la confusion persistante entourant cette question m'a inspiré à écrire un billet de blog à ce sujet. La solution que je propose dans ce post est meilleure que votre solution actuelle top rated parce qu'elle ne vous limite pas à paramétrer votre objet de données pour les appels de service $http; i.e. avec ma solution, vous pouvez simplement continuer à passer des objets de données réels à $http.post(), etc. et encore obtenir le résultat souhaité.

aussi, la réponse la mieux cotée repose sur l'inclusion de la pleine jQuery dans la page pour les $.param () fonction, alors que ma solution est agnostique jQuery, AngularJS pur prêt.

http://victorblog.com/2012/12/20/make-angularjs-http-service-behave-like-jquery-ajax /

Espérons que cette aide.

91
répondu Ezekiel Victor 2012-12-21 12:07:16

j'ai pris quelques-unes des autres réponses et fait quelque chose d'un peu plus propre, mettre ce .config() appel à la fin de votre angle.module dans votre application.js:

.config(['$httpProvider', function ($httpProvider) {
  // Intercept POST requests, convert to standard form encoding
  $httpProvider.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
  $httpProvider.defaults.transformRequest.unshift(function (data, headersGetter) {
    var key, result = [];

    if (typeof data === "string")
      return data;

    for (key in data) {
      if (data.hasOwnProperty(key))
        result.push(encodeURIComponent(key) + "=" + encodeURIComponent(data[key]));
    }
    return result.join("&");
  });
}]);
82
répondu kzar 2015-07-14 08:52:14

As of AngularJS v1.4.0, Il existe un service $httpParamSerializer intégré qui convertit n'importe quel objet en une partie D'une requête HTTP selon les règles qui sont énumérées sur la page docs .

Il peut être utilisé comme ceci:

$http.post('http://example.com', $httpParamSerializer(formDataObj)).
    success(function(data){/* response status 200-299 */}).
    error(function(data){/* response status 400-999 */});

rappelez-vous que pour un message de formulaire correct, l'en-tête Content-Type doit être changé. Pour ce faire globalement pour toutes les requêtes POST, ce code (tiré de la demi-réponse D'Albireo) peut être utilisé:

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

pour ce faire uniquement pour le post courant, la propriété headers de la requête-objet doit être modifiée:

var req = {
 method: 'POST',
 url: 'http://example.com',
 headers: {
   'Content-Type': 'application/x-www-form-urlencoded'
 },
 data: $httpParamSerializer(formDataObj)
};

$http(req);
57
répondu Mitja 2015-06-01 19:57:20

vous pouvez définir le comportement globalement:

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

donc vous n'avez pas à le redéfinir à chaque fois:

$http.post("/handle/post", {
    foo: "FOO",
    bar: "BAR"
}).success(function (data, status, headers, config) {
    // TODO
}).error(function (data, status, headers, config) {
    // TODO
});
24
répondu Albireo 2013-07-02 15:25:52

comme une solution de contournement, vous pouvez simplement faire le code qui reçoit le message Répondre aux données application/json. Pour PHP j'ai ajouté le code ci-dessous, me permettant de le poster soit en forme-encodé ou JSON.

//handles JSON posted arguments and stuffs them into $_POST
//angular's $http makes JSON posts (not normal "form encoded")
$content_type_args = explode(';', $_SERVER['CONTENT_TYPE']); //parse content_type string
if ($content_type_args[0] == 'application/json')
  $_POST = json_decode(file_get_contents('php://input'),true);

//now continue to reference $_POST vars as usual
20
répondu James Bell 2013-11-08 22:57:52

ces réponses ressemblent à de la folie excessive, parfois, simple est juste mieux:

$http.post(loginUrl, "userName=" + encodeURIComponent(email) +
                     "&password=" + encodeURIComponent(password) +
                     "&grant_type=password"
).success(function (data) {
//...
16
répondu Serj Sagan 2015-03-24 09:19:28

vous pouvez essayer avec la solution ci-dessous

$http({
        method: 'POST',
        url: url-post,
        data: data-post-object-json,
        headers: {'Content-Type': 'application/x-www-form-urlencoded'},
        transformRequest: function(obj) {
            var str = [];
            for (var key in obj) {
                if (obj[key] instanceof Array) {
                    for(var idx in obj[key]){
                        var subObj = obj[key][idx];
                        for(var subKey in subObj){
                            str.push(encodeURIComponent(key) + "[" + idx + "][" + encodeURIComponent(subKey) + "]=" + encodeURIComponent(subObj[subKey]));
                        }
                    }
                }
                else {
                    str.push(encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]));
                }
            }
            return str.join("&");
        }
    }).success(function(response) {
          /* Do something */
        });
9
répondu tmquang6805 2013-10-09 11:00:31

créer un service d'adaptateur pour la poste:

services.service('Http', function ($http) {

    var self = this

    this.post = function (url, data) {
        return $http({
            method: 'POST',
            url: url,
            data: $.param(data),
            headers: {'Content-Type': 'application/x-www-form-urlencoded'}
        })
    }

}) 

utilisez - le dans vos contrôleurs ou autre:

ctrls.controller('PersonCtrl', function (Http /* our service */) {
    var self = this
    self.user = {name: "Ozgur", eMail: null}

    self.register = function () {
        Http.post('/user/register', self.user).then(function (r) {
            //response
            console.log(r)
        })
    }

})
8
répondu Ozgur 2016-05-16 23:41:34

il y a un très joli tutoriel qui passe en revue ce sujet et d'autres choses connexes - soumettre des formulaires AJAX: la voie AngularJS .

fondamentalement, vous devez définir l'en-tête de la demande de poste pour indiquer que vous envoyez des données de formulaire comme une chaîne de caractères encodée URL, et de définir les données à envoyer le même format

$http({
  method  : 'POST',
  url     : 'url',
  data    : $.param(xsrf),  // pass in data as strings
  headers : { 'Content-Type': 'application/x-www-form-urlencoded' }  // set the headers so angular passing info as form data (not request payload)
});

notez que la fonction d'aide param() de jQuery est utilisée ici pour sérialiser les données dans une chaîne, mais vous pouvez le faire manuellement si vous n'utilisez pas jQuery.

7
répondu robinmitra 2014-07-02 12:33:34
var fd = new FormData();
    fd.append('file', file);
    $http.post(uploadUrl, fd, {
        transformRequest: angular.identity,
        headers: {'Content-Type': undefined}
    })
    .success(function(){
    })
    .error(function(){
    });

please check out! https://uncorkedstudios.com/blog/multipartformdata-file-upload-with-angularjs

6
répondu aul 2015-04-29 10:14:13

pour les utilisateurs de Symfony2:

si vous ne voulez pas changer quoi que ce soit dans votre javascript pour que cela fonctionne, vous pouvez faire ces modifications dans votre application symfony:

créer une classe qui étend Symfony\Component\HttpFoundation\Request class:

<?php

namespace Acme\Test\MyRequest;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\ParameterBag;

class MyRequest extends Request{


/**
* Override and extend the createFromGlobals function.
* 
* 
*
* @return Request A new request
*
* @api
*/
public static function createFromGlobals()
{
  // Get what we would get from the parent
  $request = parent::createFromGlobals();

  // Add the handling for 'application/json' content type.
  if(0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/json')){

    // The json is in the content
    $cont = $request->getContent();

    $json = json_decode($cont);

    // ParameterBag must be an Array.
    if(is_object($json)) {
      $json = (array) $json;
  }
  $request->request = new ParameterBag($json);

}

return $request;

}

}

utilisez maintenant votre classe dans app_dev.php (ou tout fichier d'index que vous utilisez)

// web/app_dev.php

$kernel = new AppKernel('dev', true);
// $kernel->loadClassCache();
$request = ForumBundleRequest::createFromGlobals();

// use your class instead
// $request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);
4
répondu carmel 2013-11-05 09:37:54

il ne suffit pas de définir le type de contenu, l'url encodent les données du formulaire avant l'envoi. $http.post(url, jQuery.param(data))

3
répondu Merlin Ran 2013-10-01 09:12:19

j'utilise actuellement la solution suivante i trouvé dans le groupe Google AngularJS.

$http
.post('/echo/json/', 'json=' + encodeURIComponent(angular.toJson(data)), {
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
    }
}).success(function(data) {
    $scope.data = data;
});

notez que si vous utilisez PHP, vous devrez utiliser quelque chose comme le composant HTTP Request::createFromGlobals() de Symfony 2 pour lire ceci, car $_POST ne sera pas automatiquement chargé avec.

3
répondu Aditya M P 2013-10-15 23:02:22

AngularJS le fait correctement en faisant le type de contenu suivant à l'intérieur de l'en-tête http-request:

Content-Type: application/json

si vous allez avec php comme moi, ou même avec Symfony2 vous pouvez simplement étendre votre compatibilité de serveur pour la norme json comme décrit ici: http://silex.sensiolabs.org/doc/cookbook/json_request_body.html

La Symfony2 (par exemple à l'intérieur de votre DefaultController):

$request = $this->getRequest();
if (0 === strpos($request->headers->get('Content-Type'), 'application/json')) {
    $data = json_decode($request->getContent(), true);
    $request->request->replace(is_array($data) ? $data : array());
}
var_dump($request->request->all());

l'avantage serait, que vous n'avez pas besoin d'utiliser jQuery param et vous pourriez utiliser AngularJS sa façon native de faire de telles requêtes.

2
répondu Michael 2013-07-22 10:27:08

réponse complète (depuis l'angle 1,4). Vous devez inclure la dépendance $httpParamSerializer

var res = $resource(serverUrl + 'Token', { }, {
                save: { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
            });

            res.save({ }, $httpParamSerializer({ param1: 'sdsd', param2: 'sdsd' }), function (response) {

            }, function (error) { 

            });
2
répondu Sebastián Rojas 2015-11-20 21:46:28

dans votre application config -

$httpProvider.defaults.transformRequest = function (data) {
        if (data === undefined)
            return data;
        var clonedData = $.extend(true, {}, data);
        for (var property in clonedData)
            if (property.substr(0, 1) == '$')
                delete clonedData[property];

        return $.param(clonedData);
    };

Avec votre demande de ressource -

 headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            }
1
répondu Vivek 2015-06-14 17:46:43

ce n'est pas une réponse directe, mais plutôt une direction de conception légèrement différente:

ne pas afficher les données comme une forme, mais comme un objet JSON pour être directement mappé à un objet côté serveur, ou utiliser la variable REST style path

maintenant je sais qu'aucune option ne pourrait être appropriée dans votre cas puisque vous essayez de passer une clé XSRF. Le Mapping dans une variable de chemin comme celle-ci est un dessin terrible:

http://www.someexample.com/xsrf/{xsrfKey}

parce que par nature vous voudriez passer la touche xsrf à d'autres chemins aussi, /login , /book-appointment etc. et vous ne voulez pas gâcher votre URL jolie

il est intéressant de l'ajouter comme champ objet n'est pas approprié non plus, parce que maintenant sur chacun des objets json que vous passez au serveur vous devez ajouter le champ

{
  appointmentId : 23,
  name : 'Joe Citizen',
  xsrf : '...'
}

vous ne voulez certainement pas ajouter un autre champ sur votre classe côté serveur qui n'a pas d'association sémantique directe avec le domaine de l'objet.

à mon avis, la meilleure façon de passer votre clé xsrf est via un en-tête HTTP. De nombreuses bibliothèques de cadres web Côté Serveur de protection XSRF prennent en charge cette fonction. par exemple en Java Spring, vous pouvez le passer en utilisant X-CSRF-TOKEN en-tête .

excellente capacité D'Angular de lier l'objet JS à L'objet UI signifie que nous pouvons nous débarrasser de la pratique de poster forme tous ensemble, et post JSON à la place. JSON peut être facilement dé-sérialisé dans l'objet côté serveur et soutient des structures de données complexes telles que la carte, les tableaux, les objets imbriqués, etc.

Comment afficher un tableau dans un formulaire de charge utile? Peut-être comme ceci:

shopLocation=downtown&daysOpen=Monday&daysOpen=Tuesday&daysOpen=Wednesday

ou ceci:

shopLocation=downtwon&daysOpen=Monday,Tuesday,Wednesday

tous les deux sont de mauvaise conception..

0
répondu gerrytan 2015-02-26 11:47:42

C'est ce que je fais pour répondre à mes besoins, où je dois envoyer les données de connexion à L'API comme données de forme et L'objet Javascript (userData) est converti automatiquement en données encodées URL

        var deferred = $q.defer();
        $http({
            method: 'POST',
            url: apiserver + '/authenticate',
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
            transformRequest: function (obj) {
                var str = [];
                for (var p in obj)
                    str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
                return str.join("&");
            },
            data: userData
        }).success(function (response) {
            //logics
            deferred.resolve(response);
        }).error(function (err, status) {
           deferred.reject(err);
        });

Ce comment mon Userdata est

var userData = {
                grant_type: 'password',
                username: loginData.userName,
                password: loginData.password
            }
0
répondu Shubham 2018-06-25 07:56:42

la seule chose que vous devez changer est d'utiliser la propriété "params" plutôt que" data "lorsque vous créez votre objet $http:

$http({
   method: 'POST',
   url: serviceUrl + '/ClientUpdate',
   params: { LangUserId: userId, clientJSON: clients[i] },
})

dans l'exemple ci-dessus clients[i] est juste un objet JSON (non sérialisé d'une quelconque manière). Si vous utilisez "params" plutôt que" data "angular va sérialiser l'objet pour vous en utilisant $httpParamSerializer: https://docs.angularjs.org/api/ng/service/ $httpParamSerializer

-1
répondu Rafal Zajac 2015-07-13 16:05:17

utiliser AngularJS $http service et utiliser sa post méthode ou configurer $http fonction.

-3
répondu Shivang Gupta 2014-12-30 09:28:41