我有一些旧代码通过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¶m2=value2¶m3=value3
我遇到的端点是期望请求参数而不是JSON。所以,我的问题是,无论如何要告诉$http.post
将javascript对象作为请求参数而不是JSON发送?是的,我知道我可以自己从对象构造字符串,但我想知道Angular是否提供了开箱即用的任何内容。
答案 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¶m2=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
}
);