AngularJs $ http.post () nie wysyła danych

337

Czy ktoś mógłby mi powiedzieć, dlaczego poniższe oświadczenie nie wysyła danych do podanego adresu URL? Adres URL jest wywoływany, ale na serwerze, gdy drukuję $ _POST - dostaję pustą tablicę. Jeśli wydrukuję wiadomość w konsoli przed dodaniem jej do danych - pokazuje prawidłową treść.

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

Próbowałem również z danymi jako ciągiem znaków (z takim samym wynikiem):

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

Wygląda na to, że działa, gdy używam go w następującym formacie:

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

ale czy można to zrobić za pomocą $ http.post () - i czy zawsze muszę dołączać nagłówek, aby działał? Uważam, że powyższy typ zawartości określa format wysyłanych danych, ale czy mogę wysłać go jako obiekt javascript?

Spencer Mark
źródło
Czy adres URL jest tego samego pochodzenia?
fmquaglia
Przepraszamy - tak dla wszystkich przykładów jest to ten sam adres URL
Spencer Mark
@SpencerMark przepraszam .. próbowałem powyżej twojego działającego kodu .. to nie działa dla mnie.
Arul Sidthan,

Odpowiedzi:

346

Miałem ten sam problem przy użyciu asp.net MVC i znalazłem rozwiązanie tutaj

Istnieje duże zamieszanie wśród nowicjuszy w AngularJS, co do tego, dlaczego $httpfunkcje skróconej usługi ( $http.post()itp.) Nie wydają się być wymienne z odpowiednikami jQuery ( jQuery.post()itp.)

Różnica polega na tym, jak jQuery i AngularJS serializują i przesyłają dane. Zasadniczo problem polega na tym, że wybrany język serwera nie jest w stanie zrozumieć transmisji AngularJS natywnie ... Domyślnie jQuery przesyła dane za pomocą

Content-Type: x-www-form-urlencoded

i znana foo=bar&baz=moeserializacja.

Jednak AngularJS przesyła dane za pomocą

Content-Type: application/json 

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

Serializacja JSON, która niestety niektóre języki serwera WWW - w szczególności PHP - nie mogą odserializować natywnie.

Działa jak marzenie.

KOD

// 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;
  }];
});
Felipe Miosso
źródło
7
Dodałem ten skrypt do altany, użyj go, bower install angular-post-fix --save-devaby go dodać.
Billy Blaze,
jest więc sposób na zmianę metody transmisji danych przez php. Ponieważ to jest problem, który mam obecnie.
Demodave,
1
Ten kod działa w większości świetnie, ale miałem z nim problemy podczas przesyłania hierarchii pustych obiektów lub nawet płaskich pustych wartości. Na przykład {a: 1, b: {c: {d: {}}}, e: undefined, f: null, g: 2} nie zostaną poprawnie zakodowane, a PHP otrzyma je jako ["a" = > „1”, „g” => „2”]. Cała struktura pod „b”, a także „e” i „f”, w tym same klucze - zostałaby utracona. Poniżej zamieściłem alternatywny kod, za pomocą którego powyższa struktura jest dekodowana jako: [„a” => „1”, „b” => [„c” => [„d” => „”]], „e” => „”, „f” => „”, „g” => „2”].
obe
1
jak powinienem to zaimplementować dla danych wieloczęściowych / formularzy?
davidlee,
Znakomity :) Rzeczywiście działał jak urok. Problem z Spring MVC
SKaul
115

Nie jest to zbyt jasne powyżej, ale jeśli otrzymujesz żądanie w PHP, możesz użyć:

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

Aby uzyskać dostęp do tablicy w PHP z POST AngularJS.

