AngularJs $http.post() does not send data
Asked Answered
A

37

343

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?

Amorino answered 8/10, 2013 at 17:7 Comment(3)
Is the url in the same origin?Piliferous
Sorry - yes for all examples it's the same urlAmorino
@SpencerMark sorry.. i tried above your working code.. its not working for me.Terrazas
P
347

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;
  }];
});
Pendent answered 29/11, 2013 at 0:45 Comment(9)
I have add'd this script to bower, use bower install angular-post-fix --save-dev to add it.Yesteryear
so is there a way to change php's transmits data method. Because that is the issue I am having currently.Ghetto
This code works great on the most part, but I've had issues with it when submitting a hierarchy of empty objects or even flat empty values. For example, { a: 1, b: { c: { d: { } } }, e: undefined, f: null, g: 2 } will not be encoded properly, and PHP will get it as [ "a" => "1", "g" => "2" ]. The entire structure under "b", as well as "e" and "f", including the keys themselves - would be lost. I posted alternative code below, with which the above structure gets decoded as: [ "a" => "1", "b" => [ "c" => [ "d" => "" ] ], "e" => "", "f" => "", "g" => "2" ].Inwrought
how should i implement this for multipart/form-data?Sabba
Superb :) Indeed worked like a charm. I faced the issue with Spring MVCArchpriest
@Inwrought this skips empty array alsoSaid
Here is a modernized version of this code.Wessels
Still I assume the client won't be able to know which form the server is understanding the message. whether its Content-Type: x-www-form-urlencoded or Content-Type: application/jsonFritter
Content-Type: application/json this is work for me. ThanksHierophant
M
116

It's not super clear above, but if you are receiving the request in PHP you can use:

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

To access an array in PHP from an AngularJS POST.

Martyry answered 27/10, 2014 at 16:35 Comment(2)
I needed to add true to force it to an array when overwriting the $_POST array with it. json_decode(file_get_contents('php://input'), true);Ingridingrim
@Zalaboza, I would agree that it is tough to have any solution considered 'universal' but I don't agree that it is 'hacky'--- php.net states: "file_get_contents() is the preferred way to read the contents of a file into a string. It will use memory mapping techniques if supported by your OS to enhance performance." Granted we're not reading a file in this situation but we are nonetheless reading posted json data. It would be great if you could contribute a new answer or provide new information to help readers (including myself) make a better decision about this.Martyry
V
78

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
    });
}
Volta answered 8/10, 2013 at 17:14 Comment(2)
It doesn't seem to work. I've just tried the variation with the data as string and : headers: {'Content-Type': 'application/x-www-form-urlencoded'} - and that seem to work, but is there a better way of doing it?Amorino
Set default content type as described above and for data don't use js object. Use string like this: 'message='+message Works for meOfficiary
P
62

I have had a similar issue, and I wonder if this can be useful as well: 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'}
})

Regards,

Preferable answered 31/5, 2014 at 3:54 Comment(2)
It looks like the headers was the only change we needed. Thank you!Curacy
Thanks, that did it for me :) The problem was the encoding of the POST data.Grekin
S
34

I like to use a function to convert objects to post 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'}
})
Stotinka answered 29/8, 2014 at 14:10 Comment(0)
J
30

This has finally been addressed in angular 1.4 using $httpParamSerializerJQLike

See 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'
})})
Jonell answered 10/9, 2015 at 16:25 Comment(1)
I am facing issue POST 192.168.225.75:7788/procure/p/search 400 (Bad Request)Intoxicated
B
20

I use jQuery param with AngularJS post requrest. Here is a example ... create AngularJS application module, where myapp is defined with ng-app in your HTML code.

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

Now let us create a Login controller and POST email and password.

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

I don't like to exaplain the code, it is simple enough to understand :) Note that param is from jQuery, so you must install both jQuery and AngularJS to make it working. Here is a screenshot.

enter image description here

