Angular2 - Http POST request parameters
Asked Answered
C

9

96

I'm trying to make a POST request but i can't get it working:

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

I basically want to replicate this http request (not ajax) like it was originated by a html form:

URL: /api

Params: username and password

Clinker answered 4/2, 2016 at 21:52 Comment(3)
have a look at this https://mcmap.net/q/94074/-using-http-rest-apis-with-angular-2 and https://mcmap.net/q/219254/-how-to-use-import-http-module this will explain all about POST request in deep !Ungracious
@PardeepJain i'm not trying to consume an API. Just to simulate a POST originated by a html form.Clinker
also check here, post a file with user_name and password, https://mcmap.net/q/219255/-update-a-formcontrol-that-is-a-file-input-in-a-formarray-in-angular2Remittee
S
51

I think that the body isn't correct for an application/x-www-form-urlencoded content type. You could try to use this:

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

Hope it helps you, Thierry

Syndicate answered 4/2, 2016 at 22:5 Comment(4)
yes with that content type in the header, it is the only solution passing values in "the old way" instead of json stringSinistrous
This is not a good answer. Use URLSearchParams instead, like mentioned below with more upvotes.Snaffle
To people from the future coming from a Google search, this is not the best answer (no offense Thierry! your answer is still technically correct :)). V Stoykov's answer is so far the most accurate. p.s. make sure to import { URLSearchParams } from "@angular/http" and not the default one so 1) you don't need to do the .toString on it, and 2) you don't need to set the content type. Angular will infer it automatically for you (see github.com/angular/angular/blob/4.4.4/packages/http/src/…)Heavyfooted
Hi ! if i want to pass post service with header -> content type like 'application/json' what i need to pass in body .... i am trying to pass json object but it;s not working properly ...Nipa
D
114

Update for Angualar 4.3+

Now we can use HttpClient instead of Http

Guide is here

Sample code

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

Deprecated

Or you can do like this:

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

Update Oct/2017

From angular4+, we don't need headers, or .toString() stuffs. Instead, you can do like below example

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

POST/PUT method

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 method

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

For JSON application/json Content-Type

this.http.post('/api',
      JSON.stringify({
        username: username,
        password: password,
      })).subscribe(
      data => {
        alert('ok');
      },
      error => {
        console.log(JSON.stringify(error.json()));
      }
      )
Doughty answered 15/10, 2016 at 7:2 Comment(6)
Don't forget to import the URLSearchParams Class import { URLSearchParams } from "angular2/http"Tessler
my import looks different: import { URLSearchParams } from '@angular/http';Rundown
but, there is not a more simple way to send a form object ? i did not see any tutorial using URLSearchParams() to send post for a backend with restful. how they do ? return this.http.post(this.actionUrl , body, { headers: this.headers }) .map((response: Response) => response.json()) .catch(this.handleError);Dogger
How does this work with booleans? Getting an error saying that I cant add booleans or numbers, just strings (in append)Pint
About boolean, maybe this topic can help you #14775407Doughty
@user623396 not anymore, as V Stoykov said in the answer (currently) below, if you use Angular's URLSearchParams you don't need to 1) do the .toString on it, and 2) set the content type. Angular will infer it automatically for you: github.com/angular/angular/blob/4.4.4/packages/http/src/… and github.com/angular/angular/blob/4.4.4/packages/http/src/… and github.com/angular/angular/blob/4.4.4/packages/http/src/…Heavyfooted
S
51

I think that the body isn't correct for an application/x-www-form-urlencoded content type. You could try to use this:

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

Hope it helps you, Thierry

Syndicate answered 4/2, 2016 at 22:5 Comment(4)
yes with that content type in the header, it is the only solution passing values in "the old way" instead of json stringSinistrous
This is not a good answer. Use URLSearchParams instead, like mentioned below with more upvotes.Snaffle
To people from the future coming from a Google search, this is not the best answer (no offense Thierry! your answer is still technically correct :)). V Stoykov's answer is so far the most accurate. p.s. make sure to import { URLSearchParams } from "@angular/http" and not the default one so 1) you don't need to do the .toString on it, and 2) you don't need to set the content type. Angular will infer it automatically for you (see github.com/angular/angular/blob/4.4.4/packages/http/src/…)Heavyfooted
Hi ! if i want to pass post service with header -> content type like 'application/json' what i need to pass in body .... i am trying to pass json object but it;s not working properly ...Nipa
R
42

In later versions of Angular2 there is no need of manually setting Content-Type header and encoding the body if you pass an object of the right type as body.

You simply can do this

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

This way angular will encode the body for you and will set the correct Content-Type header.

P.S. Do not forget to import URLSearchParams from @angular/http or it will not work.