Don F.
źródło
3
Musiałem dodać wartość true, aby wymusić ją w tablicy podczas nadpisywania tablicą $ _POST. json_decode(file_get_contents('php://input'), true);
Jon
4
@Zalaboza, zgodziłbym się, że trudno jest uznać jakiekolwiek rozwiązanie za „uniwersalne”, ale nie zgadzam się, że jest „hacky” --- php.net stwierdza: „file_get_contents () to preferowany sposób czytania zawartości pliku na ciąg. Wykorzysta techniki mapowania pamięci, jeśli jest obsługiwane przez system operacyjny w celu zwiększenia wydajności. ” To prawda, że ​​nie czytamy pliku w tej sytuacji, ale mimo to czytamy opublikowane dane JSON. Byłoby wspaniale, gdybyś mógł udzielić nowej odpowiedzi lub dostarczyć nowych informacji, aby pomóc czytelnikom (w tym mnie) podjąć lepszą decyzję w tej sprawie.
Don F
78

Możesz ustawić domyślny „typ zawartości” w następujący sposób:

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

Informacje o dataformacie:

Metody $ http.post i $ http.put przyjmują dowolną wartość obiektu JavaScript (lub ciąg znaków) jako parametr danych. Jeśli dane są obiektem JavaScript, domyślnie zostaną przekonwertowane na ciąg JSON.

Spróbuj użyć tej odmiany

function sendData($scope) {
    $http({
        url: 'request-url',
        method: "POST",
        data: { 'message' : message }
    })
    .then(function(response) {
            // success
    }, 
    function(response) { // optional
            // failed
    });
}
Denison Luz
źródło
9
Wydaje się, że to nie działa. Właśnie wypróbowałem wariant z danymi w postaci ciągu i: headers: {'Content-Type': 'application / x-www-form-urlencoded'} - i wydaje się, że to działa, ale czy istnieje lepszy sposób na zrobienie tego to?
Spencer Mark,
2
Ustaw domyślny typ zawartości, jak opisano powyżej, a dla danych nie używaj obiektu js. Użyj ciągów takich jak: „wiadomość =” + wiadomość Działa dla mnie
gSorry
58

Miałem podobny problem i zastanawiam się, czy to też może być przydatne: 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'}
})

Pozdrowienia,

ericson.cepeda
źródło
Wygląda na to, że nagłówki były jedyną potrzebną zmianą. Dziękuję Ci!
Ben Guthrie,
Dzięki, zrobiłem to dla mnie :) Problemem było kodowanie danych POST.
Daan
33

Lubię używać funkcji do konwersji obiektów na parametry postu.

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'}
})
Rômulo Collopy
źródło
30

Ten problem został w końcu rozwiązany w wersji kątowej 1.4 za pomocą $ httpParamSerializerJQLike

Zobacz 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'
})})
Stetzon
źródło
Mam do czynienia z problemem POST 192.168.225.75:7788/procure/p/search 400 (złe żądanie)
Anuj 15'17
19

Używam jQuery param z AngularJS post requrest. Oto przykład ... utwórz moduł aplikacji AngularJS, w którym myappjest zdefiniowany ng-appw kodzie HTML.

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

Utwórzmy teraz kontroler logowania oraz adres e-mail i hasło POST.

app.controller('LoginController', ['$scope', '$http', function ($scope, $http) {
    // default post header
    $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
    // send login data
    $http({
        method: 'POST',
        url: 'https://example.com/user/login',
        data: $.param({
            email: $scope.email,
            password: $scope.password
        }),
        headers: {'Content-Type': 'application/x-www-form-urlencoded'}
    }).success(function (data, status, headers, config) {
        // handle success things
    }).error(function (data, status, headers, config) {
        // handle error things
    });
}]);

Nie lubię tłumaczyć kodu, wystarczy go zrozumieć :) Zauważ, że parampochodzi z jQuery, więc musisz zainstalować zarówno jQuery, jak i AngularJS, aby działało. Oto zrzut ekranu.

wprowadź opis zdjęcia tutaj

Mam nadzieję, że to jest pomocne. Dzięki!

Madan Sapkota
źródło
10

Miałem ten sam problem z AngularJS i Node.js + Express 4 + Router

Router oczekuje danych od żądania postu w treści. To ciało było zawsze puste, gdybym podążał za przykładem z Angular Docs

Notacja 1

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

Ale jeśli użyłem tego w danych

Notacja 2

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

Edycja 1:

W przeciwnym razie router node.js będzie oczekiwał danych w body.qq, jeśli użyje notacji 1:

req.body.msg

