【问题标题】:Body of Http.DELETE request in Angular2Angular2 中 Http.DELETE 请求的正文
【发布时间】:2016-12-13 15:30:21
【问题描述】:

我正在尝试从 Angular 2 前端与有点 RESTful 的 API 对话。

要从集合中删除某些项目,除了删除的唯一 ID(可以附加到 url)之外,我还需要发送一些其他数据,即身份验证令牌、一些集合信息和一些辅助数据。

我发现最直接的方法是将身份验证令牌放在请求标头中,并将其他数据放在正文中。

但是,Angular 2 的 Http 模块并不完全同意带有正文的 DELETE 请求,并试图发出此请求

let headers= new Headers();
headers.append('access-token', token);

let body= JSON.stringify({
    target: targetId,
    subset: "fruits",
    reason: "rotten"
});

let options= new RequestOptions({headers:headers});
this.http.delete('http://testAPI:3000/stuff', body,options).subscribe((ok)=>{console.log(ok)}); <------line 67

给出这个错误

app/services/test.service.ts(67,4): error TS2346: Supplied parameters do not match any signature of call target.

现在,我在语法方面做错了吗?我很确定每个 RFC 都支持 DELETE 正文

有没有更好的方法来发送这些数据?

或者我应该把它转储到标题中然后收工吗?

对这个难题的任何见解将不胜感激

【问题讨论】:

  • 使用 POST 并将删除的措辞重命名为 findAndDelete 才有意义。
  • @YOU 是的,我可以,但我不应该尝试在请求类型级别将破坏性操作与非破坏性操作区分开来吗?
  • 那么您必须将其放入查询字符串中,但通常您将要删除的内容的 id 放入 url 中,并将身份验证承载放入 ajax 标头中以发送删除请求。
  • 经过几个小时搜索解决方案并收到很多错误后,我终于使用 POST 方法,现在一切正常。

标签: angular rest http-delete


【解决方案1】:

http.delete(url, options) 确实接受一个主体。您只需将其放在选项对象中即可。

http.delete('/api/something', new RequestOptions({
   headers: headers,
   body: anyObject
}))

参考选项界面: https://angular.io/api/http/RequestOptions

更新

上述 sn-p 仅适用于 Angular 2.x、4.x 和 5.x。

对于 6.x 以后的版本,Angular 提供了 15 种不同的重载。在此处检查所有重载:https://angular.io/api/common/http/HttpClient#delete

使用示例:

const options = {
  headers: new HttpHeaders({
    'Content-Type': 'application/json',
  }),
  body: {
    id: 1,
    name: 'test',
  },
};

this.httpClient
  .delete('http://localhost:8080/something', options)
  .subscribe((s) => {
    console.log(s);
  });

【讨论】:

  • RequestOptions 已弃用。
  • 找不到名称“RequestOptions”。我在角度 10 中收到此错误
  • @SachiniWitharana,如果你再读一遍,RequestOptions 已经被弃用了一段时间。从 v6 开始,httpClient 提供了不同的重载而不是接口。
  • 你刚刚救了我))
【解决方案2】:

如果您使用 Angular 6,我们可以将 body 放入 http.request 方法中。

Reference from github

你可以试试这个,对我来说很有效。

import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent {

  constructor(
    private http: HttpClient
  ) {
    http.request('delete', url, {body: body}).subscribe();
  }
}

