AngularJS - $ http.post'un JSON yerine istek parametreleri göndermesinin bir yolu var mı?


116

JQuery'nin gönderi yöntemi aracılığıyla AJAX POST isteği yapan ve şuna benzer eski bir kodum var :

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

requestData sadece bazı temel dize özelliklerine sahip bir javascript nesnesidir.

Öğelerimizi Angular'ı kullanmak için taşıma sürecindeyim ve bu çağrıyı $ http.post ile değiştirmek istiyorum. Aşağıdakileri buldum:

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

Bunu yaptığımda, sunucudan 500 hata yanıtı aldım. Firebug kullanarak bunun istek gövdesini şu şekilde gönderdiğini buldum:

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

Başarılı jQuery $.post, gövdeyi şu şekilde gönderir:

param1=value1&param2=value2&param3=value3

Vurduğum uç nokta JSON değil istek parametreleri bekliyor. Öyleyse sorum şu, $http.postjavascript nesnesini JSON yerine istek parametreleri olarak göndermeyi söylemek mümkün mü? Evet, dizeyi nesneden kendim oluşturabileceğimi biliyorum, ancak Angular'ın kutunun dışında bunun için herhangi bir şey sağlayıp sağlamadığını bilmek istiyorum.

Yanıtlar:


140

Bence paramsyapılandırma parametresi, dizeyi gövde yerine url'ye eklediği için burada çalışmayacaktır, ancak burada Infeligo'nun önerdiği şeyi eklemek için varsayılan bir dönüşümün genel geçersiz kılma örneğidir ( dönüştürmek için örnek olarak jQuery parametresini kullanarak) veri parametresi dizesi).

Global transformRequest işlevini ayarlayın:

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

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

Bu şekilde, $ http.post'a yapılan tüm çağrılar, gövdeyi otomatik olarak jQuery $.postçağrısı tarafından kullanılan aynı param biçimine dönüştürür .

Ayrıca, Content-Type başlığını arama başına veya genel olarak şu şekilde ayarlamak isteyebileceğinizi unutmayın:

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

Çağrı başına örnek küresel olmayan transformRequest:

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

Bir transformRequest işlevine sahip olmaktan başka bir şey olup olmadığını merak ediyordum, ama yok gibi görünüyor. JQuery parametre işlevi hakkında bilgi verdiğiniz için teşekkür ederiz.
dnc253

Küresel olmayan arama başına yöntemi benim için iyi çalışıyor, ancak küresel olarak kurulum yapmaya çalışırken $httpProvider.defaultsçalışmıyor, bununla ilgili herhangi bir ipucu var mı?
Dfr

1
WRT bunu global olarak yapılandırıyor, ben de sorunlar yaşıyorum. Burada verilen parçacığı kullanarak yapmaya çalıştığımda bir hata alıyorum Cannot read property "jquery" of undefined.Bunu nasıl düzeltebilirim? PS. Çağrı başına dönüşümler işe yarar.
kshep92

@ kshep92 Olan şu ki, transformRequest işlevi verisiz bir istek üzerine çağrılıyor, bu nedenle 'veri' tanımsız. 'Return $ .param (data);' öncesinde bir koruma ekledim. Bunu transformRequest işlevinin ilk satırı olarak ekleyin: 'if (data === undefined) return data;' Cevaba yaptığım düzenlemeye bakın.
Jere.Jones


21

Kullanılıyorsa Açısal> = 1.4 , burada her şey özel veya harici dayanmaz buldum en temiz çözüm:

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

Ve sonra bunu uygulamanızın herhangi bir yerinde yapabilirsiniz:

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

Ve doğru olarak verileri serialize param1=value1&param2=value2ve göndermek /requesturlile application/x-www-form-urlencoded; charset=utf-8normalde uç noktaları üzerinde POST istekleri ile beklenen olarak Content-Type başlığına.


17

AngularJS belgelerinden:

params - {Nesne.} - URL'den sonra? key1 = value1 & key2 = value2'ye dönüştürülecek dizelerin veya nesnelerin haritası. Değer bir dize değilse JSONifiye edilecektir.

Yani, parametre olarak dizeyi sağlayın. Bunu istemiyorsanız, dönüşümleri kullanın. Yine belgelerden:

Bu dönüşümü yerel olarak geçersiz kılmak için, dönüştürme işlevlerini yapılandırma nesnesinin transformRequest ve / veya transformResponse özellikleri olarak belirtin. Varsayılan dönüşümleri genel olarak geçersiz kılmak için, $ httpProvider'ın $ httpProvider.defaults.transformRequest ve $ httpProvider.defaults.transformResponse özelliklerini geçersiz kılın.

Daha fazla ayrıntı için belgelere bakın .


Belgelerdeki parametreleri gördüm ve Gloopy'nin bahsettiği gibi, URL'de değil, vücutta ihtiyacım var. JSON yerine parametreleri yapmak için eksik olan bir seçenek veya bir şey olup olmadığını merak ediyordum, ancak sadece transformRequest özelliğini kullanmam gerekiyor gibi görünüyor.
dnc253

15

$.paramJSON verilerini requestData'da serileştirmek için jQuery'nin işlevini kullanın .

Kısacası, sizinkine benzer kod kullanarak:

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

Bunu kullanmak için, AngularJS ile birlikte sayfanıza jQuery eklemelisiniz.


7

Angular 1.4'ten itibaren form verilerini jQuery kullanmadan serileştirebileceğinizi unutmayın.

App.js'de:

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

Ardından kontrol cihazınızda:

$http({
    method: 'POST',
    url: myUrl',
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    data: myData
});

Bu cevap harika. Angular'dan Post ile ilgili 2 ana sorunu ele alır. Başlık doğru ayarlanmalı ve json verilerini serileştirmeniz gerekir. IE8 desteğine ihtiyacınız yoksa 1.4+ veya üzerini kullanın.
mbokil

Bunu yeni uyguladım ve postayla ilgili sorunları çözdü, ancak bu aynı zamanda yamanın çalışma şeklini de değiştiriyor ve $ http.patch () ile ilgili tüm kullanımlarımı bozmuş görünüyor.
Mike Feltman

5

Bu biraz hack olabilir, ancak sorunu önledim ve json'u sunucu tarafında PHP'nin POST dizisine dönüştürdüm:

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

Bu yöntemi kullandım ama nefret ediyorum; ve neden bunu kullanmak zorunda olduğumu anlamam uzun zaman aldı.
meconroy

Dediğim gibi - huysuz hissediyor.
Php'nin

5

$ Resource isteği önbelleğe aldığından, özel http kimlik doğrulaması ayarlama konusunda da sorunlar yaşıyorum.

Çalışması için bunu yaparak mevcut başlıkların üzerine yazmanız gerekir.

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

Umarım birine yardım edebilmişimdir. Bunu anlamak 3 günümü aldı.


Sanırım beni 3 günlük işten kurtardın. Teşekkürler!!! Hala her çağrı için özel bir başlık enjekte edebilmek için istek çağrısını bir şekilde engelleyip engelleyemeyeceğimi anlamaya çalışıyorum.
marcoseu

4

Varsayılan başlıkları değiştirin:

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

Ardından JQuery'nin $.paramyöntemini kullanın :

var payload = $.param({key: value});
$http.post(targetURL, payload);

3
   .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 () {});
    }
  ]);

Bana göre en basit ve en kolayı ... Başka yolları da olabilir
Rohit Luthra

2

Hızlı ayarlama - transformRequest işlevinin genel yapılandırmasında sorun yaşayanlar için, işte Cannot read property 'jquery' of undefinedhatadan kurtulmak için kullandığım kod parçacığı :

$httpProvider.defaults.transformRequest = function(data) {
        return data != undefined ? $.param(data) : null;
    }


0

Bu bütünün birçok kez sorunlu davranışını buldum. Bunu express (yazı yazmadan) ve bodyParser'dan (dt ~ body-ayrıştırıcı yazımlarıyla) kullandım.

Bir dosya yüklemeyi denemedim, bunun yerine bir gönderi dizesinde verilen bir JSON'u yorumlamayı denedim.

request.bodyBasitçe boş bir json oldu ( {}).

Bir sürü araştırmadan sonra nihayet bu benim için çalıştı:

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

application/jsonİstemci tarafından istek dizesindeki içerik türünü vermek de önemli olabilir .


"Kara tavuk" tarzı cevap için özür dilerim, maalesef yazı / düğüm / açısal ortamın şu anki aşamasında ortak olan şey.
peterh - Monica'yı eski durumuna getir

0

AngularJS v1.4.8 + (v1.5.0) için Sözdizimi

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

Örneğin:

    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
                    }
            );
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.