Co również wysyła informacje jako ładunek JSON. Jest to lepsze w niektórych przypadkach, gdy masz tablice w swoim jsonie i x-www-form-urlencoded spowoduje pewne problemy.

zadziałało. Mam nadzieję, że to pomoże.

alknows
źródło
10

W przeciwieństwie do JQuery i ze względu na pedanterię, Angular używa formatu JSON do przesyłania danych POST od klienta do serwera (JQuery przypuszczalnie stosuje x-www-form-urlencoded, chociaż JQuery i Angular używa JSON do imputacji danych). Dlatego istnieją dwie części problemu: w części klienta js i części serwera. Potrzebujesz więc:

  1. umieść część klienta js Angular w ten sposób:

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

I

  1. napisz w części serwerowej, aby otrzymać dane od klienta (jeśli jest to php).

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

Uwaga: $ _POST nie będzie działać!

Mam nadzieję, że rozwiązanie działa dobrze dla mnie i dla ciebie.

rzymski
źródło
8

Aby przesyłać dane za pomocą $httpmetody Post z angularjs, musisz zmienić

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

BERGUIGA Mohamed Amine
źródło
1
dlaczego dane: $ .param jest wymagany podczas wysyłania danych postu AngularJS?
błękitne niebo
7

Aby skorzystać z odpowiedzi @ felipe-miosso:

  1. Pobierz go jako moduł AngularJS stąd ,
  2. Zainstaluj to
  3. Dodaj go do swojej aplikacji:

    var app = angular.module('my_app', [ ... , 'httpPostFix']);
Renaud
źródło
6

Nie mam reputacji do komentowania, ale w odpowiedzi / uzupełnieniu odpowiedzi Dona F:

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

trueDo json_decodefunkcji należy dodać drugi parametr , aby poprawnie zwrócić tablicę asocjacyjną:

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

Esten
źródło
6

Kątowy

  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();
        }
Malcolm Swaine
źródło
5

Ten kod rozwiązał dla mnie problem. Jest to rozwiązanie na poziomie aplikacji:

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";
  }
]);
Spartak Lalaj
źródło
5

Dodaj to do pliku js:

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

i dodaj to do pliku serwera:

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

To powinno działać.

Jesus Erwin Suarez
źródło
4

Miałem również podobny problem i robiłem coś takiego, a to nie działało. Mój kontroler Spring nie mógł odczytać parametru danych.

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

Ale czytając to forum i dokumentację API, próbowałem postępować w ten sposób i to działało dla mnie. Jeśli ktoś ma podobny problem, możesz spróbować również poniżej.

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

Sprawdź https://docs.angularjs.org/api/ng/service/ $ http # post, aby dowiedzieć się, co robi konfiguracja parametrów. {data: '"id": "1"'} - Mapa ciągów znaków lub obiektów, które zostaną zamienione na URL? data = "id: 1"

Viraj
źródło
4

jest to prawdopodobnie późna odpowiedź, ale myślę, że najbardziej właściwym sposobem jest użycie tego samego fragmentu kodu pod kątem podczas wykonywania żądania „get” za pomocą, $httpParamSerializerbędziesz musiał wstrzyknąć go do kontrolera, abyś mógł wykonać następujące czynności bez konieczności w ogóle używaj Jquery, $http.post(url,$httpParamSerializer({param:val}))

app.controller('ctrl',function($scope,$http,$httpParamSerializer){
    $http.post(url,$httpParamSerializer({param:val,secondParam:secondVal}));
}
oneLeggedChicken
źródło
4

W moim przypadku rozwiązuję problem w następujący sposób:

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;

Musisz użyć JSON.stringify dla każdego parametru zawierającego obiekt JSON, a następnie zbuduj obiekt danych za pomocą „$ .param” :-)

NB: Mój obiekt „objJSON” jest obiektem JSON zawierającym tablicę, liczbę całkowitą, ciąg znaków i treść HTML. Jego całkowity rozmiar to> 3500 znaków.

bArraxas
źródło
3

Wiem, że zaakceptował odpowiedź. Ale śledzenie może pomóc przyszłym czytelnikom, jeśli odpowiedź z jakiegoś powodu nie pasuje.

