Angular2 - Parametri di richiesta POST Http


91

Sto provando a fare una richiesta POST ma non riesco a farlo funzionare:

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

Fondamentalmente voglio replicare questa richiesta http (non ajax) come se fosse stata originata da un modulo html:

URL: / api

Parametri: nome utente e password


dai un'occhiata a questo stackoverflow.com/a/34758630/5043867 e stackoverflow.com/a/34823818/5043867 questo spiegherà tutto sulla richiesta POST in profondità!
Pardeep Jain

@PardeepJain non sto cercando di utilizzare un'API. Giusto per simulare un POST originato da un form html.
Christopher,

controlla anche qui, pubblica un file con user_namee password, stackoverflow.com/a/45879409/2803344
Belter

Risposte:


49

Penso che il corpo non sia corretto per un application/x-www-form-urlencodedtipo di contenuto. Potresti provare a usare questo:

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

Spero che ti aiuti, Thierry


sì con quel tipo di contenuto nell'intestazione, è l'unica soluzione che passa i valori "alla vecchia maniera" invece della stringa json
Nather Webber

Questa non è una buona risposta. Usa invece URLSearchParams, come menzionato di seguito con più voti positivi.
Mick

Per le persone del futuro provenienti da una ricerca su Google, questa non è la risposta migliore (senza offesa Thierry! La tua risposta è ancora tecnicamente corretta :)). La risposta di V Stoykov è finora la più precisa. ps assicurati di import { URLSearchParams } from "@angular/http"e non quello predefinito quindi 1) non è necessario eseguire l'operazione .toStringsu di esso e 2) non è necessario impostare il tipo di contenuto. Angular lo dedurrà automaticamente per te (vedi github.com/angular/angular/blob/4.4.4/packages/http/src/… )
Eran Medan

Ciao ! se voglio passare il servizio postale con intestazione -> tipo di contenuto come 'application / json' cosa
devo

107

Aggiornamento per Angualar 4.3+

Ora possiamo usare al HttpClientposto diHttp

La guida è qui

Codice di esempio

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

Deprecato

Oppure puoi fare così:

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

Aggiornamento ottobre 2017

Da angular4 + , non abbiamo bisogno headerso cose .toString(). Invece, puoi fare come sotto l'esempio

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

Metodo POST / PUT

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

Metodo GET / DELETE

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

Per JSON application/jsonContent-Type

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

14
Non dimenticare di importare la classe URLSearchParamsimport { URLSearchParams } from "angular2/http"
Sebastian Hernandez

10
la mia importazione ha un aspetto diverso: import {URLSearchParams} da "@ angular / http";
Dang

ma non esiste un modo più semplice per inviare un oggetto form? non ho visto alcun tutorial utilizzando URLSearchParams () per inviare post per un backend con restful. come fanno? restituisci this.http.post (this.actionUrl, body, {headers: this.headers}) .map ((response: Response) => response.json ()) .catch (this.handleError);
stackdave

Come funziona con i booleani? Ottenere un errore che dice che non posso aggiungere valori booleani o numeri, solo stringhe (in append)
JohnAndrews,

A proposito di booleano, forse questo argomento può aiutarti a stackoverflow.com/questions/14774907/…
Frank Nguyen

41

Nelle versioni successive di Angular2 non è necessario impostare manualmente l' Content-Typeintestazione e codificare il corpo se si passa un oggetto del tipo corretto come body.

Puoi farlo semplicemente

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

In questo modo angolare codificherà il corpo per te e imposterà l' Content-Typeintestazione corretta .

PS Non dimenticare di importare URLSearchParamsda @angular/httpo non funzionerà.


2
@VStoykov non funziona, devi .toString () sui parametri e devi specificare il tipo di contenuto, e io uso angolare 4.0.3
Konrad

1
@ i'myourhuckleberry Dovrebbe funzionare anche su 4.0.3. Guarda il codice sorgente github.com/angular/angular/blob/4.0.3/packages/http/src/…
VStoykov

1
@VStoykov non funziona per me e l'ho segnalato come un bug su Github
Konrad

1
OK. Nvm ho dovuto importarlo da "@ angular / http" altrimenti riconosce il tipo ma non è il tipo di angolare.
Konrad

1
@ i'myourhuckleberry l'importazione era la prima riga del mio esempio, ma probabilmente l'hai persa. Dai tipi incorporati nel browser che puoi utilizzare FormDatae angolare verrà impostato Content-Typecome multipart/form-datafunziona.
VStoykov

10

quindi solo per renderlo una risposta completa:

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

1
[ts] Argomento di tipo "{headers: RequestOptions; } "non è assegnabile al parametro di tipo" RequestOptionsArgs "
Sonic Soul

2
@Sonic Soul è solo: .. post ('/ api', body, headers) ... senza {} intorno alle intestazioni
Guenther

5

Queste risposte sono tutte obsolete per coloro che utilizzano HttpClient anziché Http. Stavo iniziando a impazzire pensando, "Ho fatto l'importazione di URLSearchParams ma ancora non funziona senza .toString () e l'intestazione esplicita!"

Con HttpClient, usa HttpParams invece di URLSearchParams e nota la body = body.append()sintassi per ottenere più parametri nel corpo poiché stiamo lavorando con un oggetto immutabile:

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

grazie per la soluzione di cui sopra. Ma quando eseguo ng build --prod i parametri del mio corpo sembrano "{" params ": {" rawParams ":" "," queryEncoder ": {}," paramsMap ": {}}}:". C'è qualche soluzione.
Hemanth Poluru

4

Se qualcuno sta lottando con la versione angolare 4+ (la mia era 4.3.6) . Questo era il codice di esempio che ha funzionato per me.

Per prima cosa aggiungi le importazioni richieste

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

Quindi per la funzione api. È un esempio di accesso che può essere modificato in base alle proprie esigenze.

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

0

Avevo problemi con ogni approccio che utilizzava più parametri, ma funziona abbastanza bene con un singolo oggetto

api:

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

angolare:

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

1
Il problema di OP è il tipo di contenuto dell'applicazione / x-www-form-urlencoded, la tua risposta è un problema completamente diverso.
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)

Ciao e benvenuto in Stackoverflow. Grazie per aver risposto a questa domanda, ma pubblicare solo un blocco di codice è difficile da capire per l'OP o per chiunque si imbatta in questa domanda in futuro. Saresti in grado di modificare la tua domanda e dare una (breve) spiegazione su quale problema è stato risolto e su come lo hai risolto, per aiutarci a capire meglio la tua soluzione?
Plutiano

1
Ciao @Plutian, quando ho passato il valore sul secondo parametro della richiesta del post, mi ha restituito i valori nulli su api, quindi ho passato il secondo parametro come stringa vuota e ho passato i valori sulla proprietà params del terzo parametro, quindi questo metodo ha funzionato per me
Muniyan

-2

Sono atterrato qui mentre stavo cercando di fare una cosa simile. Per un tipo di contenuto application / x-www-form-urlencoded, potresti provare a usarlo per il corpo:

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

con quello che hai provato a fare il valore assegnato al corpo sarà una stringa.


Come ha sottolineato Joshua, questo non è JavaScript né TypeScript valido. Penso che quello che volevi dire sia esattamente la risposta attualmente accettata.
Christian Ulbrich
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.