18

I'm trying to do an API call from my angular app. What I want to do is send a post request to the API with a command param. I have done a lot of server-side testing as well as going through the outgoing request, and the $_POST nor body data is never there. I am therefore pretty sure that the problem lays within this piece of code.

public post(cmd: string, data: object): Observable<any> {
    const params = new URLSearchParams();
    params.set('cmd', cmd);
    
    const options = new RequestOptions({
      headers: this.getAuthorizedHeaders(),
      responseType: ResponseContentType.Json,
      params: params,
      body: data,
      withCredentials: false
    });
    
    console.log('Options: ' + JSON.stringify(options));
    
    return this.http.post('http://t2w.dev/index.php', data, options)
      .map(this.handleData)
      .catch(this.handleError);
}

I have tried many different JSON structures as data but this is the core of what I am trying to send:

{
    "Username": "No thanks",
    "Password": "Donno"
}

this.handleData and this.handleError is a method taking data and error as arguments, and returns just what I want.

The API is setup to log anything coming through $_POST which works fine when running requests from anywhere but my angular app. What I have done so far:

  1. Passing raw query instead of URLSearchParams.
  2. Passing the request without body.
  3. Passing all values in RequestOptions.
  4. Passing params as a string.
  5. Passing body as params.
  6. Passing body as JSON.stringify({ "Username": "No thanks", "Password": "Donno" }

Console output of RequestOptions

Options: {"method":null,"headers":{"Content-Type":["application/json"],"Accept":["application/json"],"X-CLIENT-ID":["380954038"],"X-CLIENT-SECRET":["5BgqRO9BMZ4iocAXYjjnCjnO7fHGN59WP8BTRZ5f"]},"body":"{}","url":null,"params":{"rawParams":"","queryEncoder":{},"paramsMap":{}},"withCredentials":false,"responseType":1} VM8529:1 XHR finished loading: POST "http://t2w.dev/index.php".

Does anyone have any clue why the data never gets sent?

Kh4lid MD
  • 125
  • 1
  • 2
  • 10
SlyOtis
  • 577
  • 1
  • 5
  • 20

5 Answers5

12

The 2nd parameter of http.post is the body of the message, ie the payload and not the url search parameters. Pass data in that parameter.

From the documentation

post(url: string, body: any, options?: RequestOptionsArgs) : Observable<Response
    public post(cmd: string, data: object): Observable<any> {

        const params = new URLSearchParams();
        params.set('cmd', cmd);

        const options = new RequestOptions({
          headers: this.getAuthorizedHeaders(),
          responseType: ResponseContentType.Json,
          params: params,
          withCredentials: false
        });

        console.log('Options: ' + JSON.stringify(options));

        return this.http.post(this.BASE_URL, data, options)
          .map(this.handleData)
          .catch(this.handleError);
      }

Edit

You should also check out the 1st parameter (BASE_URL). It must contain the complete url (minus query string) that you want to reach. I mention in due to the name you gave it and I can only guess what the value currently is (maybe just the domain?).

Also there is no need to call JSON.stringify on the data/payload that is sent in the http body.

If you still can't reach your end point look in the browser's network activity in the development console to see what is being sent. You can then further determine if the correct end point is being called wit the correct header and body. If it appears that is correct then use POSTMAN or Fiddler or something similar to see if you can hit your endpoint that way (outside of Angular).

raaaay
  • 496
  • 7
  • 14
Igor
  • 60,821
  • 10
  • 100
  • 175
  • Im aware, and started with that but after reading up on what others have working this is my last attempt. – SlyOtis Jun 15 '17 at 14:11
  • @SlyOtis - I added an edit at the bottom. Note that your map and catch handlers should be fine the way they are (*assuming the input parameter matches the output from the expression*). – Igor Jun 15 '17 at 14:13
  • Updated my question again with the complete url. I reach the endpoint, and a request without post data gets handled the way it's supped to on both ends. I have also gone through the console where i discovered that there is neither data or post data accompanying the request. – SlyOtis Jun 15 '17 at 14:19
  • Hi, thanks for the response but I have another question: and if you wanna pass parameter as string, how you do that? I'm trying pass a GMT param with the format '+0100' but only recognize as '0100'. Thanks again! – Drako Aug 10 '17 at 09:37
  • 1
    @Drako - It would be best if you asked a new question (*and included the details*) instead of asking in the comments of an existing question. – Igor Aug 10 '17 at 13:21
  • Thanks @Igor, I'll do it – Drako Aug 10 '17 at 21:10
9

And it works, thanks @trichetriche. The problem was in my RequestOptions, apparently, you can not pass params or body to the RequestOptions while using the post. Removing one of them gives me an error, removing both and it works. Still no final solution to my problem, but I now have something to work with. Final working code.

public post(cmd: string, data: string): Observable<any> {

    const options = new RequestOptions({
      headers: this.getAuthorizedHeaders(),
      responseType: ResponseContentType.Json,
      withCredentials: false
    });

    console.log('Options: ' + JSON.stringify(options));

    return this.http.post(this.BASE_URL, JSON.stringify({
      cmd: cmd,
      data: data}), options)
      .map(this.handleData)
      .catch(this.handleError);
  }
Sibeesh Venu
  • 18,755
  • 12
  • 103
  • 140
SlyOtis
  • 577
  • 1
  • 5
  • 20
3

Let said our backend looks like this:

public async Task<IActionResult> Post([FromBody] IList<UserRol> roles, string notes) {
}

We have a HttpService like this:

    post<T>(url: string, body: any, headers?: HttpHeaders, params?: HttpParams): Observable<T> {
        return this.http.post<T>(url, body, { headers: headers, params});
    }

Following is how we can pass the body and the notes as parameter: // how to call it

const headers: HttpHeaders = new HttpHeaders({
    'Authorization': `Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXX`
});

const bodyData = this.getBodyData(); // get whatever we want to send as body

let params: HttpParams = new HttpParams();
params = params.set('notes', 'Some notes to send');

this.httpService.post<any>(url, bodyData, headers, params);

It worked for me (using angular 7^), I hope is useful for somebody.

Jhonman681
  • 31
  • 1
-1

Yes the problem is here. It's related to your syntax.

Try using this

return this.http.post(this.BASE_URL, params, options)
  .map(data => this.handleData(data))
  .catch(this.handleError);

instead of

return this.http.post(this.BASE_URL, params, options)
  .map(this.handleData)
  .catch(this.handleError);

Also, the second parameter is supposed to be the body, not the url params.

  • 1
    again doing this `this.handleData` or `data => this.handleData(data)` outputs the same [docs](https://angular.io/guide/http#fetch-data-with-httpget) – SlyOtis Jun 15 '17 at 14:15
  • From personal experience I found out that no, but I will take a look at the doc and try again. Anyway, your second problem is that you don't send the body, but instead your params. And most of all, what does your browser console says ? –  Jun 15 '17 at 14:17
  • Everything works as it should, all my headers are there in both ends, only missing thing is post body and data. – SlyOtis Jun 15 '17 at 14:23
  • Because, as I said, you don't send any body, you send your params. try sending this : `http.post(this.BASE_URL, JSON.stringify({content: 'any'}), options)` –  Jun 15 '17 at 14:25
  • Updated my post to clarify my problem and what i have tried so far. I have tired sending the data both as string and as json. – SlyOtis Jun 15 '17 at 14:28
  • You didn't tried sending a body from what I see. Why don't you just try this ? –  Jun 15 '17 at 14:29
  • I have tried that multiple times, with different data and approaches as mentioned above. – SlyOtis Jun 15 '17 at 14:33
  • You're stubborn, aren't you ? Either you didn't say what you did correctly, or you don't want to try my method. But in no step I see `what I tried : passing data as body` –  Jun 15 '17 at 14:39
  • Sorry, but what you mean is passing body as second parameter here `return this.http.post('http://t2w.dev/index.php', data, options)` right? Because no matter what type or object i pass there the payload stays empthy :/ (and it is really frustrating) ? Thanks for helping btw. – SlyOtis Jun 15 '17 at 14:46
  • Almost, try passing hard data like I told you : `http.post(this.BASE_URL, JSON.stringify({content: 'any'}), options)`. If your call works, and the body is empty, maybe you don't send actual data when you call the method. –  Jun 15 '17 at 14:50
  • I c, but unfortunately i have already tried that :/ Also tried passing it in the `body` of the `RequestOptions`. – SlyOtis Jun 15 '17 at 15:00
  • So to get this straight : doesn't matter what you do, your request is sent to the server, the server has it, but when you look at the body you don't see anything ? Even when sending hard data like this ? –  Jun 15 '17 at 15:03
  • Yes, but i posted an answer now. I do not know if this is a bug or not. – SlyOtis Jun 15 '17 at 15:11
-4

Seems like you use Angular 4.3 version, I also faced with same problem. Use Angular 4.0.1 and post with code by @trichetricheand and it will work. I am also not sure how to solve it on Angular 4.3 :S

Turkel
  • 3
  • 2