Angular nie robi ajax tak samo jak jQuery. Podczas gdy starałem się postępować zgodnie z instrukcjami, aby zmodyfikować kąt $httpprovider, napotkałem inne problemy. Np. Używam kodu, w którym $this->input->is_ajax_request()funkcja zawsze zawodziła (która została napisana przez innego programistę i używana globalnie, więc nie mogę zmienić) mówiąc, że to nie jest prawdziwe zapytanie ajax.

Aby to rozwiązać, skorzystałem z odroczonej obietnicy . Przetestowałem to w przeglądarce Firefox i ie9 i działało.

Mam następującą funkcję zdefiniowaną poza dowolnym kodem kątowym. Ta funkcja wykonuje regularne wywołanie ajax jquery i zwraca obiekt odroczony / obiecany (wciąż się uczę).

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

Następnie nazywam go kodem kątowym za pomocą następującego kodu. Pamiętaj, że musimy $scoperęcznie zaktualizować za pomocą $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!");
    });

To może nie być idealna odpowiedź, ale pozwoliło mi to na użycie wywołań jquery ajax z angular i pozwoliło mi zaktualizować $scope.

Nis
źródło
2
Angular ma własną usługę obietnic o nazwie $ q od 1.3. Nie trzeba używać JQuery dla postu.
mbokil
3

Miałem ten sam problem w trybie ekspresowym .. aby rozwiązać, musisz użyć bodyparsera do parsowania obiektów json przed wysłaniem żądań HTTP ..

app.use(bodyParser.json());
Muhammad Soliman
źródło
3

Korzystam z usługi web.net WCF asp.net z kątowym js i działał poniższy kod:

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

Mam nadzieję, że to pomoże.

Mehdi Rostami
źródło
3

Nie znalazłem pełnego fragmentu kodu dotyczącego sposobu użycia metody $ http.post do wysyłania danych do serwera i dlaczego nie działa w tym przypadku.

Objaśnienia do poniższego fragmentu kodu ...

  1. Korzystam z funkcji jQuery $ .param do serializacji danych JSON do danych www post
  2. Ustawienie Content-Type w zmiennej config, która zostanie przekazana wraz z żądaniem angularJS $ http.post, które instruuje serwer, że wysyłamy dane w formacie www post.

  3. Zwróć uwagę na metodę $ htttp.post, w której wysyłam pierwszy parametr jako adres URL, drugi parametr jako dane (serializowane) i trzeci parametr jako config.

Pozostały kod jest zrozumiały.

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

Spójrz na przykładowy kod metody $ http.post tutaj .

Sheo Narayan
źródło
3

Jeśli używasz PHP, jest to łatwy sposób na dostęp do tablicy w PHP z AngularJS POST.

$params = json_decode(file_get_contents('php://input'),true);
Luis Felipe Barnett V.
źródło
Ten artykuł może pomóc ludziom.
Stphane,
3

Jeśli używasz Angular> = 1.4 , oto najczystsze rozwiązanie z wykorzystaniem serializatora dostarczonego przez 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';
});

Następnie możesz to zrobić w dowolnym miejscu w aplikacji:

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

I poprawnie serializuje dane jako param1=value1&param2=value2i wysyła je /requesturlz application/x-www-form-urlencoded; charset=utf-8nagłówkiem Content-Type, jak zwykle oczekuje się w przypadku żądań POST w punktach końcowych.

TL; DR

Podczas moich badań odkryłem, że odpowiedź na ten problem ma wiele różnych smaków; niektóre są bardzo skomplikowane i zależą od funkcji niestandardowych, niektóre zależą od jQuery, a niektóre są niepełne w sugerowaniu, że wystarczy ustawić nagłówek.

Jeśli właśnie ustawisz Content-Typenagłówek, punkt końcowy zobaczy dane POST, ale nie będzie w standardowym formacie, ponieważ jeśli nie podasz ciągu jako obiektu datalub ręcznie nie serializujesz obiektu danych, wszystko to zostanie serializowane jako JSON przez domyślna i może być niepoprawnie interpretowana w punkcie końcowym.

