【问题标题】:Angular2 - Http POST request parametersAngular2 - Http POST 请求参数
【发布时间】:2016-05-14 17:35:47
【问题描述】:

我正在尝试发出 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 表单发起的一样:

网址:/api

参数:用户名和密码

【问题讨论】:

标签: typescript angular


【解决方案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 或将来遇到这个问题的任何人来说,仅仅发布一段代码是很难理解的。您能否edit您的问题并就您解决的问题以及您如何解决问题提供(简短的)解释,以帮助我们更好地了解您的解决方案?
  • 嗨@Plutian,当我传递post请求的第二个参数的值时,它返回api上的空值,所以我将第二个参数作为空字符串传递,我传递了第三个参数的params属性值所以这个方法对我有用
【解决方案2】:

Angular 4.3+

的更新

现在我们可以使用HttpClient 代替Http

指南是here

示例代码

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 年 10 月更新

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/json Content-Type

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

【讨论】:

  • 别忘了导入 URLSearchParams 类 import { URLSearchParams } from "angular2/http"
  • 我的导入看起来不同: import { URLSearchParams } from '@angular/http';
  • 但是,没有更简单的方法来发送表单对象吗?我没有看到任何使用 URLSearchParams() 为后端发送帖子的教程。他们是怎么做的? return this.http.post(this.actionUrl , body, { headers: this.headers }) .map((response: Response) => response.json()) .catch(this.handleError);
  • 这如何与布尔值一起工作?收到一条错误消息,说我不能添加布尔值或数字,只能添加字符串(附加)
  • 关于boolean,或许这个话题能帮到你stackoverflow.com/questions/14774907/…
【解决方案3】:

对于那些使用 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 参数看起来像“{“params”:{“rawParams”:“”,“queryEncoder”:{},“paramsMap”:{}}}:”。有什么解决办法吗?
【解决方案4】:

在更高版本的 Angular2 中,如果您将正确类型的对象传递为 body,则无需手动设置 Content-Type 标头和编码正文。

你可以这样做

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 标头。

附:不要忘记从@angular/http 导入URLSearchParams,否则将不起作用。

【讨论】:

  • @VStoykov 它不起作用,你必须在参数上使用 .toString() 并且你必须指定内容类型,我使用 angular 4.0.3
  • @i'myourhuckleberry 它甚至应该在 4.0.3 上工作。看源码github.com/angular/angular/blob/4.0.3/packages/http/src/…
  • @VStoykov 它对我不起作用,我已将其报告为 Github 上的错误
  • 好的。 Nvm 我必须从“@angular/http”导入它,否则它会识别类型,但它不是 angular 的类型。
  • @i'myourhuckleberry 导入是我示例中的第一行,但您可能错过了它。从浏览器的内置类型中,您可以使用FormData,并且角度会将Content-Type 设置为multipart/form-data,这也可以。
【解决方案5】:

如果有人正在为 angular 版本 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));
            }
        });
}

【讨论】:

    【解决方案6】:

    我对使用多个参数的每种方法都有问题,但它适用于单个对象

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

    【讨论】:

    • OP的问题是application/x-www-form-urlencoded的content-type,你的答案是完全不同的问题。
    【解决方案7】:

    所以只是为了使它成为一个完整的答案:

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

    【讨论】:

    • [ts] 类型参数 '{ headers: RequestOptions; }' 不可分配给“RequestOptionsArgs”类型的参数
    • @Sonic Soul 它只是:.. post('/api', body, headers) ... 没有 { } 在标题周围
    【解决方案8】:

    当我试图做类似的事情时,我来到了这里。对于 application/x-www-form-urlencoded 内容类型,您可以尝试将其用于正文:

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

    您尝试执行的操作分配给 body 的值将是一个字符串。

    【讨论】:

    • 正如 Joshua 指出的,这不是有效的 JavaScript 和 TypeScript。我认为您的意思正是当前接受的答案。
    【解决方案9】:

    我认为 application/x-www-form-urlencoded 内容类型的正文不正确。你可以试试这个:

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

    希望对你有帮助 蒂埃里

    【讨论】:

    • 是的,在标头中使用该内容类型,它是唯一以“旧方式”而不是 json 字符串传递值的解决方案
    • 这不是一个好的答案。请改用 URLSearchParams,如下所述,获得更多支持。
    • 对于来自 Google 搜索的未来人来说,这不是最好的答案(Thierry 无意冒犯!你的答案在技术上仍然是正确的 :))。 V Stoykov 的answer 是迄今为止最准确的。 p.s.确保import { URLSearchParams } from "@angular/http" 而不是默认的,所以1)你不需要在上面做.toString,2)你不需要设置内容类型。 Angular 会自动为你推断(见github.com/angular/angular/blob/4.4.4/packages/http/src/…
    • 嗨!如果我想传递带有标题的帖子服务 - > 内容类型(如“应用程序/json”),我需要在正文中传递什么……我正在尝试传递 json 对象,但它无法正常工作……
    猜你喜欢
    • 1970-01-01
    • 2017-12-24
    • 2016-12-31
    • 2017-03-12
    • 1970-01-01
    • 2017-03-10
    • 2017-10-07
    • 1970-01-01
    • 2018-05-10
    相关资源
    最近更新 更多