【讨论】:

    【解决方案3】:

    在 Angular 5 中,我必须使用 request 方法而不是 delete 来发送正文。 delete 方法的文档不包含body,但它包含在请求方法中。

    import { HttpClient, HttpHeaders } from '@angular/common/http';
    
    this.http.request('DELETE', url, {
      headers: new HttpHeaders({
        'Content-Type': 'application/json',
      }),
      body: { foo: bar }
    });
    

    【讨论】:

    • 如果我尝试这种方法,请求方法包含选项而不是删除。你确定这仍然有效吗?
    • @Jochen 我很确定这对我有用并在 Angular 5 中发送 DELETE 请求
    • 问题已经找到,是服务器没有以正确的 OPTIONS 回答,因此客户端从未发送过 DELETE。
    【解决方案4】:

    您实际上可以使用request 方法欺骗Angular2 HTTPDELETE 发送body。方法如下:

    let body = {
        target: targetId,
        subset: "fruits",
        reason: "rotten"
    };
    
    let options = new RequestOptionsArgs({ 
        body: body,
        method: RequestMethod.Delete
      });
    
    this.http.request('http://testAPI:3000/stuff', options)
        .subscribe((ok)=>{console.log(ok)});
    

    注意,您必须在RequestOptionsArgs 中设置请求方法,而不是在http.request 的替代第一个参数Request 中。由于某种原因,这会产生与使用 http.delete

    相同的结果

    我希望这会有所帮助,并且我不会迟到。我认为有角的人在这里不允许通过删除传递一个主体是错误的,即使不鼓励这样做。

    【讨论】:

    • 我很晚才意识到@n4nd0_o 的做法相同,但仍在使用原始删除方法。无论如何,我都会将此答案留作替代解决方案。
    • 是的@Hampus,我们基本上提供了相同的答案。你的有点“冗长”,但是,同样的解决方案:D
    【解决方案5】:

    下面是带有新 HttpClient 的 Angular 4/5 的相关代码示例。

    import { HttpClient } from '@angular/common/http';
    import { HttpHeaders } from '@angular/common/http';
    
    public removeItem(item) {
        let options = {
          headers: new HttpHeaders({
            'Content-Type': 'application/json',
          }),
          body: item,
        };
    
        return this._http
          .delete('/api/menu-items', options)
          .map((response: Response) => response)
          .toPromise()
          .catch(this.handleError);
      }
    

    【讨论】:

      【解决方案6】:

      对于 Angular 10,您还可以使用通用请求格式和 DELETE 方法:

      http.request('DELETE',  path, {
                  body:body,
                  headers: httpHeaders,
                  params: ((params != null) ? params : new HttpParams())
              })
      

      【讨论】:

      • 谢谢!这个解决方案对我来说非常有效。为什么这没有更多的赞成票?
      • @AlexWillenbrink 可能是因为这个问题已经超过 5 年了,而这个答案只有几个月的历史
      • 这对我也有用!谢谢
      【解决方案7】:

      以下是 Angular 6 的示例

      deleteAccount(email) {
                  const header: HttpHeaders = new HttpHeaders()
                      .append('Content-Type', 'application/json; charset=UTF-8')
                      .append('Authorization', 'Bearer ' + sessionStorage.getItem('accessToken'));
                  const httpOptions = {
                      headers: header,
                      body: { Email: email }
                  };
                  return this.http.delete<any>(AppSettings.API_ENDPOINT + '/api/Account/DeleteAccount', httpOptions);
              }
      

      【讨论】:

      • 像魅力一样工作!
      【解决方案8】:

      REST 不会阻止 DELETE 请求中包含正文,但最好使用查询字符串,因为它是最标准化的(除非您需要加密数据)

      我通过执行以下操作使其与 angular 2 一起工作:

      let options:any = {}
      option.header = new Headers({
          'header_name':'value'
      });
      
      options.search = new URLSearchParams();
      options.search.set("query_string_key", "query_string_value");
      
      this.http.delete("/your/url", options).subscribe(...)
      

      【讨论】:

        【解决方案9】:

        以下是 Angular 2/4/5 项目的相关代码示例:

        let headers = new Headers({
          'Content-Type': 'application/json'
        });
        
        let options = new RequestOptions({
          headers: headers,
          body: {
            id: 123
          }
        });
        
        return this.http.delete("http//delete.example.com/delete", options)
          .map((response: Response) => {
            return response.json()
          })
          .catch(err => {
            return err;
          });
        

        注意body 是通过RequestOptions 传递的

        【讨论】:

          【解决方案10】:

          在 Angular Http 7 中,DELETE 方法接受作为第二个参数 options 对象,您可以在其中提供请求参数作为 params 对象以及 headers 对象。这与 Angular6 不同。

          参见示例:

          this.httpClient.delete('https://api-url', {
              headers: {},
              params: {
                  'param1': paramValue1,
                  'param2': paramValue2
              }
          });
          

          【讨论】:

            【解决方案11】:
            deleteInsurance(insuranceId: any) {
                const insuranceData = {
                  id : insuranceId
                }
                var reqHeader = new HttpHeaders({
                        "Content-Type": "application/json",
                    });
                    const httpOptions = {
                        headers: reqHeader,
                        body: insuranceData,
                    };
                return this.http.delete<any>(this.url + "users/insurance", httpOptions);
                }
            

            【讨论】:

              【解决方案12】:

              由于 RequestOptions 已弃用,因此不支持在 DELETE 请求中将数据作为正文发送。

              如果你看一下DELETE的定义,它看起来像这样:

                  delete<T>(url: string, options?: {
                    headers?: HttpHeaders | {
                       [header: string]: string | string[];
                      };
                    observe?: 'body';
                    params?: HttpParams | {
                        [param: string]: string | string[];
                       };
                    reportProgress?: boolean;
                    responseType?: 'json';
                    withCredentials?: boolean;
                   }): Observable<T>;
              

              您可以将有效负载与 DELETE 请求一起作为 options 对象中 params 的一部分发送,如下所示:

              this.http.delete('http://testAPI:3000/stuff', { params: {
                  data: yourData
                   }).subscribe((data)=>. 
                      {console.log(data)});
              

              但是,请注意,params 只接受 stringstring[] 形式的数据,因此除非将其字符串化,否则您将无法发送自己的接口数据。

              【讨论】:

              【解决方案13】:

              @angular/http 在 http.js 中的定义:

              删除(网址,选项)

              该请求不接受正文,因此您唯一的选择似乎是 URI 中的数据。

              我发现了另一个主题,其中引用了相应的 RFC,其中包括: How to pass data in the ajax DELETE request other than headers

              【讨论】:

              • 在 github 上是否有针对此主题的未解决问题?我认为绝对应该添加一个可选的 body 参数。
              • 另外两个答案证明这个答案是错误的,它不应该是公认的答案。
              • 为这个答案提供的链接指向 jquery ajax delete,而不是问题中指定的 Angular 2。这不应该是公认的答案。
              • 这个答案不应该被否决,RFC 说 DELETE 方法不支持请求正文。因此,即使可能有解决方法可以将其放在那里,但从技术上讲,它是一种 hack。
              • 对于 2021 年的人们,不幸的是,这是正确的答案。 delete 根本不应该支持请求正文。 +1
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-01-24
              • 2018-05-10
              • 1970-01-01
              • 2016-09-23
              • 2015-08-10
              • 2019-02-14
              相关资源
              最近更新 更多