AngularJs $http.post() не отправляет данные


может ли кто-нибудь сказать мне, почему следующее заявление не отправляет данные post на указанный url-адрес? Url-адрес вызывается, но на сервере, когда я печатаю $_POST - я получаю пустой массив. Если я печатаю сообщение в консоли перед добавлением его в данные-он показывает правильное содержимое.

$http.post('request-url',  { 'message' : message });

Я также пробовал его с данными в виде строки (с тем же результатом):

$http.post('request-url',  "message=" + message);

это, кажется, работает, когда я использую его в следующем формат:

$http({
    method: 'POST',
    url: 'request-url',
    data: "message=" + message,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'}
});

но есть ли способ сделать это с помощью $http.post () - и всегда ли мне нужно включать заголовок, чтобы он работал? Я считаю, что приведенный выше тип контента определяет формат отправленных данных, но могу ли я отправить его как объект javascript?

30 324

30 ответов:

у меня была такая же проблема с использованием asp.net MVC и нашел решение здесь

есть много путаницы среди новичков AngularJS а почему $http сервис стенография функции ($http.post() и т. д.) не представляется быть заменяемым с jQuery эквиваленты (jQuery.post() и т. д.)

разница в том, как jQuery и AngularJS сериализация и передача данных. По сути, проблема заключается в том, что ваш серверный язык выбора не может понять передачу AngularJS изначально ... По умолчанию jQuery передает данные с использованием

Content-Type: x-www-form-urlencoded

и знакомый foo=bar&baz=moe сериализация.

AngularJS, однако, передает данные с помощью

Content-Type: application/json 

и { "foo": "bar", "baz": "moe" }

сериализация JSON, которая, к сожалению, некоторые языки веб-сервера -в частности, PHP - не unserialize изначально.

работает как шарм.

код

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

это не очень ясно выше, но если вы получаете запрос в PHP, вы можете использовать:

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

для доступа к массиву в PHP из сообщения AngularJS.

вы можете установить по умолчанию "Content-Type" следующим образом:

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

о :

$http.post и $http.методы put принимают любое значение объекта JavaScript (или строки) в качестве параметра данных. Если данные являются объектом JavaScript, то по умолчанию они будут преобразованы в строку JSON.

попробуйте использовать этот вариант

function sendData($scope) {
    $http({
        url: 'request-url',
        method: "POST",
        data: { 'message' : message }
    })
    .then(function(response) {
            // success
    }, 
    function(response) { // optional
            // failed
    });
}

У меня была аналогичная проблема, и мне интересно, может ли это быть полезно: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'}
})

С уважением,

Мне нравится использовать функцию для преобразования объектов в параметры post.

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

это, наконец, было рассмотрено в angular 1.4 с помощью $httpParamSerializerJQLike

см.https://github.com/angular/angular.js/issues/6039

.controller('myCtrl', function($http, $httpParamSerializerJQLike) {
$http({
  method: 'POST',
  url: baseUrl,
  data: $httpParamSerializerJQLike({
    "user":{
      "email":"wahxxx@gmail.com",
      "password":"123456"
    }
  }),
  headers:
    'Content-Type': 'application/x-www-form-urlencoded'
})})

я использую jQuery param С AngularJS post requrest. Вот вам пример ... создайте модуль приложения AngularJS, где myapp определен с ng-app в вашем HTML-коде.

var app = angular.module('myapp', []);

теперь давайте создадим контроллер входа и отправим электронную почту и пароль.

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

Я не люблю объяснять код, это достаточно просто понять:) обратите внимание, что param из jQuery, поэтому вы должны установить как jQuery, так и AngularJS, чтобы сделать это рабочий. Вот скриншот.

enter image description here

надеюсь, что это полезно. Спасибо!

у меня была такая же проблема с AngularJS и узлов.JS + Express 4 + Router

маршрутизатор ожидает данные от запроса post в теле. Это тело всегда было пустым, если я следовал примеру из Angular Docs

обозначение 1

$http.post('/someUrl', {msg:'hello word!'})

но если я использовал его в данные

нотация 2

$http({
       withCredentials: false,
       method: 'post',
       url: yourUrl,
       headers: {'Content-Type': 'application/x-www-form-urlencoded'},
       data: postData
 });

редактировать 1:

В противном случае узел.маршрутизатор js будет ожидать данные в req.тело, если используется обозначение 1:

req.body.msg

что также отправляет информацию в качестве полезной нагрузки JSON. Это лучше в некоторых случаях, когда у вас есть массивы в вашем json и x-www-form-urlencoded даст некоторые проблемы.

это сработало. Надеюсь, это поможет.

В отличие от JQuery и ради педантичности, Angular использует формат JSON для POST данные передачи от клиента к серверу (jQuery применяет x-www-form-urlencoded предположительно, хотя JQuery и Angular используют JSON для вменения данных). Поэтому есть две части проблемы: в клиентской части js и в вашей серверной части. Так что вам нужно:

  1. положите часть клиента js угловую как это:

    $http({
    method: 'POST',
    url: 'request-url',
    data: {'message': 'Hello world'}
    });
    

