AngularJs $ http.post () không gửi dữ liệu


337

Bất cứ ai có thể cho tôi biết tại sao tuyên bố sau không gửi dữ liệu bài đăng đến url được chỉ định? Url được gọi nhưng trên máy chủ khi tôi in $ _POST - Tôi nhận được một mảng trống. Nếu tôi in thông báo trong bảng điều khiển trước khi thêm nó vào dữ liệu - nó sẽ hiển thị nội dung chính xác.

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

Tôi cũng đã thử dữ liệu dưới dạng chuỗi (có cùng kết quả):

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

Nó dường như hoạt động khi tôi sử dụng nó ở định dạng sau:

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

nhưng có cách nào để làm điều đó với $ http.post () - và tôi có luôn phải bao gồm tiêu đề để nó hoạt động không? Tôi tin rằng loại nội dung trên là chỉ định định dạng của dữ liệu đã gửi, nhưng tôi có thể gửi nó dưới dạng đối tượng javascript không?


Là url trong cùng một nguồn gốc?
fmquaglia

Xin lỗi - có cho tất cả các ví dụ, đó là cùng một url
Spencer Mark

@SpencerMark xin lỗi .. tôi đã thử ở trên mã làm việc của bạn .. nó không hoạt động với tôi.
Arul Sidthan

Câu trả lời:


345

Tôi gặp vấn đề tương tự khi sử dụng asp.net MVC và tìm thấy giải pháp ở đây

Có nhiều sự nhầm lẫn giữa những người mới sử dụng AngularJS về lý do tại sao các $httpchức năng tốc ký dịch vụ ( $http.post(), v.v.) dường như không thể hoán đổi được với các tương đương của jQuery ( jQuery.post(), v.v.)

Sự khác biệt là ở cách jQueryAngularJS tuần tự hóa và truyền dữ liệu. Về cơ bản, vấn đề nằm ở việc ngôn ngữ máy chủ của bạn không thể hiểu được truyền dẫn của AngularJS ... Theo mặc định, jQuery truyền dữ liệu bằng cách sử dụng

Content-Type: x-www-form-urlencoded

và sự foo=bar&baz=moetuần tự hóa quen thuộc .

AngularJS , tuy nhiên, truyền dữ liệu bằng cách sử dụng

Content-Type: application/json 

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

Tuần tự hóa JSON, không may là một số ngôn ngữ máy chủ Web, đặc biệt là PHP PHP, không hủy kích hoạt nguyên bản.

Hoạt động như một lá bùa.

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

7
Tôi đã thêm tập lệnh này để cung cấp, sử dụng bower install angular-post-fix --save-devđể thêm nó.
Billy Blaze

vì vậy có cách nào để thay đổi phương thức truyền dữ liệu của php. Bởi vì đó là vấn đề tôi đang có hiện tại.
Demodave

1
Mã này hoạt động tốt trên hầu hết các phần, nhưng tôi đã gặp vấn đề với nó khi gửi một hệ thống phân cấp của các đối tượng trống hoặc thậm chí các giá trị trống phẳng. Ví dụ: {a: 1, b: {c: {d: {}}}, e: không xác định, f: null, g: 2} sẽ không được mã hóa chính xác và PHP sẽ lấy nó dưới dạng ["a" = > "1", "g" => "2"]. Toàn bộ cấu trúc trong "b", cũng như "e" và "f", bao gồm cả các phím - sẽ bị mất. Tôi đã đăng mã thay thế bên dưới, với cấu trúc trên được giải mã thành: ["a" => "1", "b" => ["c" => ["d" => ""]], "e" => "", "f" => "", "g" => "2"].
tuân theo

1
Làm thế nào tôi nên thực hiện điều này cho nhiều dữ liệu / biểu mẫu?
davidlee

Tuyệt vời :) Quả thực làm việc như một lá bùa. Tôi đã đối mặt với vấn đề với Spring MVC
SKaul

115

Không rõ lắm ở trên, nhưng nếu bạn nhận được yêu cầu trong PHP, bạn có thể sử dụng:

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

Để truy cập một mảng trong PHP từ AngularJS POST.


3
Tôi cần thêm true để buộc nó vào một mảng khi ghi đè mảng $ _POST với nó. json_decode(file_get_contents('php://input'), true);
Jon