Repudiation answered 29/12, 2016 at 14:6 Comment(13)
Do you know in which version this has been added?Cinema
I don't know in which version it is added but in 2.3.1 and later version it works.Repudiation
@Repudiation it doesn't work, you have to .toString() on the params and you have to specify the content type, and I use angular 4.0.3Derogatory
@i'myourhuckleberry It should work even on 4.0.3. Look at the source code github.com/angular/angular/blob/4.0.3/packages/http/src/…Repudiation
@Repudiation it doesn't work for me and I have reported it as a bug on GithubDerogatory
OK. Nvm I had to import this from "@angular/http" otherwise it recognizes the type but it's not angular's type.Derogatory
@i'myourhuckleberry the import was the first line in my example, but probably you missed it. From the built in types in the browser you can use FormData, and angular will set Content-Type as multipart/form-data which also work.Repudiation
This doesn't work, only appending params to the url worksLousy
@Daria if you are appending params to the URL this is different then sending POST request with payload in the body. Appended URL params are called "query string".Repudiation
@i'myourhuckleberry I saw your comment, and still missed it :) and thought I'm going crazy. to everyone reading this: do the import { URLSearchParams } from "@angular/http" otherwise it will import the default one from lib.es6.d.ts! (which will require you to mention the content type manually and do the .toString())Heavyfooted
@EranMedan that's the reason i switched to react/vue, bloody mess in angular, if you use vue/react you can actually choose yourself what http library suits best for you. I don't like observables, I can choose a library that uses futures instead. Funny fact: angular developers probably struggle theirselves wth they made :) Personally vue looks really easy! react is a little mess with state management but i got it solved with Resub from microsoft (i'm not a fanboy of microsoft, it annoys me that they advertise azure in their all tutorials!)Derogatory
I used angular for 1 project though, it worked but it's a framework, I remember always having some issues with simple things, and most often some part of library didn't work, when I reported that issue on github I got completely ignored. It would be better if it was more simple! I kinda liked these special attributes like ngFor but too many complications with imports. When you use react or vue you have to install things like routing, internationalization separately.Derogatory
NIce I forgot to import the URLSearchParams now its all working thanksLietuva
R
11

so just to make it a complete answer:

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;
                }
            });
    }
Rundown answered 15/11, 2016 at 15:31 Comment(2)
[ts] Argument of type '{ headers: RequestOptions; }' is not assignable to parameter of type 'RequestOptionsArgs'Vivid
@Sonic Soul it's just: .. post('/api', body, headers) ... without { } around headersBlackbird
J
7

These answers are all outdated for those utilizing the HttpClient rather than Http. I was starting to go crazy thinking, "I have done the import of URLSearchParams but it still doesn't work without .toString() and the explicit header!"

With HttpClient, use HttpParams instead of URLSearchParams and note the body = body.append() syntax to achieve multiple params in the body since we are working with an immutable object:

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();
  }
Jolley answered 9/11, 2017 at 19:21 Comment(1)
thanks for the above solution. But when running ng build --prod my body param's are looking like "{"params":{"rawParams":"","queryEncoder":{},"paramsMap":{}}}:". Is there any work around.Dark
S
5

If anyone is struggling with angular version 4+ (mine was 4.3.6). This was the sample code which worked for me.

First add the required imports

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

Then for the api function. It's a login sample which can be changed as per your needs.

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));
            }
        });
}
Stockbreeder answered 3/9, 2017 at 15:19 Comment(0)
A
3
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)
Austro answered 28/11, 2019 at 11:28 Comment(2)
Hi and welcome to Stackoverflow. Thank you for answering this question, but just posting a block of code is hard to understand for the OP or anyone coming across this question in the future. Would you be able to edit your question and give a (short) explanation as to what the problem was you solved, and how you solved it, to help us understand your solution better?Checkerbloom
Hi @Checkerbloom when i passed the value on 2nd parameter of post request it returning me the null values on api so i passed that 2nd parameter as empty string and I passed the values on params property of 3rd parameter so this method worked for meAustro
V
1

I was having problems with every approach using multiple parameters, but it works quite well with single object

api:

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

angular:

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
    });
}
Vivid answered 2/3, 2017 at 16:18 Comment(1)
The problem of OP is the content-type of application/x-www-form-urlencoded, your answer is a totally different problem.Latea
H
-2

I landed here when I was trying to do a similar thing. For a application/x-www-form-urlencoded content type, you could try to use this for the body:

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

with what you tried doing the value assigned to body will be a string.

Haiduk answered 4/7, 2016 at 17:44 Comment(1)
As Joshua pointed out, this is not valid JavaScript nor TypeScript. I think what you meant is exactly the currently accepted answer.Latea

© 2022 - 2024 — McMap. All rights reserved.