AngularJS - $ http.post发送请求参数而不是JSON的任何方式?

时间:2012-08-30 04:59:52

标签: javascript jquery post angularjs

我有一些旧代码通过jQuery's post method发出AJAX POST请求,看起来像这样:

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

requestData只是一个带有一些基本字符串属性的javascript对象。

我正在将我们的东西移动到使用Angular,我想用$ http.post替换这个调用。我想出了以下内容:

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

当我这样做时,我收到了来自服务器的500错误响应。使用Firebug,我发现这样就发送了请求体:

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

成功的jQuery $.post发送身体如下:

param1=value1&param2=value2&param3=value3

我遇到的端点是期望请求参数而不是JSON。所以,我的问题是,无论如何要告诉$http.post将javascript对象作为请求参数而不是JSON发送?是的,我知道我可以自己从对象构造字符串,但我想知道Angular是否提供了开箱即用的任何内容。

13 个答案:

答案 0 :(得分:140)

我认为params配置参数在这里不起作用,因为它将字符串添加到url而不是body,但是添加到Infeligo建议的是全局覆盖默认变换的示例(使用jQuery param作为示例将数据转换为param字符串)。

设置全局transformRequest函数:

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

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

这样所有对$ http.post的调用都会自动将主体转换为jQuery $.post调用所使用的相同param格式。

请注意,您可能还希望为每次调用设置Content-Type标头,或者像这样全局设置:

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

每次调用示例非全局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
    });

答案 1 :(得分:20)

如果使用 Angular> = 1.4 ,这是我发现的最简洁的解决方案,它不依赖于自定义或外部的任何内容:

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

然后您可以在应用中的任何位置执行此操作:

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

它会将数据正确序列化为param1=value1&param2=value2并将其发送到/requesturl,并使用application/x-www-form-urlencoded; charset=utf-8 Content-Type标头,因为它通常在端点上使用POST请求。

答案 2 :(得分:17)

来自AngularJS文档:

  

params - {Object。} - 字符串或对象的映射   将在url之后转到?key1 = value1& key2 = value2。 如果   值不是字符串,它将是JSONified。

因此,请提供字符串作为参数。如果您不想这样,那么使用转换。再次,从文档:

  

要在本地覆盖这些转换,请指定转换函数   作为配置的transformRequest和/或transformResponse属性   宾语。要全局覆盖默认转换,请覆盖   $ httpProvider.defaults.transformRequest和   $ httpProvider.defaults.transformResponse的属性   $ httpProvider。

有关详细信息,请参阅documentation

答案 3 :(得分:15)

使用jQuery的$.param函数序列化requestData中的JSON数据。

简而言之,使用与您类似的代码:

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

要使用此功能,您必须在页面中包含jQuery以及AngularJS。

答案 4 :(得分:7)

请注意,从Angular 1.4开始,您可以在不使用jQuery的情况下序列化表单数据。

在app.js中:

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

然后在你的控制器中:

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

答案 5 :(得分:5)

我在设置自定义http身份验证时遇到问题,因为$ resource会缓存请求。

要使其正常工作,您必须通过执行此操作覆盖现有标头

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

我希望我能帮助别人。我花了3天的时间才想出这个。

答案 6 :(得分:5)

这可能是一个黑客,但我避免了这个问题,并将json转换为服务器端的PHP的POST数组:

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

答案 7 :(得分:4)

修改默认标题:

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

然后使用JQuery的$.param方法:

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

答案 8 :(得分: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 () {});
    }
  ]);

答案 9 :(得分:2)

快速调整 - 对于那些遇到transformRequest函数全局配置问题的人,这里是我用来摆脱Cannot read property 'jquery' of undefined错误的片段:

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

答案 10 :(得分:1)

您也可以在不更改服务器中的代码的情况下解决此问题,在$http.post调用中更改标头并以常规方式使用$_POST。在此解释:http://victorblog.com/2012/12/20/make-angularjs-http-service-behave-like-jquery-ajax/

答案 11 :(得分:0)

我发现很多次这个问题的行为。我从express(没有打字)和bodyParser(使用dt~body-parser typings)中使用它。

我没有尝试上传文件,只是简单地解释帖子字符串中给出的JSON。

request.body只是一个空的json({})。

经过大量调查后,这对我有用:

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

从客户端提供请求字符串中的application/json内容类型也很重要。

答案 12 :(得分:0)

AngularJS v1.4.8 +(v1.5.0)的语法

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

例如:

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