4
@Zalaboza, tôi đồng ý rằng thật khó để có bất kỳ giải pháp nào được coi là 'phổ quát' nhưng tôi không đồng ý rằng đó là 'hacky' --- php.net tuyên bố: "file_get_contents () là cách ưa thích để đọc nội dung của một tập tin thành một chuỗi. Nó sẽ sử dụng các kỹ thuật ánh xạ bộ nhớ nếu được hệ điều hành của bạn hỗ trợ để nâng cao hiệu suất. " Cấp cho chúng tôi không đọc một tập tin trong tình huống này nhưng chúng tôi vẫn đọc dữ liệu json được đăng. Sẽ thật tuyệt nếu bạn có thể đóng góp một câu trả lời mới hoặc cung cấp thông tin mới để giúp độc giả (bao gồm cả bản thân tôi) đưa ra quyết định tốt hơn về vấn đề này.
Don F

78

Bạn có thể đặt "Loại nội dung" mặc định như thế này:

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

Về datađịnh dạng:

Các phương thức $ http.post và $ http.put chấp nhận bất kỳ giá trị đối tượng JavaScript (hoặc chuỗi) nào làm tham số dữ liệu của chúng. Nếu dữ liệu là một đối tượng JavaScript, theo mặc định, nó sẽ được chuyển đổi thành một chuỗi JSON.

Cố gắng sử dụng biến thể này

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

9
Nó dường như không hoạt động. Tôi vừa thử biến thể với dữ liệu dưới dạng chuỗi và: tiêu đề: {'Kiểu nội dung': 'application / x-www-form-urlencoding'} - và điều đó có vẻ hiệu quả, nhưng có cách nào tốt hơn nó không
Spencer Mark

2
Đặt loại nội dung mặc định như được mô tả ở trên và đối với dữ liệu không sử dụng đối tượng js. Sử dụng chuỗi như thế này: 'message =' + message Hoạt động cho tôi
gS lỗi 21/2/2015

58

Tôi đã có một vấn đề tương tự, và tôi tự hỏi nếu điều này cũng có thể hữu ích: 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'}
})

Trân trọng,


Có vẻ như các tiêu đề là thay đổi duy nhất chúng tôi cần. Cảm ơn bạn!
Ben Guthrie

Cảm ơn, điều đó đã giúp tôi :) Vấn đề là mã hóa dữ liệu POST.
Daan

33

Tôi thích sử dụng một chức năng để chuyển đổi các đối tượng để đăng 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'}
})

30

Điều này cuối cùng đã được giải quyết trong góc 1.4 bằng cách sử dụng $ httpParamSerializerJQLike

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

Tôi đang gặp vấn đề POST 192.168.225.75:7788/procure/p/search 400 (Yêu cầu xấu)
Anuj

19

Tôi sử dụng jQuery param với bài đăng requrest của AngularJS . Dưới đây là một ví dụ ... tạo mô-đun ứng dụng AngularJS, myappđược xác định ng-apptrong mã HTML của bạn.

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

Bây giờ hãy để chúng tôi tạo một Trình điều khiển đăng nhập và POST email và mật khẩu.

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

Tôi không muốn làm mất mã, nó đủ đơn giản để hiểu :) Lưu ý đó paramlà từ jQuery, vì vậy bạn phải cài đặt cả jQuery và AngularJS để làm cho nó hoạt động. Đây là một ảnh chụp màn hình.

nhập mô tả hình ảnh ở đây

Hy vọng điều này là hữu ích. Cảm ơn!


10

Tôi gặp vấn đề tương tự với AngularJS và Node.js + Express 4 + Router

Bộ định tuyến mong đợi dữ liệu từ yêu cầu của bài viết trong cơ thể. Cơ thể này luôn trống nếu tôi làm theo ví dụ từ Angular Docs

Ký hiệu 1

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

Nhưng nếu tôi sử dụng nó trong dữ liệu

Ký hiệu 2

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

Chỉnh sửa 1:

Nếu không, bộ định tuyến node.js sẽ mong đợi dữ liệu trong req.body nếu được sử dụng ký hiệu 1:

req.body.msg

