Angular2 - HTTP-POST-Anforderungsparameter

90

Ich versuche eine POST-Anfrage zu stellen, aber ich kann sie nicht zum Laufen bringen:

testRequest() {
      var body = 'username=myusername?password=mypassword';
      var headers = new Headers();
      headers.append('Content-Type', 'application/x-www-form-urlencoded');

      this.http
        .post('/api',
          body, {
            headers: headers
          })
          .subscribe(data => {
                alert('ok');
          }, error => {
              console.log(JSON.stringify(error.json()));
          });
}

Grundsätzlich möchte ich diese http-Anfrage (nicht Ajax) so replizieren, als ob sie von einem HTML-Formular stammt:

URL: / api

Parameter: Benutzername und Passwort

Christopher
quelle
Schauen Sie sich diese stackoverflow.com/a/34758630/5043867 und stackoverflow.com/a/34823818/5043867 an , um alles über POST-Anfragen ausführlich zu erklären!
Pardeep Jain
@PardeepJain Ich versuche nicht, eine API zu konsumieren. Nur um einen POST zu simulieren, der von einem HTML-Formular stammt.
Christopher
Überprüfen Sie auch hier, posten Sie eine Datei mit user_nameund password, stackoverflow.com/a/45879409/2803344
Belter

Antworten:

49

Ich denke, dass der Körper für einen application/x-www-form-urlencodedInhaltstyp nicht korrekt ist . Sie könnten versuchen, dies zu verwenden:

var body = 'username=myusername&password=mypassword';

Hoffe es hilft dir, Thierry

Thierry Templier
quelle
Ja, mit diesem Inhaltstyp im Header ist dies die einzige Lösung, die Werte auf "alte Weise" anstelle von JSON-Zeichenfolgen übergibt
Nather Webber,
Dies ist keine gute Antwort. Verwenden Sie stattdessen URLSearchParams, wie unten erwähnt, mit mehr Upvotes.
Mick
Für Leute aus der Zukunft, die von einer Google-Suche kommen, ist dies nicht die beste Antwort (keine Beleidigung, Thierry! Ihre Antwort ist immer noch technisch korrekt :)). Die Antwort von V Stoykov ist bislang die genaueste. ps stellen Sie sicher, dass dies import { URLSearchParams } from "@angular/http"nicht der Standard ist, und 1) Sie müssen dies nicht tun .toString, und 2) Sie müssen den Inhaltstyp nicht festlegen. Angular wird es automatisch für Sie ableiten (siehe github.com/angular/angular/blob/4.4.4/packages/http/src/… )
Eran Medan
Hallo ! wenn ich will mit Kopf Post - Service zu übergeben -> Inhaltstyp wie ‚application / json‘ , was ich brauche in Körper zu passieren .... Ich versuche , json Objekt zu übergeben , aber es; s nicht richtig funktioniert ...
VjyV
106

Update für Angualar 4.3+

Jetzt können wir HttpClientstatt verwendenHttp

Führer ist hier

Beispielcode

const myheader = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded')
let body = new HttpParams();
body = body.set('username', USERNAME);
body = body.set('password', PASSWORD);
http
  .post('/api', body, {
    headers: myheader),
  })
  .subscribe();

Veraltet

Oder Sie können so tun:

let urlSearchParams = new URLSearchParams();
urlSearchParams.append('username', username);
urlSearchParams.append('password', password);
let body = urlSearchParams.toString()

Update Okt / 2017

Von angular4 + , brauchen wir nicht headers, oder .toString()stopft. Stattdessen können Sie wie im folgenden Beispiel vorgehen

import { URLSearchParams } from '@angular/http';

POST / PUT-Methode

let urlSearchParams = new URLSearchParams();
urlSearchParams.append('username', username);
urlSearchParams.append('password', password);
this.http.post('/api', urlSearchParams).subscribe(
      data => {
        alert('ok');
      },
      error => {
        console.log(JSON.stringify(error.json()));
      }
    )

GET / DELETE-Methode

    let urlSearchParams = new URLSearchParams();
    urlSearchParams.append('username', username);
    urlSearchParams.append('password', password);
    this.http.get('/api', { search: urlSearchParams }).subscribe(
      data => {
        alert('ok');
      },
      error => {
        console.log(JSON.stringify(error.json()));
      }
    )

Für JSON- application/jsonInhaltstyp

this.http.post('/api',
      JSON.stringify({
        username: username,
        password: password,
      })).subscribe(
      data => {
        alert('ok');
      },
      error => {
        console.log(JSON.stringify(error.json()));
      }
      )