и

  1. запись в серверной части для получения данных от клиента (если это php).

            $data               = file_get_contents("php://input");
            $dataJsonDecode     = json_decode($data);
            $message            = $dataJsonDecode->message;
            echo $message;     //'Hello world'
    

Примечание: $_POST не будет работать!

решение работает для меня, надеюсь, и для вас.

для отправки данных через Post methode с $http из angularjs вам нужно изменить

data: "message=" + message С data: $.param({message:message})

чтобы построить на @felipe-miosso ответ:

  1. загрузите его как модуль AngularJS из здесь,
  2. установки
  3. добавить его в ваше приложение:

    var app = angular.module('my_app', [ ... , 'httpPostFix']);
    

у меня нет репутации, чтобы комментировать, но в ответ / дополнение к ответу Дона Ф:

$params = json_decode(file_get_contents('php://input'));

второй параметр true необходимо добавить в json_decode функция для правильного возврата ассоциативного массива:

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

Угловое

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

добавьте это в свой js-файл:

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

и добавьте это в ваш файл-сервера:

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

Это должно сработать.

Я тоже столкнулся с подобной проблемой и я делал что-то подобное, и это не сработало. Мой весенний контроллер не смог прочитать параметр данных.

var paramsVal={data:'"id":"1"'};
  $http.post("Request URL",  {params: paramsVal});  

но читая этот форум и API Doc, я попробовал следующий путь, и это сработало для меня. Если у кого-то также есть подобная проблема, вы также можете попробовать ниже.

$http({
      method: 'POST',
      url: "Request URL",           
      params: paramsVal,
      headers: {'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'}
            });

пожалуйста, проверьте https://docs.angularjs.org/api/ng/service/$http#post для того, что делает param config. {data: '"id":" 1"'} - карта строки или объекты, которые будут включены в URL?data= "id:1"

Это, вероятно, поздний ответ, но я думаю, что наиболее правильным способом является использование одного и того же фрагмента кода углового использования при выполнении запроса "get" с помощью вас $httpParamSerializer придется ввести его в контроллер таким образом, вы можете просто сделать следующее, не используя Jquery вообще , $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;

вы должны использовать JSON.stringify для каждого параметра, содержащего объект JSON, а затем построить объект данных с "$.парам" :-)

NB: мой "objson" - это объект JSON, содержащий массив, целое число, строку и содержимое html. Его общий размер составляет >3500 символов.

Я знаю принят ответ. Но, может помочь будущим читателям, если ответ их не устраивает по какой-либо причине.

Angular не делает ajax так же, как jQuery. В то время как я пытался следовать руководству, чтобы изменить угловой $httpprovider , я столкнулся с другими проблемами. Например, я использую codeigniter, в котором $this->input->is_ajax_request() функция всегда терпела неудачу (которая была написана другим программистом и использовалась глобально, поэтому не может измениться), говоря, что это не настоящий ajax запрос.

чтобы решить эту проблему, я взял помощь отложенное обещание. Я тестировал его в Firefox, и ie9, и он работал.

у меня есть следующая функция определена за пределами любой угловой код. Эта функция делает обычный вызов jQuery ajax и возвращает отложенный / обещающий (я все еще учусь) объект.

function getjQueryAjax(url, obj){
    return $.ajax({
        type: 'post',
        url: url,
        cache: true,
        data: obj
    });
}

тогда я называю его угловым кодом, используя следующий код. Обратите внимание, что мы должны обновить $scope вручную с помощью $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!");
    });

это может быть не идеальный ответ, но он позволил мне использовать вызовы jQuery ajax с angular и позволил мне обновить $scope.

У меня была такая же проблема в экспресс .. чтобы решить эту проблему, вы должны использовать bodyparser для анализа объектов json перед отправкой http-запросов ..

app.use(bodyParser.json());

Я использую asp.net веб-сервисы WCF с угловым JS и ниже кодом работал:

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

надеюсь, что это помогает.

не удалось найти полный фрагмент кода, как использовать $http.метод POST для отправки данных на сервер и почему он не работает в этом случае.

пояснения ниже фрагмента кода...

  1. Я использую jQuery $.функция param для сериализации JSON-данных для данных ВСП в должности
  2. установка типа содержимого в переменной конфигурации, которая будет передана вместе с запросом angularJS $http.сообщение, которое инструктирует сервер, на который мы отправляем данные формат сообщения www.

  3. обратите внимание на $htttp.метод post, где я отправляю 1-й параметр в качестве url, 2-й параметр в качестве данных (сериализованных) и 3-й параметр в качестве конфигурации.

оставшийся код понятен самому себе.

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

посмотрите на пример кода $ http.метод post здесь.

Если вы используете PHP, это простой способ получить доступ к массиву в PHP из сообщения AngularJS.

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

при использовании угловые >= 1.4, вот самое чистое решение с помощью сериализатор, предоставляемый 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';
});

и тогда вы можете просто сделать это в любом месте вашего приложения:

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

