AngularJs $http.post () não envia dados
alguém me pode dizer porque é que a seguinte declaração não envia os dados do post para a url designada? O url é chamado, mas no servidor quando eu imprimir $_POST - eu recebo um array vazio. Se eu imprimir a mensagem no console antes de adicioná - la aos dados-ele mostra o conteúdo correto.
$http.post('request-url', { 'message' : message });
eu também tentei com os dados como string (com o mesmo resultado):
$http.post('request-url', "message=" + message);
parece estar a funcionar quando o uso no seguinte formato:
$http({
method: 'POST',
url: 'request-url',
data: "message=" + message,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
});
Mas há uma maneira de a fazê-lo com os $ http.post () - e eu sempre tenho que incluir o cabeçalho para que ele funcione? Eu acredito que o tipo de Conteúdo acima está especificando o formato dos dados enviados, mas posso enviá-lo como objeto javascript?
30 answers
Há muita confusão entre os recém-chegados a AngularJS {[16] } quanto ao porquê do
$http
funções de estenografia de serviço ($http.post()
, etc.) não parecem ser swappable with the jQuery equivalents (jQuery.post()
, etc.)A diferença está em como jQuery e AngularJS serializa e transmite os dados. Fundamentalmente, o problema reside no seu servidor linguagem de escolha sendo incapaz de entender a transmissão AngularJS nativamente ... Por omissão, o jQuery transmite os dados usando
Content-Type: x-www-form-urlencoded
E a familiar
foo=bar&baz=moe
serialização.AngularJS , no entanto, transmite dados usando
Content-Type: application/json
E
{ "foo": "bar", "baz": "moe" }
Serialização JSON, que infelizmente algumas linguagens de servidor Web - notavelmente PHP - Não deserialize nativamente.
Funciona como um charme.
CÓDIGO
// Your app's root module...
angular.module('MyModule', [], function($httpProvider) {
// Use x-www-form-urlencoded Content-Type
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
/**
* The workhorse; converts an object to x-www-form-urlencoded serialization.
* @param {Object} obj
* @return {String}
*/
var param = function(obj) {
var query = '', name, value, fullSubName, subName, subValue, innerObj, i;
for(name in obj) {
value = obj[name];
if(value instanceof Array) {
for(i=0; i<value.length; ++i) {
subValue = value[i];
fullSubName = name + '[' + i + ']';
innerObj = {};
innerObj[fullSubName] = subValue;
query += param(innerObj) + '&';
}
}
else if(value instanceof Object) {
for(subName in value) {
subValue = value[subName];
fullSubName = name + '[' + subName + ']';
innerObj = {};
innerObj[fullSubName] = subValue;
query += param(innerObj) + '&';
}
}
else if(value !== undefined && value !== null)
query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&';
}
return query.length ? query.substr(0, query.length - 1) : query;
};
// Override $http service's default transformRequest
$httpProvider.defaults.transformRequest = [function(data) {
return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data;
}];
});
Não é super claro acima, mas se você está recebendo o pedido em PHP você pode usar:
$params = json_decode(file_get_contents('php://input'),true);
Para aceder a um array em PHP a partir de um post AngularJS.
Você pode definir o "tipo de conteúdo" por omissão como este:
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
Acerca do formato data
:
Os $ http.post e $http.put methods accept any JavaScript object (or a string) value as their data parameter. Se os dados são um objeto JavaScript será, por padrão, convertido para uma string JSON.
Tente usar esta variação
function sendData($scope) {
$http({
url: 'request-url',
method: "POST",
data: { 'message' : message }
})
.then(function(response) {
// success
},
function(response) { // optional
// failed
});
}
Tive um problema semelhante, e pergunto-me se isto também pode ser útil: https://stackoverflow.com/a/11443066
var xsrf = $.param({fkey: "key"});
$http({
method: 'POST',
url: url,
data: xsrf,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
Atenciosamente,
Eu gosto de usar uma função para converter objetos para postar params.
myobject = {'one':'1','two':'2','three':'3'}
Object.toparams = function ObjecttoParams(obj) {
var p = [];
for (var key in obj) {
p.push(key + '=' + encodeURIComponent(obj[key]));
}
return p.join('&');
};
$http({
method: 'POST',
url: url,
data: Object.toparams(myobject),
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
Isto foi finalmente tratado em 1, 4 angular usando $httpParamSerializerJQLike
Ver https://github.com/angular/angular.js/issues/6039
.controller('myCtrl', function($http, $httpParamSerializerJQLike) {
$http({
method: 'POST',
url: baseUrl,
data: $httpParamSerializerJQLike({
"user":{
"email":"[email protected]",
"password":"123456"
}
}),
headers:
'Content-Type': 'application/x-www-form-urlencoded'
})})
Eu uso jQuery param com AngularJS post requrest. Aqui está um exemplo ... crie o módulo de Aplicação AngularJS, onde myapp
é definido com ng-app
no seu código HTML.
var app = angular.module('myapp', []);
Agora vamos criar um controlador de Login e enviar e-mail e senha.
app.controller('LoginController', ['$scope', '$http', function ($scope, $http) {
// default post header
$http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
// send login data
$http({
method: 'POST',
url: 'https://example.com/user/login',
data: $.param({
email: $scope.email,
password: $scope.password
}),
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}).success(function (data, status, headers, config) {
// handle success things
}).error(function (data, status, headers, config) {
// handle error things
});
}]);
Eu não gosto de exaplain o código, é simples o suficiente para entender :) Note que {[[4]} é de jQuery, então você deve instalar tanto jQuery e AngularJS para fazê-lo funcionar. Aqui está um imagem.
Espero que isto seja útil. Obrigado!O Router espera os dados do pedido de post no corpo. Este corpo estava sempre vazio se eu seguisse o exemplo dos documentos angulares
Notação 1
$http.post('/someUrl', {msg:'hello word!'})
Mas se o usei nos dados
Notação 2
$http({
withCredentials: false,
method: 'post',
url: yourUrl,
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
data: postData
});
Editar 1:
Caso contrário, nó.o roteador js espera os dados no req.corpo, se utilizado Notação 1:
req.body.msg
Que também envia a informação como carga JSON. Presente é melhor em alguns casos onde você tem arrays em seu json e x-www-form-urlencoded dará alguns problemas.
Funcionou. Espero que ajude.-
Põe a parte Angular do cliente js assim:
$http({ method: 'POST', url: 'request-url', data: {'message': 'Hello world'} });
E
-
Escreva no seu servidor parte para receber dados de um cliente (se for php).
$data = file_get_contents("php://input"); $dataJsonDecode = json_decode($data); $message = $dataJsonDecode->message; echo $message; //'Hello world'
Nota: $_POST não vai funcionar!
A solução funciona para mim bem, Espero, e para ti.
Para enviar dados através do método de Pós com $http
de angularj, é necessário alterar
data: "message=" + message
, com data: $.param({message:message})
A partir da resposta de @felipe-miosso:
- Faça o Download como um módulo AngularJS a partir de aqui,
- Instale-o
-
Adicione - o à sua aplicação:
var app = angular.module('my_app', [ ... , 'httpPostFix']);
Não tenho a reputação de comentar, mas em resposta/adição à resposta de Don F:
$params = json_decode(file_get_contents('php://input'));
Um segundo parâmetro de true
tem de ser adicionado à função json_decode
de modo a devolver adequadamente uma matriz associativa:
$params = json_decode(file_get_contents('php://input'), true);
Angular
var payload = $.param({ jobId: 2 });
this.$http({
method: 'POST',
url: 'web/api/ResourceAction/processfile',
data: payload,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});
WebAPI 2
public class AcceptJobParams
{
public int jobId { get; set; }
}
public IHttpActionResult ProcessFile([FromBody]AcceptJobParams thing)
{
// do something with fileName parameter
return Ok();
}
moduleName.config(['$httpProvider',
function($httpProvider) {
$httpProvider.defaults.transformRequest.push(function(data) {
var requestStr;
if (data) {
data = JSON.parse(data);
for (var key in data) {
if (requestStr) {
requestStr += "&" + key + "=" + data[key];
} else {
requestStr = key + "=" + data[key];
}
}
}
return requestStr;
});
$httpProvider.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
}
]);
Adicione isto no seu ficheiro js:
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
E adicione isto ao seu ficheiro do servidor:
$params = json_decode(file_get_contents('php://input'), true);
Isso deve funcionar.
var paramsVal={data:'"id":"1"'};
$http.post("Request URL", {params: paramsVal});
Mas ao ler este fórum e o DOC da API, tentei seguir o caminho e isso funcionou comigo.
Se algum também tiver um problema semelhante, você pode tentar abaixo também.
$http({
method: 'POST',
url: "Request URL",
params: paramsVal,
headers: {'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'}
});
Por Favor verifique https://docs.angularjs.org/api/ng/service / $http#post para o que a configuração do param faz. {data: '"id": "1"'} - Mapa de cadeias de caracteres ou objectos qual será a URL?data= "id: 1"
Esta é provavelmente uma resposta tardia, mas acho que a maneira mais adequada é usar a mesma peça de código angular ao fazer um pedido " get " usando você $httpParamSerializer
terá que injectá-lo no seu controlador
então você pode simplesmente fazer o seguinte sem ter que usar Jquery em tudo ,
$http.post(url,$httpParamSerializer({param:val}))
app.controller('ctrl',function($scope,$http,$httpParamSerializer){
$http.post(url,$httpParamSerializer({param:val,secondParam:secondVal}));
}
var deferred = $q.defer();
$http({
method: 'POST',
url: 'myUri',
data: $.param({ param1: 'blablabla', param2: JSON.stringify(objJSON) }),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(
function(res) {
console.log('succes !', res.data);
deferred.resolve(res.data);
},
function(err) {
console.log('error...', err);
deferred.resolve(err);
}
);
return deferred.promise;
Tens de usar o JSON.stringify para cada param contendo um objeto JSON, e então construir seu objeto de dados com"$.param": -)
NB: o meu "objJSON" é um objecto JSON que contém array, inteiro, string e html. Seu tamanho total é >3500 caracteres.
Eu sei que tem aceite responde. Mas, seguir pode ajudar os futuros leitores, se a resposta não se adequar a eles por qualquer razão.
O Angular não faz ajax como o jQuery. Enquanto eu tentava seguir o guia para modificar o angular {[[2]}, eu encontrei outros problemas. Por exemplo, eu uso codeigniter no qual a função$this->input->is_ajax_request()
sempre falhou (que foi escrita por outro programador e usada globalmente, então não pode mudar) dizendo que esta não era uma solicitação ajax real.
Para resolvê-lo., Aceitei a ajuda de uma promessa adiada. Testei-o no Firefox, e o ie9 funcionou.
Tenho a seguinte função definida fora qualquer um do Código angular. Esta função faz a chamada regular jQuery ajax e retorna diferido / promessa (ainda estou aprendendo) objeto.
function getjQueryAjax(url, obj){
return $.ajax({
type: 'post',
url: url,
cache: true,
data: obj
});
}
Então vou chamar-lhe código angular usando o seguinte código. Por favor, note que temos que atualizar o $scope
manualmente usando $scope.$apply()
.
var data = {
media: "video",
scope: "movies"
};
var rPromise = getjQueryAjax("myController/getMeTypes" , data);
rPromise.success(function(response){
console.log(response);
$scope.$apply(function(){
$scope.testData = JSON.parse(response);
console.log($scope.testData);
});
}).error(function(){
console.log("AJAX failed!");
});
Isto pode não ser perfeito. atende, mas permitiu-me usar o jquery ajax com chamadas angulares e permitiu-me actualizar o
$scope
.
app.use(bodyParser.json());
Estou a usar asp.net sítios Web da WCF com js angular e abaixo do Código trabalhado:
$http({
contentType: "application/json; charset=utf-8",//required
method: "POST",
url: '../../operation/Service.svc/user_forget',
dataType: "json",//optional
data:{ "uid_or_phone": $scope.forgettel, "user_email": $scope.forgetemail },
async: "isAsync"//optional
}).success( function (response) {
$scope.userforgeterror = response.d;
})
Espero que ajude.
Não encontrei um excerto completo de código de como usar $ http.método de post para enviar dados para o servidor e por que não estava funcionando neste caso.
Explicações do excerto de código abaixo...
-
Estou a usar o jQuery $.função param para serializar os dados JSON para www post data
Definir o tipo de conteúdo na variável de configuração que será passada juntamente com o pedido de angularJS $http.post que indica ao servidor que estamos enviando dados em www post formato.
Repara no $ htttp.Método post, onde estou enviando o primeiro parâmetro como url, o segundo parâmetro como dados (serializado) e o terceiro parâmetro como configuração.
O código restante é auto-entendido.
$scope.SendData = function () {
// use $.param jQuery function to serialize data from JSON
var data = $.param({
fName: $scope.firstName,
lName: $scope.lastName
});
var config = {
headers : {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8;'
}
}
$http.post('/ServerRequest/PostDataResponse', data, config)
.success(function (data, status, headers, config) {
$scope.PostDataResponse = data;
})
.error(function (data, status, header, config) {
$scope.ResponseDetails = "Data: " + data +
"<hr />status: " + status +
"<hr />headers: " + header +
"<hr />config: " + config;
});
};
Veja o exemplo de código de $http.método de post aqui.
Se você usar o PHP esta é uma maneira fácil de acessar um array em PHP a partir de um post AngularJS.
$params = json_decode(file_get_contents('php://input'),true);
Se usar Angular > = 1, 4 , Aqui está a solução mais limpa usando o serializador fornecido pelo Angular:
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';
});
E depois podes simplesmente fazer isto em qualquer parte da tua aplicação:
$http({
method: 'POST',
url: '/requesturl',
data: {
param1: 'value1',
param2: 'value2'
}
});
E irá serializar correctamente os dados como param1=value1¶m2=value2
e enviá-los para /requesturl
com o cabeçalho application/x-www-form-urlencoded; charset=utf-8
do tipo de Conteúdo, como é normalmente esperado com os pedidos de publicação nos pontos finais.
TL; DR
Durante a minha pesquisa descobri que a resposta para este problema vem em muitos sabores diferentes; alguns são muito complicados e dependem de funções personalizadas, alguns dependem de jQuery e alguns estão incompletos em sugerir que você só precisa definir o cabeçalho.Se você definir o cabeçalho Content-Type
, o ponto final irá ver os dados de publicação, mas não será no formato padrão, porque a menos que você forneça um texto como o seu data
, ou serialize manualmente o seu objecto de dados, tudo será serializado como JSON por omissão e poderá ser interpretado incorrectamente no extremidade.
Por exemplo, se o serializador correcto não estivesse definido no exemplo acima, seria visto no ponto final como:
{"param1":"value1","param2":"value2"}
E isso pode levar a uma análise inesperada. ASP.NET trata-o como um nome de parâmetro null
, com {"param1":"value1","param2":"value2"}
como valor; ou Fiddler interpreta-o de outra forma, com {"param1":"value1","param2":"value2"}
como nome do parâmetro, e null
como valor.
Similar ao formato de trabalho sugerido pelo OP e à resposta de Denison, exceto usando $http.post
em vez de apenas $http
e ainda depende do jQuery.
A coisa boa sobre o uso de Jquery aqui é que objetos complexos são passados corretamente; contra a conversão manual em parâmetros de URL que podem obter os dados.
$http.post( 'request-url', jQuery.param( { 'message': message } ), {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});
Quando eu tinha este problema o parâmetro que eu estava postando acabou por ser um array de objetos em vez de um objeto simples.
Acabei de actualizar de 1.2 A 1.3 angulares, encontrei um problema no código. Transformar um recurso vai levar a um loop infinito porque (eu acho) da promessa $segurando novamente o mesmo objeto. Talvez ajude alguém...
Posso arranjar isso até:[...]
/**
* The workhorse; converts an object to x-www-form-urlencoded serialization.
* @param {Object} obj
* @return {String}
*/
var param = function (obj) {
var query = '', name, value, fullSubName, subName, subValue, innerObj, i;
angular.forEach(obj, function(value, name) {
+ if(name.indexOf("$promise") != -1) {
+ return;
+ }
value = obj[name];
if (value instanceof Array) {
for (i = 0; i < value.length; ++i) {
[...]
Eu tenho usado o código de resposta aceito (código de Felipe) por um tempo e tem funcionado muito bem (obrigado, Felipe!).
No entanto, recentemente descobri que tem problemas com objetos ou arrays vazios. Por exemplo, ao submeter este objecto:{
A: 1,
B: {
a: [ ],
},
C: [ ],
D: "2"
}
O PHP não parece ver B E C de todo. Ele recebe isto:
[
"A" => "1",
"B" => "2"
]
Um olhar para o pedido real no Chrome mostra isto:
A: 1
:
D: 2
Escrevi um excerto de código alternativo. Parece funcionar bem com os meus casos de uso. mas não o testei extensivamente, por isso, use-o com cuidado.
Usei um texto porque gosto de escrever forte, mas seria fácil converter-me a JS puro:
angular.module("MyModule").config([ "$httpProvider", function($httpProvider: ng.IHttpProvider) {
// Use x-www-form-urlencoded Content-Type
$httpProvider.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8";
function phpize(obj: Object | any[], depth: number = 1): string[] {
var arr: string[] = [ ];
angular.forEach(obj, (value: any, key: string) => {
if (angular.isObject(value) || angular.isArray(value)) {
var arrInner: string[] = phpize(value, depth + 1);
var tmpKey: string;
var encodedKey = encodeURIComponent(key);
if (depth == 1) tmpKey = encodedKey;
else tmpKey = `[${encodedKey}]`;
if (arrInner.length == 0) {
arr.push(`${tmpKey}=`);
}
else {
arr = arr.concat(arrInner.map(inner => `${tmpKey}${inner}`));
}
}
else {
var encodedKey = encodeURIComponent(key);
var encodedValue;
if (angular.isUndefined(value) || value === null) encodedValue = "";
else encodedValue = encodeURIComponent(value);
if (depth == 1) {
arr.push(`${encodedKey}=${encodedValue}`);
}
else {
arr.push(`[${encodedKey}]=${encodedValue}`);
}
}
});
return arr;
}
// Override $http service's default transformRequest
(<any>$httpProvider.defaults).transformRequest = [ function(data: any) {
if (!angular.isObject(data) || data.toString() == "[object File]") return data;
return phpize(data).join("&");
} ];
} ]);
É menos eficiente do que o código do Felipe, mas acho que não importa muito, pois deve ser imediato comparado com a sobrecarga geral do próprio pedido HTTP.
Agora o PHP mostra:
[
"A" => "1",
"B" => [
"a" => ""
],
"C" => "",
"D" => "2"
]
Tanto quanto sei, não é possível fazer com que o PHP reconheça que B. A E C são matrizes vazias, mas pelo menos as chaves. aparece, o que é importante quando há um código que depende de uma certa estrutura, mesmo quando está essencialmente vazia por dentro.
Note também que converte indefinidos e nullpara cadeias de caracteres vazias.
Resolvi isto pelos seguintes códigos:
Lado Do Cliente (Js):
$http({
url: me.serverPath,
method: 'POST',
data: data,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
}).
success(function (serverData) {
console.log("ServerData:", serverData);
......
Repara que os dados são um objecto.
No servidor (ASP.NET MVC):
[AllowCrossSiteJson]
public string Api()
{
var data = JsonConvert.DeserializeObject<AgentRequest>(Request.Form[0]);
if (data == null) return "Null Request";
var bl = Page.Bl = new Core(this);
return data.methodName;
}
E 'Allowcrossitejsonattribute'é necessário para pedidos de domínio cruzado:
public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
base.OnActionExecuting(filterContext);
}
}
Espero que tenha sido útil.
application/x-www-form-urlencoded
. Desta forma, a sua aplicação de infra-estrutura capaz de receber formulários-dados sob a forma de parâmetros post e não JSON.
Mas você pode modificar o comportamento por omissão do Angular $http service por
- Adicionar cabeçalho
- a serializar o json
$http({
method: 'POST',
url: 'request-url',
data: $httpParamSerializerJQLike(json-form-data),
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8;'
}
});
Se precisar de um 'plugin' para serializar os dados do formulário no JSON primeiro, use este https://github.com/marioizquierdo/jquery.serializeJSON