np. jeśli w powyższym przykładzie nie ustawiono poprawnego serializatora, będzie on widoczny w punkcie końcowym jako:

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

A to może prowadzić do nieoczekiwanego analizowania, np. ASP.NET traktuje go jako nullnazwę parametru o {"param1":"value1","param2":"value2"}wartości; lub Fiddler interpretuje to w drugą stronę, z {"param1":"value1","param2":"value2"}nazwą parametru i nullwartością.

Saeb Amini
źródło
3

Podobnie do sugerowanego formatu roboczego OP i odpowiedzi Denisona, z wyjątkiem użycia $http.postzamiast tylko $httpi nadal zależy od jQuery.

Zaletą korzystania z jQuery jest to, że złożone obiekty są poprawnie przekazywane; przed ręcznym przekształceniem w parametry URL, które mogą zakłócić dane.

$http.post( 'request-url', jQuery.param( { 'message': message } ), {
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});
Benjamin Intal
źródło
2

Kiedy miałem ten problem, parametr, który publikowałem, okazał się tablicą obiektów zamiast prostego obiektu.

D. Kermott
źródło
2

Właśnie zaktualizowano z kątowego 1.2 do 1.3, znaleziono problem w kodzie. Przekształcenie zasobu doprowadzi do nieskończonej pętli, ponieważ (myślę) o obietnicy $ zawierającej ponownie ten sam obiekt. Może to pomoże komuś ...

Mógłbym to naprawić przez:

[...]
  /**
 * 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) {
[...]
tom_w
źródło
2

Od jakiegoś czasu korzystam z przyjętego kodu odpowiedzi (kodu Felipe) i działa on świetnie (dzięki, Felipe!).

Jednak niedawno odkryłem, że ma problemy z pustymi obiektami lub tablicami. Na przykład podczas przesyłania tego obiektu:

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

PHP wydaje się wcale nie widzieć B i C. Otrzymuje to:

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

Spojrzenie na rzeczywiste żądanie w Chrome pokazuje:

A: 1
:
D: 2

Napisałem alternatywny fragment kodu. Wygląda na to, że działa dobrze z moimi przypadkami użycia, ale nie przetestowałem go dokładnie, więc używaj go ostrożnie.

Użyłem TypeScript, ponieważ lubię mocne pisanie, ale łatwo byłoby przekonwertować na czysty 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("&");
    } ];
} ]);

Jest mniej wydajny niż kod Felipe, ale nie sądzę, żeby miało to duże znaczenie, ponieważ powinno być natychmiastowe w porównaniu do ogólnego obciążenia samego żądania HTTP.

Teraz PHP pokazuje:

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

O ile mi wiadomo, PHP nie może rozpoznać, że Ba i C są pustymi tablicami, ale przynajmniej pojawiają się klucze, co jest ważne, gdy istnieje kod, który opiera się na pewnej strukturze, nawet jeśli jest ona zasadniczo pusta.

Zauważ też, że konwertuje niezdefiniowane si null na puste ciągi.

posłuszny
źródło
TypeScript to najlepszy sposób na kodowanie w POO za pomocą JavaScript!
Zniekształć
2

Po prostu umieść dane, które chcesz wysłać, jako drugi parametr:

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

Inną formą, która również działa, jest:

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

Upewnij się, że paramNamedokładnie odpowiada nazwie parametru wywoływanej funkcji.

Źródło: Metoda skrótu postowego AngularJS

Marco Lackovic
źródło
5
Czy ktoś może wyjaśnić, dlaczego odrzucono tę odpowiedź?
Marco Lackovic,
1
Nie ma mowy, aby to rozwiązanie zostało odrzucone, jest to najprostsze, najkrótsze i sprawdzone w dokumentacji kątowej docs.quarejs.org/api/ng/service/$http
ainasiart
1

Rozwiązałem to przez poniższe kody:

Po stronie klienta (Js):

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

zauważ, że dane są przedmiotem.

Na serwerze (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;
        }

i „AllowCrossSiteJsonAttribute” jest wymagany w przypadku żądań między domenami:

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

Mam nadzieję, że to się przydało.

pixparker
źródło