Mà cũng gửi thông tin dưới dạng tải trọng JSON. Điều này tốt hơn trong một số trường hợp bạn có mảng trong json và x-www-form-urlencoding sẽ gây ra một số vấn đề.

nó đã làm việc. Hy vọng nó giúp.


10

Không giống như JQuery và vì mục đích giáo dục, Angular sử dụng định dạng JSON để truyền dữ liệu POST từ máy khách sang máy chủ (có lẽ JQuery áp dụng x-www-form-urlencoding, mặc dù JQuery và Angular sử dụng JSON để nhập dữ liệu). Do đó, có hai phần của vấn đề: trong phần máy khách js và phần máy chủ của bạn. Vì vậy bạn cần:

  1. đặt phần máy khách js Angular như thế này:

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

  1. ghi vào phần máy chủ của bạn để nhận dữ liệu từ máy khách (nếu đó là php).

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

Lưu ý: $ _POST sẽ không hoạt động!

Các giải pháp làm việc cho tôi tốt, hy vọng, và cho bạn.


8

Để gửi dữ liệu qua Post methode với $httpangularjs, bạn cần thay đổi

data: "message=" + message, với data: $.param({message:message})


1
Tại sao dữ liệu: $ .param cần thiết khi gửi dữ liệu bài đăng AngularJS?
bầu trời xanh

7

Để xây dựng dựa trên câu trả lời của @ felipe-miosso:

  1. Tải xuống dưới dạng mô-đun AngularJS từ đây ,
  2. Cài đặt nó
  3. Thêm nó vào ứng dụng của bạn:

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

6

Tôi không có tiếng tăm để bình luận, nhưng để đáp lại / thêm vào câu trả lời của Don F:

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

Một tham số thứ hai truecần được thêm vào json_decodehàm để trả về đúng một mảng kết hợp:

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


6

Góc cạnh

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

5

Mã này đã giải quyết vấn đề cho tôi. Đây là một giải pháp cấp ứng dụng:

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

5

Thêm phần này vào tệp js của bạn:

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

và thêm nó vào tập tin máy chủ của bạn:

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

Cần làm việc.


4

Tôi cũng gặp phải vấn đề tương tự và tôi đã làm một cái gì đó như thế này và nó đã không hoạt động. Bộ điều khiển Spring của tôi không thể đọc tham số dữ liệu.

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

Nhưng đọc diễn đàn này và API Doc, tôi đã thử làm theo cách đó và nó hiệu quả với tôi. Nếu ai đó cũng có vấn đề tương tự, bạn cũng có thể thử cách dưới đây.

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

Vui lòng kiểm tra https://docs.angularjs.org/api/ng/service/ $ http # post để biết cấu hình param nào. {data: '"id": "1"'} - Bản đồ các chuỗi hoặc đối tượng sẽ được chuyển thành URL? data = "id: 1"


4

Đây có lẽ là một câu trả lời muộn nhưng tôi nghĩ cách đúng đắn nhất là sử dụng cùng một đoạn mã sử dụng góc khi thực hiện một yêu cầu "nhận" bằng cách sử dụng bạn $httpParamSerializersẽ phải tiêm nó vào bộ điều khiển của bạn để bạn có thể chỉ cần làm như sau mà không cần phải làm sử dụng Jquery $http.post(url,$httpParamSerializer({param:val}))

app.controller('ctrl',function($scope,$http,$httpParamSerializer){
    $http.post(url,$httpParamSerializer({param:val,secondParam:secondVal}));
}

4

Trong trường hợp của tôi, tôi giải quyết vấn đề như thế này:

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;

Bạn cần sử dụng JSON.opesify cho mỗi param chứa một đối tượng JSON và sau đó xây dựng đối tượng dữ liệu của bạn với "$ .param" :-)

NB: "objJSON" của tôi là một đối tượng JSON chứa nội dung mảng, số nguyên, chuỗi và html. Tổng kích thước của anh là> 3500 ký tự.


3

Tôi biết đã chấp nhận câu trả lời. Nhưng, sau đây có thể giúp ích cho độc giả trong tương lai, nếu câu trả lời không phù hợp với họ vì bất kỳ lý do nào.

