Angular2中Http.DELETE请求的主体

101

我正在尝试从Angular 2前端与一个相对RESTful的API进行通讯。

为了从一个集合中删除某个项,除了要将其唯一标识符(可以附加到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 body是被支持的。

还有更好的发送这些数据的方法吗?

或者我应该只是把它倒入标题中并结束呢?

任何关于这个难题的见解都将不胜感激。


1
使用POST方法,并将删除操作重命名为findAndDelete以使其更有意义。 - YOU
@你 是的,我可以这样做,但是我不应该尝试在请求类型级别将破坏性操作与非破坏性操作区分开来吗? - TriTap
然后你将不得不将它放在查询字符串中,但通常你会将想要删除的ID放在URL中,并在AJAX头部中放置身份验证令牌以发送删除请求。 - YOU
在搜索了几个小时的解决方案并收到了很多错误后,我最终使用了POST方法,现在一切都正常了。 - Yamashiro Rion
14个回答

220

http.delete(url, options) 可以接受请求体,只需将其放入 options 对象中即可。

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

参考选项接口: https://angular.io/api/http/RequestOptions

更新:

上述代码片段仅适用于 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);
  });

26
请求选项 RequestOptions 已被弃用。 - hestellezg
在 Angular 10 中,我遇到了“找不到名称'RequestOptions'”这个错误。 - Sachini Witharana
@SachiniWitharana,如果你再仔细看一遍,RequestOptions 已经过时了。自从 v6 版本以来,httpClient 提供了不同的重载而不是接口。 - n4nd0_o
你刚刚救了我)) - Tatyana Molchanova

28

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

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

22

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

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

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

如果我尝试这种方法,请求方法会包含OPTIONS而不是DELETE。你确定这仍然有效吗? - Jochen
@Jochen 我非常确定这个对我有效,并在 Angular 5 中发送了 DELETE 请求。 - Dominik Szymański
问题已经找到了,原因是服务器没有正确地回答OPTIONS请求,因此客户端从未发送DELETE请求。 - Jochen

19

通过使用 request 方法,您实际上可以欺骗 Angular2 HTTP 发送带有 DELETEbody。具体方法如下:

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
是的 @Hampus,我们基本上提供了相同的答案。虽然你的答案更加 "冗长",但是解决方案是一样的 :D - n4nd0_o

12

以下是Angular 4/5的相关代码示例,使用新的HttpClient。

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

9

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

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

1
谢谢!这个解决方案对我非常有效。为什么没有更多的赞? - Alex Willenbrink
@AlexWillenbrink 可能是因为这个问题已经超过5年了,而这个答案仅仅几个月前发布的。 - claudekennilol
1
这对我也有效!谢谢 - Deniss M.

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

5
在Angular 13中,这对我来说很有效:
const options = {
   headers: this._headers,
   body: JSON.stringify(user)
};

return this._http.delete<DeleteVirtualAssistantResult>(`${this._apiUrl}/users`, options);

1
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(...)

0

以下是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传递的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接