Angular2 - พารามิเตอร์คำขอ Http POST


94

ฉันพยายามส่งคำขอ 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

Params: ชื่อผู้ใช้และรหัสผ่าน


ลองดูที่stackoverflow.com/a/34758630/5043867และstackoverflow.com/a/34823818/5043867นี้จะอธิบายทั้งหมดเกี่ยวกับคำขอ POST แบบเจาะลึก!
Pardeep Jain

@PardeepJain ฉันไม่ได้พยายามใช้ API เพียงเพื่อจำลอง POST ที่มาจากรูปแบบ html
Christopher

นอกจากนี้ยังตรวจสอบที่นี่โพสต์ไฟล์ที่มีuser_nameและpassword, stackoverflow.com/a/45879409/2803344
Belter

คำตอบ:


49

ฉันคิดว่าเนื้อหาไม่ถูกต้องสำหรับapplication/x-www-form-urlencodedประเภทเนื้อหา คุณสามารถลองใช้สิ่งนี้:

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

หวังว่ามันจะช่วยคุณ Thierry


ใช่กับประเภทเนื้อหานั้นในส่วนหัวเป็นโซลูชันเดียวที่ส่งผ่านค่าใน "วิธีเก่า" แทนสตริง json
Nather Webber

นี่ไม่ใช่คำตอบที่ดี ใช้ URLSearchParams แทนเช่นที่กล่าวไว้ด้านล่างพร้อมการโหวตเพิ่มขึ้น
มิก

สำหรับผู้คนจากอนาคตที่มาจากการค้นหาของ Google นี่ไม่ใช่คำตอบที่ดีที่สุด (Thierry ไม่มีความผิด! คำตอบของคุณยังคงถูกต้องในทางเทคนิค :)) คำตอบของ V Stoykov นั้นแม่นยำที่สุด ps ตรวจสอบให้แน่ใจว่า import { URLSearchParams } from "@angular/http"ไม่ใช่ค่าเริ่มต้นดังนั้น 1) คุณไม่จำเป็นต้องทำสิ่ง.toStringนั้นและ 2) คุณไม่จำเป็นต้องตั้งค่าประเภทเนื้อหา Angular จะสรุปให้คุณโดยอัตโนมัติ (ดูgithub.com/angular/angular/blob/4.4.4/packages/http/src/… )
Eran Medan

ไฮ! หากฉันต้องการส่งบริการโพสต์ด้วยส่วนหัว -> ประเภทเนื้อหาเช่น '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()

อัปเดต ต.ค. / 2560

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

สำหรับ 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
อย่าลืมนำเข้า URLSearchParams Classimport { URLSearchParams } from "angular2/http"
Sebastian Hernandez

10
การนำเข้าของฉันดูแตกต่างออกไป: นำเข้า {URLSearchParams} จาก "@ angular / http";
dang

แต่ไม่มีวิธีที่ง่ายกว่าในการส่งวัตถุแบบฟอร์ม? ฉันไม่เห็นบทช่วยสอนใด ๆ ที่ใช้ URLSearchParams () เพื่อส่งโพสต์สำหรับแบ็กเอนด์ด้วยความสงบ พวกเขาทำอย่างไร? ส่งคืน this.http.post (this.actionUrl, body, {headers: this.headers}) .map ((response: Response) => response.json ()) .catch (this.handleError);
stackdave

วิธีนี้ทำงานร่วมกับบูลีนได้อย่างไร ได้รับข้อผิดพลาดแจ้งว่าฉันไม่สามารถเพิ่มบูลีนหรือตัวเลขเพียงแค่สตริง (ในภาคผนวก)
JohnAndrews

เกี่ยวกับบูลีนหัวข้อนี้อาจช่วยคุณได้stackoverflow.com/questions/14774907/…
Frank Nguyen

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

วิธีนี้เชิงมุมจะเข้ารหัสร่างกายให้คุณและจะตั้งค่าContent-Typeส่วนหัวที่ถูกต้อง

ปล. อย่าลืม import URLSearchParamsจาก@angular/httpไม่งั้นจะใช้ไม่ได้


2
@VStoykov มันใช้ไม่ได้คุณต้อง. toString () บนพารามิเตอร์และคุณต้องระบุประเภทเนื้อหาและฉันใช้เชิงมุม 4.0.3
Konrad

1
@ i'myourhuckleberry มันควรจะใช้งานได้แม้ใน 4.0.3 ดูซอร์สโค้ดgithub.com/angular/angular/blob/4.0.3/packages/http/src/…
VStoykov

1
@VStoykov มันไม่ได้ผลสำหรับฉันและฉันได้รายงานว่ามันเป็นข้อผิดพลาดใน Github
Konrad

1
ตกลง. Nvm ฉันต้องนำเข้าสิ่งนี้จาก "@ angular / http" มิฉะนั้นจะจดจำประเภท แต่ไม่ใช่ประเภทของเชิงมุม
Konrad

1
@ i'myourhuckleberry การนำเข้าเป็นบรรทัดแรกในตัวอย่างของฉัน แต่คุณอาจพลาดไป จากประเภทที่สร้างขึ้นในเบราว์เซอร์คุณสามารถใช้ได้FormDataและเชิงมุมจะตั้งค่าContent-Typeตามmultipart/form-dataที่ใช้งานได้เช่นกัน
VStoykov

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] อาร์กิวเมนต์ประเภท '{headers: RequestOptions; } 'ไม่สามารถกำหนดให้กับพารามิเตอร์ประเภท' RequestOptionsArgs '
Sonic Soul

2
@Sonic Soul It's just: .. post ('/ api', body, headers) ... without {} around 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 body param ของฉันดูเหมือน "{" 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));
            }
        });
}

1
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 ขอบคุณที่ตอบคำถามนี้ แต่การโพสต์บล็อกโค้ดนั้นยากที่จะเข้าใจสำหรับ OP หรือใครก็ตามที่เจอคำถามนี้ในอนาคต คุณจะสามารถแก้ไขคำถามของคุณและให้คำอธิบาย (สั้น ๆ ) เกี่ยวกับปัญหาที่คุณแก้ไขได้และคุณแก้ไขอย่างไรเพื่อช่วยให้เราเข้าใจวิธีแก้ปัญหาของคุณได้ดีขึ้น
Plutian

1
สวัสดี @Plutian เมื่อฉันส่งผ่านค่าในพารามิเตอร์ที่ 2 ของคำขอโพสต์มันส่งคืนค่า null ใน api ให้ฉันดังนั้นฉันจึงส่งพารามิเตอร์ที่ 2 เป็นสตริงว่างและฉันส่งผ่านค่าในคุณสมบัติ params ของพารามิเตอร์ที่ 3 ดังนั้นวิธีนี้จึงใช้ได้กับฉัน
Muniyan

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 คำตอบของคุณเป็นปัญหาที่แตกต่างกันโดยสิ้นเชิง
Christian Ulbrich

-2

ฉันมาถึงที่นี่ตอนที่ฉันพยายามทำสิ่งที่คล้ายกัน สำหรับประเภทเนื้อหาของ application / x-www-form-urlencoded คุณสามารถลองใช้สิ่งนี้สำหรับ body:

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

กับสิ่งที่คุณพยายามทำค่าที่กำหนดให้กับ body จะเป็นสตริง


ดังที่ Joshua ชี้ให้เห็นว่านี่ไม่ใช่ JavaScript หรือ TypeScript ที่ถูกต้อง ฉันคิดว่าสิ่งที่คุณหมายถึงคือคำตอบที่ยอมรับในปัจจุบัน
Christian Ulbrich
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.