Angular không làm ajax giống như jQuery. Trong khi tôi cố gắng làm theo hướng dẫn để sửa đổi góc cạnh $httpprovider, tôi đã gặp phải các vấn đề khác. Ví dụ: tôi sử dụng codeigniter trong đó $this->input->is_ajax_request()hàm luôn bị lỗi (được viết bởi một lập trình viên khác và được sử dụng trên toàn cầu, vì vậy không thể thay đổi) nói rằng đây không phải là yêu cầu ajax thực sự.

Để giải quyết nó, tôi đã giúp đỡ về lời hứa hoãn lại . Tôi đã thử nghiệm nó trong Firefox và eg9 và nó đã hoạt động.

Tôi có hàm sau được định nghĩa bên ngoài bất kỳ mã góc nào. Hàm này thực hiện cuộc gọi ajax jquery thường xuyên và trả về đối tượng hoãn / hứa (tôi vẫn đang học).

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

Sau đó, tôi gọi nó là mã góc bằng cách sử dụng mã sau đây. Xin lưu ý rằng chúng tôi phải cập nhật$scope thủ công bằng cách sử dụng $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!");
    });

Đây có thể không phải là câu trả lời hoàn hảo, nhưng nó cho phép tôi sử dụng các cuộc gọi ajax jquery với góc cạnh và cho phép tôi cập nhật $scope.


2
Angular có dịch vụ hứa hẹn của riêng mình được gọi là $ q kể từ 1.3. Không cần sử dụng JQuery cho một bài viết.
mbokil

3

Tôi đã có cùng một vấn đề trong express .. để giải quyết bạn phải sử dụng bodyparser để phân tích các đối tượng json trước khi gửi yêu cầu http ..

app.use(bodyParser.json());

3

Tôi đang sử dụng dịch vụ web asp.net WCF với js góc và mã bên dưới hoạt động:

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

Hy vọng nó giúp.


3

Không tìm thấy một đoạn mã hoàn chỉnh về cách sử dụng phương thức $ http.post để gửi dữ liệu đến máy chủ và tại sao nó không hoạt động trong trường hợp này.

Giải thích về đoạn mã dưới đây ...

  1. Tôi đang sử dụng hàm jQuery $ .param để tuần tự hóa dữ liệu JSON thành dữ liệu bài đăng www
  2. Đặt Loại nội dung trong biến cấu hình sẽ được chuyển cùng với yêu cầu của angularJS $ http.post hướng dẫn máy chủ rằng chúng tôi đang gửi dữ liệu ở định dạng bài đăng www.

  3. Lưu ý phương thức $ ometp.post, trong đó tôi đang gửi tham số thứ 1 dưới dạng url, tham số thứ 2 dưới dạng dữ liệu (tuần tự hóa) và tham số thứ 3 dưới dạng cấu hình.

Mã còn lại là tự hiểu.

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

Nhìn vào ví dụ mã của phương thức $ http.post ở đây .



3

Nếu sử dụng Angular> = 1.4 , đây là giải pháp sạch nhất sử dụng serializer được cung cấp bởi 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';
});

Và sau đó bạn có thể chỉ cần làm điều này ở bất cứ đâu trong ứng dụng của bạn:

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

Và nó sẽ tuần tự hóa dữ liệu một cách chính xác param1=value1&param2=value2và gửi nó đến /requesturlvớiapplication/x-www-form-urlencoded; charset=utf-8 tiêu đề Kiểu nội dung như thường thấy với các yêu cầu POST trên các điểm cuối.

TL; DR

Trong quá trình nghiên cứu tôi thấy rằng câu trả lời cho vấn đề này có nhiều hương vị khác nhau; một số rất phức tạp và phụ thuộc vào các hàm tùy chỉnh, một số phụ thuộc vào jQuery và một số không hoàn chỉnh khi đề xuất rằng bạn chỉ cần đặt tiêu đề.

Nếu bạn chỉ đặt Content-Typetiêu đề, điểm cuối sẽ thấy dữ liệu POST, nhưng nó sẽ không ở định dạng chuẩn vì trừ khi bạn cung cấp một chuỗi nhưdata , hoặc tuần tự hóa đối tượng dữ liệu của bạn, tất cả sẽ được tuần tự hóa dưới dạng JSON mặc định và có thể được giải thích không chính xác ở điểm cuối.

