metodo - AngularJs $ http.post() no envía datos
http.post angular 6 (30)
¿Podría alguien decirme por qué la siguiente declaración no envía los datos de la publicación a la URL designada? Se llama a la url pero en el servidor cuando imprimo $ _POST: obtengo una matriz vacía. Si imprimo un mensaje en la consola antes de agregarlo a los datos, muestra el contenido correcto.
$http.post(''request-url'', { ''message'' : message });
También lo he probado con los datos como cadena (con el mismo resultado):
$http.post(''request-url'', "message=" + message);
Parece que funciona cuando lo uso en el siguiente formato:
$http({
method: ''POST'',
url: ''request-url'',
data: "message=" + message,
headers: {''Content-Type'': ''application/x-www-form-urlencoded''}
});
pero ¿hay una manera de hacerlo con $ http.post () - y siempre tengo que incluir el encabezado para que funcione? Creo que el tipo de contenido anterior está especificando el formato de los datos enviados, pero ¿puedo enviarlo como objeto javascript?
Estoy usando los servicios web WCF de asp.net con código angular js y debajo del código trabajado:
$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 eso ayude.
A diferencia de JQuery y en aras de la pedantería, Angular usa el formato JSON para la transferencia de datos POST desde un cliente al servidor (JQuery aplica x-www-form-urlencoded presumiblemente, aunque JQuery y Angular usan JSON para imputar datos). Por lo tanto, hay dos partes del problema: en la parte del cliente js y en la parte del servidor. Así que tú necesitas:
Ponga js parte del cliente Angular como esta:
$http({ method: ''POST'', url: ''request-url'', data: {''message'': ''Hello world''} });
Y
escriba en la parte del servidor para recibir datos de un cliente (si es php).
$data = file_get_contents("php://input"); $dataJsonDecode = json_decode($data); $message = $dataJsonDecode->message; echo $message; //''Hello world''
Nota: $ _POST no funcionará!
La solución funciona bien para mí, espero, y para ti.
Añade esto en tu archivo js:
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
y agregue esto a su archivo de servidor:
$params = json_decode(file_get_contents(''php://input''), true);
Eso debería funcionar.
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();
}
Cuando tuve este problema, el parámetro que estaba publicando resultó ser una matriz de objetos en lugar de un objeto simple.
En mi caso resuelvo el problema así:
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;
Debe usar JSON.stringify para cada parámetro que contenga un objeto JSON y luego compilar su objeto de datos con "$ .param" :-)
NB: Mi "objJSON" es un objeto JSON que contiene contenido de matriz, entero, cadena y html. Su tamaño total es de> 3500 caracteres.
Esta es probablemente una respuesta tardía, pero creo que la forma más adecuada es utilizar el mismo código de uso angular al realizar una solicitud de "obtención" usando $httpParamSerializer
tendrá que inyectarlo en su controlador para que pueda hacer lo siguiente sin tener que usar Jquery en absoluto, $http.post(url,$httpParamSerializer({param:val}))
app.controller(''ctrl'',function($scope,$http,$httpParamSerializer){
$http.post(url,$httpParamSerializer({param:val,secondParam:secondVal}));
}
Este código resolvió el problema para mí. Es una solución a nivel de aplicación:
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";
}
]);
Esto finalmente se ha abordado en angular 1.4 usando $ httpParamSerializerJQLike
Consulte 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''
})})
He estado usando el código de respuesta aceptado (el código de Felipe) por un tiempo y ha funcionado muy bien (¡gracias, Felipe!).
Sin embargo, recientemente descubrí que tiene problemas con los objetos vacíos o matrices. Por ejemplo, al enviar este objeto:
{
A: 1,
B: {
a: [ ],
},
C: [ ],
D: "2"
}
PHP no parece ver B y C en absoluto. Obtiene esto:
[
"A" => "1",
"B" => "2"
]
Un vistazo a la solicitud real en Chrome muestra esto:
A: 1
:
D: 2
Escribí un fragmento de código alternativo. Parece funcionar bien con mis casos de uso, pero no lo he probado mucho, así que utilícelo con precaución.
Utilicé TypeScript porque me gusta la escritura fuerte pero sería fácil de convertir 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("&");
} ];
} ]);
Es menos eficiente que el código de Felipe, pero no creo que importe mucho, ya que debería ser inmediato en comparación con la sobrecarga general de la solicitud HTTP en sí.
Ahora PHP muestra:
[
"A" => "1",
"B" => [
"a" => ""
],
"C" => "",
"D" => "2"
]
Por lo que sé, no es posible hacer que PHP reconozca que Ba y C son matrices vacías, pero al menos aparecen las claves, lo cual es importante cuando hay un código que depende de cierta estructura, incluso cuando está esencialmente vacío por dentro.
También tenga en cuenta que convierte undefined sy null s en cadenas vacías.
He tenido un problema similar, y me pregunto si esto también puede ser útil: https://.com/a/11443066
var xsrf = $.param({fkey: "key"});
$http({
method: ''POST'',
url: url,
data: xsrf,
headers: {''Content-Type'': ''application/x-www-form-urlencoded''}
})
Saludos,
Me gusta usar una función para convertir objetos para publicar parámetros.
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''}
})
No es culpa del angular. Angular está diseñado para trabajar en el mundo JSON. Por lo tanto, cuando el servicio $ http envía una solicitud AJAX, envía todos sus datos como una carga útil, no como datos de formulario para que su aplicación de fondo pueda manejarlos. Pero jQuery hace algunas cosas internamente. Le indica al módulo $ ajax de jQuery que vincule los datos de formulario como JSON, pero antes de enviar la solicitud AJAX, serializó JSON y application/x-www-form-urlencoded
encabezado application/x-www-form-urlencoded
. De esta manera, su aplicación de fondo puede recibir datos de formulario en forma de parámetros de publicación y no JSON.
Pero puede modificar el comportamiento predeterminado del servicio angular $ http por
- Añadiendo encabezado
- Serializacion json
$ httpParamSerializerJQLike es el servicio integrado de angular que serializa json de la misma manera que $ .param hace de jQuery.
$http({
method: ''POST'',
url: ''request-url'',
data: $httpParamSerializerJQLike(json-form-data),
headers: {
''Content-Type'': ''application/x-www-form-urlencoded; charset=UTF-8;''
}
});
Si necesita un complemento para serializar los datos de formulario en JSON primero, use este https://github.com/marioizquierdo/jquery.serializeJSON
No está muy claro anteriormente, pero si está recibiendo la solicitud en PHP, puede usar:
$params = json_decode(file_get_contents(''php://input''),true);
Para acceder a una matriz en PHP desde un AngularJS POST.
No se encontró un fragmento de código completo de cómo usar el método $ http.post para enviar datos al servidor y por qué no funcionó en este caso.
Explicaciones del siguiente fragmento de código ...
- Estoy usando la función jQuery $ .param para serializar los datos JSON a www.
Configuración del tipo de contenido en la variable de configuración que se pasará junto con la solicitud de angularJS $ http.post que indica al servidor que estamos enviando datos en formato www post.
Observe el método $ htttp.post, donde envío el primer parámetro como url, el segundo parámetro como datos (serializado) y el tercer parámetro como config.
El código restante es auto comprendido.
$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;
});
};
Mira el ejemplo de código del método $ http.post aquí .
No tengo la reputación de comentar, pero en respuesta / adición a la respuesta de Don F:
$params = json_decode(file_get_contents(''php://input''));
Un segundo parámetro de true
debe agregarse a la función json_decode
para devolver correctamente una matriz asociativa:
$params = json_decode(file_get_contents(''php://input''), true);
Para construir sobre la respuesta de @ felipe-miosso:
- Descárgalo como un módulo AngularJS desde here ,
- Instalarlo
Agrégalo a tu aplicación:
var app = angular.module(''my_app'', [ ... , ''httpPostFix'']);
Para enviar datos a través del método Post con $http
de angularjs debe cambiar
data: "message=" + message
, con data: $.param({message:message})
Puede configurar el "Tipo de contenido" predeterminado de esta manera:
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
Sobre el formato de data
:
Los métodos $ http.post y $ http.put aceptan cualquier valor de objeto JavaScript (o una cadena) como su parámetro de datos. Si los datos son un objeto de JavaScript, se convertirán, de forma predeterminada, en una cadena JSON.
Intenta usar esta variación
function sendData($scope) {
$http({
url: ''request-url'',
method: "POST",
data: { ''message'' : message }
})
.then(function(response) {
// success
},
function(response) { // optional
// failed
});
}
Recién actualizado de angular 1.2 a 1.3, he encontrado un problema en el código. Transformar un recurso conducirá a un bucle sin fin porque (creo) de la promesa $ que mantiene de nuevo el mismo objeto. Tal vez ayude a alguien ...
Podría arreglar eso por:
[...]
/**
* 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) {
[...]
Resolví esto por los siguientes códigos:
Lado del 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);
......
Note que los datos son un objeto.
En el 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;
}
y ''AllowCrossSiteJsonAttribute'' es necesario para las solicitudes de dominios cruzados:
public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
base.OnActionExecuting(filterContext);
}
}
Espero que esto haya sido útil.
Sé que ha aceptado la respuesta. Pero, lo siguiente podría ayudar a los futuros lectores, si la respuesta no les conviene por alguna razón.
Angular no hace ajax igual que jQuery. Mientras intentaba seguir la guía para modificar $httpprovider
angular, encontré otros problemas. Por ejemplo, uso codeigniter en el que la función $this->input->is_ajax_request()
siempre fallaba (lo cual fue escrito por otro programador y se usó globalmente, por lo que no puedo cambiar) diciendo que esta no era una solicitud real de ajax.
Para resolverlo, tomé ayuda de promesa diferida . Lo probé en Firefox, y ie9 y funcionó.
Tengo la siguiente función definida fuera de cualquiera de los códigos angulares. Esta función hace que el jja de ajax jquery regular y devuelva el objeto de aplazamiento / promesa (todavía estoy aprendiendo).
function getjQueryAjax(url, obj){
return $.ajax({
type: ''post'',
url: url,
cache: true,
data: obj
});
}
Entonces lo llamo código angular usando el siguiente código. Tenga en cuenta que debemos actualizar el $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!");
});
Puede que esta no sea la respuesta perfecta, pero me permitió usar jquery ajax calls con angular y me permitió actualizar $scope
.
Si está utilizando PHP, esta es una forma fácil de acceder a una matriz en PHP desde un POST de AngularJS.
$params = json_decode(file_get_contents(''php://input''),true);
Si usa Angular> = 1.4 , aquí está la solución más limpia con el serializador provisto por 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'';
});
Y luego puedes hacer esto en cualquier lugar de tu aplicación:
$http({
method: ''POST'',
url: ''/requesturl'',
data: {
param1: ''value1'',
param2: ''value2''
}
});
Y serializará correctamente los datos como param1=value1¶m2=value2
y los enviará a /requesturl
con la application/x-www-form-urlencoded; charset=utf-8
application/x-www-form-urlencoded; charset=utf-8
Content-Type header como suele esperarse con las solicitudes POST en los puntos finales.
TL; DR
Durante mi investigación encontré que la respuesta a este problema viene en muchos sabores diferentes; Algunos son muy complicados y dependen de funciones personalizadas, algunos dependen de jQuery y otros son incompletos al sugerir que solo necesita establecer el encabezado.
Si acaba de establecer el encabezado Content-Type
, el punto final verá los datos POST, pero no estará en el formato estándar porque a menos que proporcione una cadena como sus data
, o serialice manualmente su objeto de datos, todo será serializado como JSON por defecto y puede interpretarse incorrectamente en el punto final.
por ejemplo, si el serializador correcto no se configuró en el ejemplo anterior, se vería en el punto final como:
{"param1":"value1","param2":"value2"}
Y eso puede llevar a un análisis inesperado, por ejemplo, ASP.NET lo trata como un nombre de parámetro null
, con {"param1":"value1","param2":"value2"}
como valor; o Fiddler lo interpreta de la otra manera, con {"param1":"value1","param2":"value2"}
como el nombre del parámetro, y null
como el valor.
Similar al formato de trabajo sugerido por el OP y la respuesta de Denison, excepto que usa $http.post
lugar de solo $http
y aún depende de jQuery.
Lo bueno de usar jQuery aquí es que los objetos complejos se pasan correctamente; contra la conversión manual en parámetros de URL que pueden distorsionar los datos.
$http.post( ''request-url'', jQuery.param( { ''message'': message } ), {
headers: { ''Content-Type'': ''application/x-www-form-urlencoded'' }
});
También me enfrenté a un problema similar y estaba haciendo algo como esto y eso no funcionó. Mi controlador Spring no pudo leer el parámetro de datos.
var paramsVal={data:''"id":"1"''};
$http.post("Request URL", {params: paramsVal});
Pero leyendo este foro y API Doc, lo intenté de la siguiente manera y eso me funcionó. Si alguien también tiene un problema similar, puedes intentarlo a continuación.
$http({
method: ''POST'',
url: "Request URL",
params: paramsVal,
headers: {''Content-Type'': ''application/x-www-form-urlencoded;charset=utf-8''}
});
Consulte https://docs.angularjs.org/api/ng/service/ $ http # post para ver qué config config. {data: ''"id": "1"''} - Mapa de cadenas u objetos que se convertirá en URL? data = "id: 1"
Tuve el mismo problema al usar asp.net MVC y encontré la solución aquí
Hay mucha confusión entre los recién llegados a AngularJS acerca de por qué las funciones abreviadas del servicio
$http
($http.post()
, etc.) no parecen ser intercambiables con los equivalentes de jQuery (jQuery.post()
, etc.)La diferencia está en cómo jQuery y AngularJS serializan y transmiten los datos. Fundamentalmente, el problema radica en que el idioma de su servidor elegido no puede entender la transmisión de AngularJS de forma nativa ... De forma predeterminada, jQuery transmite datos usando
Content-Type: x-www-form-urlencoded
y la familiarización
foo=bar&baz=moe
.AngularJS , sin embargo, transmite datos utilizando
Content-Type: application/json
y
{ "foo": "bar", "baz": "moe" }
La serialización JSON, que desafortunadamente en algunos lenguajes de servidor web, especialmente PHP, no se inicializa de forma nativa.
Funciona de maravilla.
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;
}];
});
Tuve el mismo problema con AngularJS y Node.js + Express 4 + Router
Enrutador espera los datos de la solicitud de la publicación en el cuerpo. Este cuerpo siempre estaba vacío si seguía el ejemplo de Angular Docs
Notación 1
$http.post(''/someUrl'', {msg:''hello word!''})
Pero si lo usara en los datos.
Notación 2
$http({
withCredentials: false,
method: ''post'',
url: yourUrl,
headers: {''Content-Type'': ''application/x-www-form-urlencoded''},
data: postData
});
Edición 1:
De lo contrario, el router node.js esperará los datos en req.body si se usa la notación 1:
req.body.msg
Que también envía la información como carga útil JSON. Esto es mejor en algunos casos donde tienes arreglos en tu json y x-www-form-urlencoded te dará algunos problemas.
funcionó. Espero eso ayude.
Tuve el mismo problema en Express ... para resolver tienes que usar bodyparser para analizar objetos json antes de enviar solicitudes http ...
app.use(bodyParser.json());
Yo uso jQuery param con AngularJS post requrest. Aquí hay un ejemplo ... crear el módulo de aplicación AngularJS, donde myapp
se define con ng-app
en su código HTML.
var app = angular.module(''myapp'', []);
Ahora vamos a crear un controlador de inicio de sesión y correo electrónico y contraseña POST.
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
});
}]);
No me gusta explicar el código, es bastante simple de entender :) Tenga en cuenta que param
es de jQuery, por lo que debe instalar tanto jQuery como AngularJS para que funcione. Aquí hay una captura de pantalla.
Espero que esto sea de ayuda. ¡Gracias!