Angular2 - параметри запиту POST Http


91

Я намагаюся зробити запит POST, але не можу змусити його працювати:

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

Я в основному хочу відтворити цей http-запит (не ajax), як він був створений у формі html:

URL: / api

Параметри: ім'я користувача та пароль


подивіться на stackoverflow.com/a/34758630/5043867 та stackoverflow.com/a/34823818/5043867, це глибоко пояснить все про запит POST!
Пардіп Джейн

@PardeepJain я не намагаюся використовувати API. Просто для імітації POST, що походить від форми html.
Крістофер

Крім того, перевірте тут, опублікувати файл з user_nameі password, stackoverflow.com/a/45879409/2803344
Belter

Відповіді:


49

Я думаю, що основний application/x-www-form-urlencodedвміст неправильний для типу вмісту. Ви можете спробувати використати це:

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

Сподіваюся, це допоможе тобі, Тьєррі


так, з таким типом вмісту в заголовку, це єдине рішення, яке передає значення "по-старому" замість json-рядка
Nather Webber

Це невдала відповідь. Замість цього використовуйте URLSearchParams, як зазначено нижче, з більшою кількістю голосів.
Мік

Для людей з майбутнього, які надходять із пошуку Google, це не найкраща відповідь (без образ Тьєррі! Ваша відповідь досі технічно правильна :)). V Стойков в відповідь до сих пір найбільш точним. ps переконайтесь, import { URLSearchParams } from "@angular/http"а не за замовчуванням, тому 1) вам не потрібно робити .toStringна ньому, і 2) вам не потрібно встановлювати тип вмісту. Angular зробить це для вас автоматично (див. Github.com/angular/angular/blob/4.4.4/packages/http/src/… )
Еран Медан,

Привіт ! якщо я хочу передати поштовий сервіс із заголовком -> тип вмісту, такий як 'application / json', що мені потрібно передати в тілі .... я намагаюся передати json-об'єкт, але він не працює належним чином ...
VjyV

107

Оновлення для Angualar 4.3+

Тепер ми можемо використовувати HttpClientзамістьHttp

Путівник тут

Зразок коду

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

Застаріле

Або ви можете зробити так:

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

Оновлення жовтня / 2017

З angular4 + , ми не потрібні headers, або .toString()харчування. Натомість ви можете зробити, як показано на прикладі нижче

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

Метод 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()));
      }
    )

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

Для типу application/jsonвмісту JSON

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

14
Не забудьте імпортувати клас URLSearchParamsimport { URLSearchParams } from "angular2/http"
Себастьян Ернандес,

10
мій імпорт виглядає інакше: імпортувати {URLSearchParams} з '@ angular / http';
dang

але, немає більш простого способу надіслати об’єкт форми? я не побачив жодного підручника за допомогою URLSearchParams () для надсилання публікації для бекенда з restful. як вони роблять? повернути this.http.post (this.actionUrl, body, {headers: this.headers}) .map ((response: Response) => response.json ()) .catch (this.handleError);
stackdave

Як це працює з логічними значеннями? Повідомлення про помилку про те, що я не можу додати логічні значення або числа, лише рядки (у
додатку

Про булеву, можливо ця тема може допомогти вам stackoverflow.com/questions/14774907/…
Френк Нгуєн

41

У пізніших версіях Angular2 немає необхідності вручну встановлювати Content-Typeзаголовок і кодувати тіло, якщо ви передаєте об'єкт правильного типу як body.

Ви просто можете це зробити

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

Таким чином angular буде кодувати тіло для вас і встановить правильний Content-Typeзаголовок.

PS Не забувайте імпортувати URLSearchParamsз, @angular/httpінакше він не буде працювати.


2
@VStoykov це не працює, вам потрібно .toString () на параметри, і ви повинні вказати тип вмісту, а я використовую angular 4.0.3
Конрад

1
@ i'myourhuckleberry Це має працювати навіть на версії 4.0.3. Подивіться на вихідний код github.com/angular/angular/blob/4.0.3/packages/http/src/…
В.Стойков

1
@VStoykov у мене це не працює, і я повідомив про це як про помилку на Github
Konrad

1
ГАРАЗД. Nvm мені довелося імпортувати це з "@ angular / http", інакше він розпізнає тип, але це не тип angular.
Конрад,

1
@ i'myourhuckleberry, імпорт був першим рядком у моєму прикладі, але, мабуть, ви його пропустили. З вбудованих типів у браузері ви можете використовувати FormData, і angular буде встановлено Content-Typeяк multipart/form-dataякі також працюють.
В.Стойков

10

отже, щоб дати на нього повну відповідь:

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] Аргумент типу '{заголовки: RequestOptions; } 'не можна призначити параметру типу' RequestOptionsArgs '
Sonic Soul

2
@Sonic Soul це просто: .. post ('/ api', body, headers) ... без {} навколо заголовків
Guenther,

5

Усі ці відповіді застарілі для тих, хто використовує HttpClient, а не Http. Я починав божеволіти, думаючи: "Я зробив імпорт URLSearchParams, але він все ще не працює без .toString () і явного заголовка!"

У HttpClient використовуйте HttpParams замість URLSearchParams і зверніть увагу на body = body.append()синтаксис для досягнення декількох параметрів у тілі, оскільки ми працюємо з незмінним об’єктом:

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

дякую за вищевказане рішення. Але під час запуску ng build --prod параметри мого тіла мають вигляд "{" params ": {" rawParams ":" "," queryEncoder ": {}," paramsMap ": {}}}:". Чи є якась робота навколо.
Hemanth Poluru

4

Якщо хтось бореться з кутовою версією 4+ (моя була 4.3.6) . Це був зразок коду, який працював у мене.

Спочатку додайте необхідний імпорт

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

Тоді для функції api. Це зразок для входу, який можна змінити відповідно до ваших потреб.

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

У мене були проблеми з кожним підходом із використанням декількох параметрів, але це досить добре працює з одним об’єктом

api:

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

кутова:

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
Проблема OP - це тип вмісту програми / x-www-form-urlencoded, ваша відповідь - зовсім інша проблема.
Крістіан Ульбріх,

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)

Привіт і ласкаво просимо до Stackoverflow. Дякуємо за відповідь на це запитання, але просто опублікувати блок коду важко зрозуміти для ОП або тих, хто стикається з цим питанням у майбутньому. Чи зможете ви відредагувати своє запитання та дати (коротке) пояснення щодо того, яку проблему ви вирішили та як її вирішили, щоб допомогти нам краще зрозуміти ваше рішення?
Плутіан

1
Привіт @Plutian, коли я передав значення 2-му параметру запиту на повідомлення, він повернув мені нульові значення на api, тому я передав цей другий параметр як порожній рядок, і я передав значення у властивості params 3-го параметра, тому цей метод спрацював для мене
Muniyan

-2

Я приземлився тут, коли намагався зробити подібне. Для типу вмісту application / x-www-form-urlencoded ви можете спробувати використовувати це для основного тексту:

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

з того, що ви спробували зробити, значення, призначене body, буде рядком.


Як зазначив Джошуа, це не дійсний JavaScript і TypeScript. Я думаю, що ви мали на увазі саме зараз прийняту відповідь.
Крістіан Ульбріх,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.