ví dụ: nếu bộ nối tiếp đúng không được đặt trong ví dụ trên, nó sẽ được nhìn thấy ở điểm cuối là:

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

Và điều đó có thể dẫn đến phân tích cú pháp bất ngờ, ví dụ ASP.NET coi nó như một nulltên tham số, với {"param1":"value1","param2":"value2"}giá trị là; hoặc Fiddler diễn giải nó theo cách khác, với {"param1":"value1","param2":"value2"}tên tham số và nullgiá trị.


3

Tương tự như định dạng làm việc được đề xuất của OP & câu trả lời của Denison, ngoại trừ việc sử dụng $http.postthay vì chỉ $httpvà vẫn phụ thuộc vào jQuery.

Điểm hay của việc sử dụng jQuery ở đây là các đối tượng phức tạp được truyền đúng; chống lại việc chuyển đổi thủ công thành các tham số URL có thể bị cắt xén dữ liệu.

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

2

Khi tôi gặp vấn đề này, tham số tôi đã đăng hóa ra là một mảng các đối tượng thay vì một đối tượng đơn giản.


2

Chỉ cần cập nhật từ góc 1,2 đến 1,3, đã tìm thấy một vấn đề trong mã. Việc chuyển đổi một tài nguyên sẽ dẫn đến một vòng lặp vô tận bởi vì (tôi nghĩ) về lời hứa $ giữ lại cùng một đối tượng. Có lẽ nó sẽ giúp được ai đó ...

Tôi có thể khắc phục điều đó bằng cách:

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

2

Tôi đã sử dụng mã câu trả lời được chấp nhận (mã của Felipe) trong một thời gian và nó đã hoạt động rất tốt (cảm ơn, Felipe!).

Tuy nhiên, gần đây tôi phát hiện ra rằng nó có vấn đề với các đối tượng hoặc mảng trống. Ví dụ: khi gửi đối tượng này:

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

PHP dường như không thấy B và C nào cả. Nó nhận được điều này:

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

Nhìn vào yêu cầu thực tế trong Chrome cho thấy điều này:

A: 1
:
D: 2

Tôi đã viết một đoạn mã thay thế. Nó có vẻ hoạt động tốt với các trường hợp sử dụng của tôi nhưng tôi chưa thử nghiệm rộng rãi vì vậy hãy thận trọng khi sử dụng.

Tôi đã sử dụng TypeScript vì tôi thích gõ mạnh nhưng sẽ dễ dàng chuyển đổi sang JS thuần túy:

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

Nó kém hiệu quả hơn mã của Felipe nhưng tôi không nghĩ nó quan trọng lắm vì nó phải ngay lập tức so với tổng chi phí chung của chính yêu cầu HTTP.

Bây giờ PHP hiển thị:

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

Theo như tôi biết thì không thể để PHP nhận ra rằng Ba và C là các mảng trống, nhưng ít nhất các khóa xuất hiện, điều này rất quan trọng khi có mã dựa trên một cấu trúc nhất định ngay cả khi bên trong nó trống rỗng.

Cũng lưu ý rằng nó chuyển đổi s và null s không xác định thành chuỗi rỗng.


TypeScript cách tốt nhất để viết mã trong POO bằng JavaScript!
Biến hình

2

Chỉ cần đặt dữ liệu bạn muốn gửi làm tham số thứ hai:

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

Một hình thức khác cũng hoạt động là:

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

Đảm bảo rằng paramName khớp chính xác với tên của tham số của hàm bạn đang gọi.

Nguồn: Phương pháp phím tắt bài AngularJS


5
Bất cứ ai có thể giải thích tại sao câu trả lời này đã được bỏ phiếu?
Marco Lackovic

1
Không có cách nào mà giải pháp này được bỏ phiếu, đó là cách đơn giản nhất, ngắn nhất và được chứng minh trong tài liệu góc cạnh docs.angularjs.org/api/ng/service/$http
ainasiart

1

Tôi đã giải quyết điều này bằng các mã dưới đây:

Phía khách hàng (Js):

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

lưu ý rằng dữ liệu là một đối tượng.

Trên máy chủ (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;
        }

và 'AllowCrossSiteJsonAttribution' là cần thiết cho các yêu cầu tên miền chéo:

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

Hy vọng điều này là hữu ích.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.