AngularJs $http.post() does not send data

2018-12-31 05:29发布

Could anyone tell me why the following statement does not send the post data to the designated url? The url is called but on the server when I print $_POST - I get an empty array. If I print message in the console before adding it to the data - it shows the correct content.

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

I've also tried it with the data as string (with the same outcome):

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

It seem to be working when I use it in the following format:

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

but is there a way of doing it with the $http.post() - and do I always have to include the header in order for it to work? I believe that the above content type is specifying format of the sent data, but can I send it as javascript object?

30条回答
永恒的永恒
2楼-- · 2018-12-31 05:36

I had the same problem using asp.net MVC and found the solution here

There is much confusion among newcomers to AngularJS as to why the $http service shorthand functions ($http.post(), etc.) don’t appear to be swappable with the jQuery equivalents (jQuery.post(), etc.)

The difference is in how jQuery and AngularJS serialize and transmit the data. Fundamentally, the problem lies with your server language of choice being unable to understand AngularJS’s transmission natively ... By default, jQuery transmits data using

Content-Type: x-www-form-urlencoded

and the familiar foo=bar&baz=moe serialization.

AngularJS, however, transmits data using

Content-Type: application/json 

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

JSON serialization, which unfortunately some Web server languages—notably PHP—do not unserialize natively.

Works like a charm.

CODE

// 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;
  }];
});
查看更多
裙下三千臣
3楼-- · 2018-12-31 05:41

To build on @felipe-miosso's answer:

  1. Download it as an AngularJS module from here,
  2. Install it
  3. Add it to your application:

    var app = angular.module('my_app', [ ... , 'httpPostFix']);
    
查看更多
无与为乐者.
4楼-- · 2018-12-31 05:42

You can set the default "Content-Type" like this:

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

About the data format:

The $http.post and $http.put methods accept any JavaScript object (or a string) value as their data parameter. If data is a JavaScript object it will be, by default, converted to a JSON string.

Try to use this variation

function sendData($scope) {
    $http({
        url: 'request-url',
        method: "POST",
        data: { 'message' : message }
    })
    .then(function(response) {
            // success
    }, 
    function(response) { // optional
            // failed
    });
}
查看更多
何处买醉
5楼-- · 2018-12-31 05:43

In my case I resolve the problem like this :

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;

You need to use JSON.stringify for each param containing a JSON object, and then build your data object with "$.param" :-)

NB : My "objJSON" is a JSON object containing array, integer, string and html content. His total size is >3500 characters.

查看更多
看淡一切
6楼-- · 2018-12-31 05:44

I solved this by below codes:

Client Side (Js):

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

notice that data is an object.

On the server (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;
        }

and 'AllowCrossSiteJsonAttribute' is needed for cross domain requests:

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

Hope this was useful.

查看更多
临风纵饮
7楼-- · 2018-12-31 05:45

I don't have the reputation to comment, but in response/addition to Don F's answer:

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

A second parameter of true needs to be added to the json_decode function in order to properly return an associative array:

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

查看更多
登录 后发表回答