Frank Nguyen
quelle
14
Vergessen Sie nicht, die URLSearchParams-Klasseimport { URLSearchParams } from "angular2/http"
Sebastian Hernandez
10
Mein Import sieht anders aus: {URLSearchParams} aus '@ angle / http' importieren;
Dang
Aber gibt es keine einfachere Möglichkeit, ein Formularobjekt zu senden? Ich habe kein Tutorial mit URLSearchParams () gesehen, um einen Beitrag für ein Backend mit Restful zu senden. wie machen sie das return this.http.post (this.actionUrl, body, {headers: this.headers}) .map ((response: Response) => response.json ()) .catch (this.handleError);
Stackdave
Wie funktioniert das mit Booleschen? Immer eine Fehlermeldung, dass ich keine Booleschen Werte oder Zahlen hinzufügen kann, nur Zeichenfolgen (im Anhang)
JohnAndrews
Über boolean, vielleicht kann dieses Thema Ihnen helfen stackoverflow.com/questions/14774907/…
Frank Nguyen
41

In späteren Versionen von Angular2 ist es nicht erforderlich, den Content-TypeHeader manuell festzulegen und den Body zu codieren, wenn Sie ein Objekt des richtigen Typs als übergeben body.

Sie können dies einfach tun

import { URLSearchParams } from "@angular/http"


testRequest() {
  let data = new URLSearchParams();
  data.append('username', username);
  data.append('password', password);

  this.http
    .post('/api', data)
      .subscribe(data => {
            alert('ok');
      }, error => {
          console.log(error.json());
      });
}

Auf diese Weise codiert eckig den Körper für Sie und setzt den richtigen Content-TypeHeader.

PS Vergessen Sie nicht importieren URLSearchParamsaus @angular/httpoder es wird nicht funktionieren.

VStoykov
quelle
2
@VStoykov es funktioniert nicht, Sie müssen .toString () auf den Parametern und Sie müssen den Inhaltstyp angeben, und ich verwende Winkel 4.0.3
Konrad
1
@ i'myourhuckleberry Es sollte sogar auf 4.0.3 funktionieren. Schauen Sie sich den Quellcode github.com/angular/angular/blob/4.0.3/packages/http/src/…
VStoykov
1
@VStoykov es funktioniert nicht für mich und ich habe es als Fehler auf Github gemeldet
Konrad
1
OK. Nvm Ich musste dies aus "@ angle / http" importieren, sonst erkennt es den Typ, aber es ist nicht der Typ von angle.
Konrad
1
@ i'myourhuckleberry der Import war die erste Zeile in meinem Beispiel, aber wahrscheinlich haben Sie es verpasst. Aus den im Browser integrierten Typen können Sie verwenden FormData, und der Winkel wird so eingestellt Content-Type, multipart/form-datadass er auch funktioniert.
VStoykov
10

Nur um eine vollständige Antwort zu erhalten:

login(username, password) {
        var headers = new Headers();
        headers.append('Content-Type', 'application/x-www-form-urlencoded');
        let urlSearchParams = new URLSearchParams();
        urlSearchParams.append('username', username);
        urlSearchParams.append('password', password);
        let body = urlSearchParams.toString()
        return this.http.post('http://localHost:3000/users/login', body, {headers:headers})
            .map((response: Response) => {
                // login successful if there's a jwt token in the response
                console.log(response);
                var body = response.json();
                console.log(body);
                if (body.response){
                    let user = response.json();
                    if (user && user.token) {
                        // store user details and jwt token in local storage to keep user logged in between page refreshes
                        localStorage.setItem('currentUser', JSON.stringify(user)); 
                    }
                }
                else{
                    return body;
                }
            });
    }
Mist
quelle
1
[ts] Argument vom Typ '{headers: RequestOptions; } 'kann nicht dem Parameter vom Typ' RequestOptionsArgs 'zugewiesen werden
Sonic Soul
2
@Sonic Soul es ist nur: .. post ('/ api', body, headers) ... ohne {} um headers
Günther
5

Diese Antworten sind alle veraltet, wenn Sie den HttpClient anstelle von Http verwenden. Ich fing an verrückt zu werden und dachte: "Ich habe den Import von URLSearchParams durchgeführt, aber es funktioniert immer noch nicht ohne .toString () und den expliziten Header!"

Verwenden Sie mit HttpClient HttpParams anstelle von URLSearchParams und beachten Sie die body = body.append()Syntax, um mehrere Parameter im Body zu erreichen, da wir mit einem unveränderlichen Objekt arbeiten:

login(userName: string, password: string): Promise<boolean> {
    if (!userName || !password) {
      return Promise.resolve(false);
    }

    let body: HttpParams = new HttpParams();
    body = body.append('grant_type', 'password');
    body = body.append('username', userName);
    body = body.append('password', password);

    return this.http.post(this.url, body)
      .map(res => {
        if (res) {          
          return true;
        }
        return false;
      })
      .toPromise();
  }
333Matt
quelle
Danke für die obige Lösung. Aber wenn ng build --prod ausgeführt wird, sehen meine Körperparameter wie folgt aus: "{" params ": {" rawParams ":" "," queryEncoder ": {}," paramsMap ": {}}}:". Gibt es irgendwelche Probleme?
Hemanth Poluru
4

Wenn jemand mit der eckigen Version 4+ zu kämpfen hat (meine war 4.3.6) . Dies war der Beispielcode, der für mich funktioniert hat.

Fügen Sie zuerst die erforderlichen Importe hinzu

import { Http, Headers, Response, URLSearchParams } from '@angular/http';

Dann für die API-Funktion. Es ist ein Anmeldebeispiel, das je nach Bedarf geändert werden kann.

login(username: string, password: string) {
    var headers = new Headers();
    headers.append('Content-Type', 'application/x-www-form-urlencoded');
    let urlSearchParams = new URLSearchParams();
    urlSearchParams.append('email', username);
    urlSearchParams.append('password', password);
    let body = urlSearchParams.toString()

    return this.http.post('http://localhost:3000/api/v1/login', body, {headers: headers})
        .map((response: Response) => {
            // login successful if user.status = success in the response
            let user = response.json();
            console.log(user.status)
            if (user && "success" == user.status) {
                // store user details and jwt token in local storage to keep user logged in between page refreshes
                localStorage.setItem('currentUser', JSON.stringify(user.data));
            }
        });
}
Krishnadas PC
quelle
0

Ich hatte Probleme bei jedem Ansatz mit mehreren Parametern, aber es funktioniert ziemlich gut mit einem einzelnen Objekt

api:

    [HttpPut]
    [Route("addfeeratevalue")]
    public object AddFeeRateValue(MyValeObject val)

eckig:

var o = {ID:rateId, AMOUNT_TO: amountTo, VALUE: value};
return this.http.put('/api/ctrl/mymethod', JSON.stringify(o), this.getPutHeaders());


private getPutHeaders(){
    let headers = new Headers();
    headers.append('Content-Type', 'application/json');
    return new RequestOptions({
        headers: headers
        , withCredentials: true // optional when using windows auth
    });
}
Sonic Soul
quelle
1
Das Problem von OP ist der Inhaltstyp der Anwendung / x-www-form-urlencoded. Ihre Antwort ist ein völlig anderes Problem.
Christian Ulbrich
0
angular: 
    MethodName(stringValue: any): Observable<any> {
    let params = new HttpParams();
    params = params.append('categoryName', stringValue);

    return this.http.post('yoururl', '', {
      headers: new HttpHeaders({
        'Content-Type': 'application/json'
      }),
      params: params,
      responseType: "json"
    })
  }

api:   
  [HttpPost("[action]")]
  public object Method(string categoryName)
Muniyan
quelle
Hallo und willkommen bei Stackoverflow. Vielen Dank, dass Sie diese Frage beantwortet haben, aber es ist für das OP oder jeden, der in Zukunft auf diese Frage stößt, schwer zu verstehen, nur einen Codeblock zu veröffentlichen. Könnten Sie Ihre Frage bearbeiten und eine (kurze) Erklärung dazu geben, welches Problem Sie gelöst haben und wie Sie es gelöst haben, damit wir Ihre Lösung besser verstehen können?
Plutian
1
Hallo @Plutian, als ich den Wert für den 2. Parameter der Post-Anfrage übergeben habe, habe ich die Nullwerte für die API zurückgegeben, also habe ich den 2. Parameter als leere Zeichenfolge übergeben und die Werte für die Eigenschaft params des 3. Parameters übergeben, sodass diese Methode für mich funktioniert hat
Muniyan
-2

Ich bin hier gelandet, als ich versucht habe, etwas Ähnliches zu tun. Für einen Inhaltstyp application / x-www-form-urlencoded können Sie versuchen, diesen für den Body zu verwenden:

var body = 'username' =myusername & 'password'=mypassword;

Bei dem, was Sie versucht haben, wird der dem Körper zugewiesene Wert eine Zeichenfolge sein.

Adongo
quelle
Wie Joshua betonte, ist dies weder gültiges JavaScript noch TypeScript. Ich denke, was Sie meinten, ist genau die aktuell akzeptierte Antwort.
Christian Ulbrich