Hope this is helpful. Thanks!

Bacillus answered 17/7, 2015 at 12:18 Comment(0)
D
10

I had the same problem with AngularJS and Node.js + Express 4 + Router

Router expects the data from post's request in body. This body was always empty if i followed the example from Angular Docs

Notation 1

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

But if i used it in the data

Notation 2

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

Edit 1:

Otherwise node.js router will expect the data in req.body if used notation 1:

req.body.msg

Which also sends the information as JSON payload. This is better in some cases where you have arrays in your json and x-www-form-urlencoded will give some problems.

it worked. Hope it helps.

Dorkus answered 11/10, 2014 at 19:13 Comment(0)
M
10

Unlike JQuery and for the sake of pedantry, Angular uses JSON format for POST data transfer from a client to the server (JQuery applies x-www-form-urlencoded presumably, although JQuery and Angular uses JSON for data imput). Therefore there are two parts of problem: in js client part and in your server part. So you need:

  1. put js Angular client part like this:

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

AND

  1. write in your server part to receive data from a client (if it is php).

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

Note: $_POST will not work!

The solution works for me fine, hopefully, and for you.

Mismatch answered 18/4, 2015 at 2:31 Comment(0)
A
8

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']);
    
Azotemia answered 19/11, 2014 at 20:28 Comment(0)
E
8

To send data via Post methode with $http of angularjs you need to change

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

Ellon answered 16/5, 2015 at 10:50 Comment(1)
why is data: $.param required when sending AngularJS post data ?Palatine
T
6

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

Toe answered 21/2, 2015 at 21:15 Comment(0)
P
6

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();
        }
Patrilineage answered 22/7, 2015 at 15:7 Comment(0)
S
6

This code solved the issue for me. It is an application-level solution:

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";
  }
]);
Strode answered 27/7, 2015 at 15:21 Comment(0)
D
5

Add this in your js file:

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

and add this to your server file:

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

That should work.

Decompose answered 21/12, 2015 at 11:45 Comment(0)
F
5

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.

Foramen answered 28/7, 2016 at 10:29 Comment(0)
S
4

I also faced similar problem and i was doing something like this and that didn't worked. My Spring controller was not able read data parameter.

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

But reading this forum and API Doc, I tried following way and that worked for me. If some one also have similar problem, You can try below way as well.

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

Please check https://docs.angularjs.org/api/ng/service/$http#post for what param config does. {data:'"id":"1"'} – Map of strings or objects which will be turned to URL?data="id:1"

Stamm answered 22/1, 2015 at 13:16 Comment(0)
A
4

this is probably a late answer but i think the most proper way is to use the same piece of code angular use when doing a "get" request using you $httpParamSerializer will have to inject it to your controller so you can simply do the following without having to use Jquery at all , $http.post(url,$httpParamSerializer({param:val}))

app.controller('ctrl',function($scope,$http,$httpParamSerializer){
    $http.post(url,$httpParamSerializer({param:val,secondParam:secondVal}));
}
Apulia answered 24/5, 2016 at 18:20 Comment(0)
C
4

Similar to the OP's suggested working format & Denison's answer, except using $http.post instead of just $http and is still dependent on jQuery.

The good thing about using jQuery here is that complex objects get passed properly; against manually converting into URL parameters which may garble the data.

$http.post( 'request-url', jQuery.param( { 'message': message } ), {
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});
Calico answered 24/7, 2016 at 3:20 Comment(0)
F
3

I know has accepted answer. But, following might help to future readers, if the answer doesn't suit them for any reason.

Angular doesn't do ajax same as jQuery. While I tried to follow the guide to modify angular $httpprovider , I encountered other problems. E.g. I use codeigniter in which $this->input->is_ajax_request() function always failed (which was written by another programmer and used globally, so cant change) saying this was not real ajax request.

To solve it, I took help of deferred promise. I tested it in Firefox, and ie9 and it worked.

I have following function defined outside any of the angular code. This function makes regular jquery ajax call and returns deferred/promise (I'm still learning) object.

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

Then I'm calling it angular code using the following code. Please note that we have to update the $scope manually using $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!");
    });