и он будет правильно сериализовать данные как param1=value1&param2=value2 и отправить его в /requesturl С application/x-www-form-urlencoded; charset=utf-8 заголовок типа содержимого, как обычно ожидается, с запросами POST на конечных точках.

TL; DR

в ходе мое исследование я обнаружил, что ответ на эту проблему приходит во многих разных вариантах; некоторые из них очень запутаны и зависят от пользовательских функций, некоторые зависят от jQuery, а некоторые неполны в предположении, что вам нужно только установить заголовок.

если вы просто установите Content-Type заголовок, конечная точка будет видеть данные POST, но это не будет в стандартном формате, потому что если вы не предоставите строку в качестве data, или вручную сериализовать объект данных, все это будет сериализовано как JSON по умолчанию и может быть неправильно интерпретирован в конечной точке.

например, если правильный сериализатор не был установлен в приведенном выше примере, он будет отображаться в конечной точке как:

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

и это может привести к неожиданному разбору, например ASP.NET трактует его как null параметр name, с {"param1":"value1","param2":"value2"} как значение; или скрипач интерпретирует его по-другому, с {"param1":"value1","param2":"value2"} как имя параметра, а null как значение.

похоже на предложенный OP рабочий формат и ответ Денисона, за исключением использования просто $http и по-прежнему зависит от jQuery.

хорошая вещь об использовании jQuery здесь заключается в том, что сложные объекты передаются правильно; против ручного преобразования в Параметры URL, которые могут искажать данные.

$http.post( 'request-url', jQuery.param( { 'message': message } ), {
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});

когда у меня была эта проблема, параметр, который я отправлял, оказался массивом объектов вместо простого объекта.

только что обновил с углового 1.2 до 1.3, нашли проблему в коде. Преобразование ресурса приведет к бесконечному циклу, потому что (я думаю) $promise снова держит тот же объект. Может быть, это кому-то поможет...

Я мог бы исправить это:

[...]
  /**
 * 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) {
[...]

Я уже некоторое время использую код принятого ответа (код Фелипе), и он отлично работает (спасибо, Фелипе!).

однако, недавно я обнаружил, что у него есть проблемы с пустыми объектами или массивами. Например, при отправке этого объекта:

{
    A: 1,
    B: {
        a: [ ],
    },
    C: [ ],
    D: "2"
}

PHP, кажется, не видит B и C вообще. Он получает это:

[
    "A" => "1",
    "B" => "2"
]

взгляд на фактический запрос в Chrome показывает это:

A: 1
:
D: 2

я написал альтернативный фрагмент кода. Кажется чтобы хорошо работать с моими прецедентами, но я не тестировал его широко, поэтому используйте с осторожностью.

Я использовал TypeScript, потому что мне нравится сильная типизация, но было бы легко конвертировать в чистый JS:

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("&");
    } ];
} ]);

Это менее эффективно, чем код Фелипе, но я не думаю, что это имеет большое значение, так как он должен быть немедленным по сравнению с общими накладными расходами самого HTTP-запроса.

теперь PHP показывает:

[
    "A" => "1",
    "B" => [
        "a" => ""
    ],
    "C" => "",
    "D" => "2"
]

насколько я знаю, это не возможно, чтобы получить PHP, чтобы признайте, что B. a и C-пустые массивы, но, по крайней мере, ключи появляются, что важно, когда есть код, который полагается на определенную структуру, даже когда ее по существу пусто внутри.

Также обратите внимание, что он преобразует undefined s и nulls для пустых строк.

я решил это с помощью следующих кодов:

Сторона Клиента (Js):

     $http({
                url: me.serverPath,
                method: 'POST',
                data: data,
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
            }).
                success(function (serverData) {
                    console.log("ServerData:", serverData);
    ......

обратите внимание, что данные-это объект.

на сервере (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;
        }

и 'AllowCrossSiteJsonAttribute' необходим для междоменных запросов:

public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
            base.OnActionExecuting(filterContext);
        }
    }

надеюсь, это было полезно.

это не вина углового. Угловой предназначен для работы в мире JSON. Поэтому, когда служба $http отправляет запрос AJAX, она отправляет все ваши данные в качестве полезной нагрузки, а не в виде данных формы, чтобы ваше серверное приложение могло обрабатывать его. Но jQuery делает некоторые вещи внутренне. Вы указываете в модуле функции jQuery $AJAX для привязки форма-данные в формате JSON, но перед отправкой AJAX-запрос, он сериализуется в JSON и добавить application/x-www-form-urlencoded заголовок. Таким образом, ваше серверное приложение может получать данные формы в виде параметров post, а не формат JSON.

но вы можете изменить поведение службы angular $http по умолчанию с помощью

  1. добавить заголовок
  2. сериализация json

$httpParamSerializerJQLike-это встроенный сервис angular, который сериализует json таким же образом $.параметр не используется jQuery.

$http({
    method: 'POST',
    url: 'request-url',
    data: $httpParamSerializerJQLike(json-form-data),
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8;'
    }
});

Если вам нужен плагин для сериализации данных формы в JSON во-первых, используйте этот https://github.com/marioizquierdo/jquery.serializeJSON