This may not be the perfect answer, but it allowed me to use jquery ajax calls with angular and allowed me to update the $scope.

Froe answered 22/5, 2014 at 1:2 Comment(1)
Angular has it own promises service called $q since 1.3. No need to use JQuery for a post.Raddie
W
3

I had the same problem in express .. to resolve you have to use bodyparser to parse json objects before sending http requests ..

app.use(bodyParser.json());
Wayworn answered 2/5, 2015 at 22:5 Comment(0)
L
3

I am using asp.net WCF webservices with angular js and below code worked:

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

Hope it helps.

Legation answered 20/7, 2015 at 14:39 Comment(0)
A
3

Didn't find a complete code snippet of how to use $http.post method to send data to the server and why it was not working in this case.

Explanations of below code snippet...

  1. I am using jQuery $.param function to serialize the JSON data to www post data
  2. Setting the Content-Type in the config variable that will be passed along with the request of angularJS $http.post that instruct the server that we are sending data in www post format.

  3. Notice the $htttp.post method, where I am sending 1st parameter as url, 2nd parameter as data (serialized) and 3rd parameter as config.

Remaining code is self understood.

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

Look at the code example of $http.post method here.

Ascidian answered 11/12, 2015 at 3:54 Comment(0)
W
3

If your using PHP this is a easy way to access an array in PHP from an AngularJS POST.

$params = json_decode(file_get_contents('php://input'),true);
Washedout answered 11/12, 2015 at 22:57 Comment(1)
This article may help people.Englebert
G
3

Just put the data you want to send as second parameter:

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

Another form which also works is:

$http.post('request-url',  { params: { paramName: value } });

Make sure that paramName exactly matches the name of the parameter of the function you are calling.

Source: AngularJS post shortcut method

Geometer answered 29/2, 2016 at 12:29 Comment(2)
Can anybody explain why this answer has been voted down?Geometer
There is no way that this solution is voted down, it's the simplest, shortest and proven in angular documentation docs.angularjs.org/api/ng/service/$httpAsymmetry
U
3

If using Angular >= 1.4, here's the cleanest solution using the serializer provided by 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';
});

And then you can simply do this anywhere in your app:

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

And it will correctly serialize the data as param1=value1&param2=value2 and send it to /requesturl with the application/x-www-form-urlencoded; charset=utf-8 Content-Type header as it's normally expected with POST requests on endpoints.

TL;DR

During my research I found that the answer to this problem comes in many different flavors; some are very convoluted and depend on custom functions, some depend on jQuery and and some are incomplete in suggesting that you only need to set the header.

If you just set the Content-Type header, the end point will see the POST data, but it won't be in the standard format because unless you provide a string as your data, or manually serialize your data object, it will all be serialized as JSON by default and may be incorrectly interpreted at the endpoint.

e.g. if the correct serializer was not set in the above example, it would be seen in the endpoint as:

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

And that can lead to unexpected parsing, e.g. ASP.NET treats it as a null parameter name, with {"param1":"value1","param2":"value2"} as value; or Fiddler interprets it the other way, with {"param1":"value1","param2":"value2"} as the parameter name, and null as the value.

Uphold answered 18/5, 2016 at 9:46 Comment(0)
P
2

When I had this problem the parameter I was posting turned out to be an array of objects instead of a simple object.

Pfennig answered 9/2, 2015 at 20:32 Comment(0)
A
2

Just updated from angular 1.2 to 1.3, have found a problem in the code. Transforming a resource will lead to an endless-loop because (I think) of the $promise holding again the same object. Maybe it will help someone...

I could fix that by:

[...]
  /**
 * 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) {
[...]
Aliped answered 3/5, 2015 at 17:31 Comment(0)
I
2

I've been using the accepted answer's code (Felipe's code) for a while and it's been working great (thanks, Felipe!).

However, recently I discovered that it has issues with empty objects or arrays. For example, when submitting this object:

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

PHP doesn't seem to see B and C at all. It gets this:

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

A look at the actual request in Chrome shows this:

A: 1
:
D: 2

I wrote an alternative code snippet. It seems to work well with my use-cases but I haven't tested it extensively so use with caution.

I used TypeScript because I like strong typing but it would be easy to convert to pure 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("&");
    } ];
} ]);

It's less efficient than Felipe's code but I don't think it matters much since it should be immediate compared to the overall overhead of the HTTP request itself.

Now PHP shows:

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

As far as I know it's not possible to get PHP to recognize that B.a and C are empty arrays, but at least the keys appear, which is important when there's code that relies on the a certain structure even when its essentially empty inside.

Also note that it converts undefineds and nulls to empty strings.

Inwrought answered 6/10, 2015 at 22:40 Comment(1)
TypeScript the best way to code in POO with JavaScript !Dehiscent
G
1

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.

Gleason answered 23/5, 2015 at 11:4 Comment(0)
F
1

It's not angular's fault. Angular is designed to work in JSON world. So when $http service send AJAX request, it send all your data as a payload, not as form-data so that your backend application can handle it. But jQuery does some things internally. You instruct jQuery's $ajax module to bind form-data as JSON but before sending AJAX request, it serialized JSON and add application/x-www-form-urlencoded header. This way your backend application able to received form-data in form of post parameters and not JSON.

But you can modify angular $http service's default behavior by

  1. Adding header
  2. Serializing json

$httpParamSerializerJQLike is angular's in-built service which serializes json in the same way $.param does of jQuery.

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

If you need a plugin to serialize form-data into JSON first, use this one https://github.com/marioizquierdo/jquery.serializeJSON

Fronde answered 29/4, 2016 at 12:35 Comment(2)
when I tried with, $http.put('/api/', {name:1}). it's sending with serialized json data. but for POST, I need to set header and serialize the data as you said. do you know why PUT doesn't need that, but only POST need?Hornwort
That's impossible.Fronde
O
0

use this way. no need to write so much

 isAuth = $http.post("Yr URL", {username: username, password: password});

and in the nodejs back end

app.post("Yr URL",function(req,resp)
{

  var username = req.body.username||req.param('username');
  var password = req.body.password||req.param('password');
}

I hope this helps

Opulent answered 31/8, 2015 at 7:18 Comment(0)
V
0

I wrote a small PHP helper function that allows both types of input parameters :

function getArgs () {
    if ($input = file_get_contents('php://input') && $input_params = json_decode($input,true))
        return $input_params + $_POST + $_GET;
    return $_POST + $_GET;
}

Usage :

<?php
    include("util.php"); # above code
    $request = getArgs();

    $myVar = "";
    if (isset($request['myVar']))
        $myVar = $request['myVar'];
?>

Therefore no changes required to your JavaScript.

Venita answered 20/9, 2015 at 3:3 Comment(0)
A
0

By using very simple method, we can follow this:

 $http({
        url : "submit_form_adv.php",
        method : 'POST',
        headers: {'Content-Type': 'application/x-www-form-urlencoded'},
        transformRequest: function(obj) {
            var str = [];
            for(var p in obj)
                str.push(encodeURIComponent(p)+' = '+encodeURIComponent(obj[p]));

            return str.join('&');
        },
        data : {sample_id : 100, sample_name: 'Abin John'},

    }).success(function(data, status, headers, config) {

    }).error(function(ata, status, headers, config) {

    });
Acetous answered 22/2, 2016 at 8:57 Comment(0)
S
0

Found the simple solution on

http://jasonwatmore.com/post/2014/04/18/post-a-simple-string-value-from-angularjs-to-net-web-api

return $http.post(Config.apiUrl + '/example/processfile', '"' + fileName + '"');
Subminiaturize answered 30/3, 2017 at 3:23 Comment(0)
W
0

Just proposing a modernized version of @FelipeMiosso's answer:

.config(["$httpProvider", function ($httpProvider) {

  function buildKey(parentKey, subKey) {
    return parentKey + "[" + subKey + "]";
  }

  function buildObject(key, value) {
    var object = {};
    object[key] = value;
    return object;
  }

  function join(array) {
    return array.filter(function (entry) {
      return entry;
    }).join("&");
  }

  function arrayToQueryString(parentKey, array) {
    return join(array.map(function (value, subKey) {
      return toQueryString(buildObject(buildKey(parentKey, subKey), value));
    }));
  }

  function objectToQueryString(parentKey, object) {
    return join(Object.keys(object).map(function (subKey) {
      return toQueryString(buildObject(buildKey(parentKey, subKey), object[subKey]));
    }));
  }

  function toQueryString(input) {
    return join(Object.keys(input).map(function (key) {
      var value = input[key];
      if (value instanceof Array) {
        return arrayToQueryString(key, value);
      } else if (value instanceof Object) {
        return objectToQueryString(key, value);
      } else if (undefined !== value && null !== value) {
        return encodeURIComponent(key) + "=" + encodeURIComponent(value);
      } else {
        return "";
      }
    }));
  }

  function isQueryStringEligible(input) {
    return null !== input && "object" === typeof input && "[object File]" !== String(input);
  }

  var interceptor = [function () {
    return {
      request: function (config) {
        if (0 <= ["post", "put", "patch"].indexOf(config.method.toLowerCase()) && isQueryStringEligible(config.data)) {
          config.headers["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8";
          config.data = toQueryString(config.data);
        }
        return config;
      }
    };
  }];

  $httpProvider.interceptors.push(interceptor);

}])

ES6 version:

.config(["$httpProvider", function ($httpProvider) {

  "use strict";

  const buildKey = (parentKey, subKey) => `${parentKey}[${subKey}]`;

  const buildObject = (key, value) => ({ [key]: value });

  const join = (array) => array.filter((entry) => entry).join("&");

  const arrayToQueryString = (parentKey, array) =>
    join(array.map((value, subKey) =>
      toQueryString(buildObject(buildKey(parentKey, subKey), value))));

  const objectToQueryString = (parentKey, object) =>
    join(Object.keys(object).map((subKey) =>
      toQueryString(buildObject(buildKey(parentKey, subKey), object[subKey]))));

  const toQueryString = (input) => join(Object.keys(input).map((key) => {
    const value = input[key];
    if (value instanceof Array) {
      return arrayToQueryString(key, value);
    } else if (value instanceof Object) {
      return objectToQueryString(key, value);
    } else if (undefined !== value && null !== value) {
      return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
    } else {
      return "";
    }
  }));

  const isQueryStringEligible = (input) =>
    null !== input && "object" === typeof input && "[object File]" !== String(input);

  const interceptor = [() => ({
    request(config) {
      if (0 <= ["post", "put", "patch"].indexOf(config.method.toLowerCase()) && isQueryStringEligible(config.data)) {
        config.headers["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8";
        config.data = toQueryString(config.data);
      }
      return config;
    }
  })];

  $httpProvider.interceptors.push(interceptor);

}])
Wessels answered 20/6, 2017 at 10:11 Comment(0)
B
0

I had this problem, the issue was i was not able to get the data while posting using above mentioned header i.e.

headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/x-www-form-urlencoded'
}

While using jquery Ajax we were usually getting data in response.body at the backend server, but while implementing Angular ajax the data was not coming in response.body instead it was coming under

request.getParameterMap.keySet().iterator().next()
Binford answered 7/8, 2017 at 11:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.