50

I have to send a delete command to a REST API service with JSON content using the HttpClient class and can't make this working.

API call:

DELETE /xxx/current
{
 "authentication_token": ""
}

because I can't add any content into below statement:

HttpResponseMessage response = client.DeleteAsync(requestUri).Result;

I know how to make this work with RestSharp:

var request = new RestRequest {
    Resource = "/xxx/current",
    Method = Method.DELETE,
    RequestFormat = DataFormat.Json
};

var jsonPayload = JsonConvert.SerializeObject(cancelDto, Formatting.Indented);

request.Parameters.Clear();
request.AddHeader("Content-type", "application/json");
request.AddHeader ("Accept", "application/json");
request.AddParameter ("application/json", jsonPayload, ParameterType.RequestBody);

var response = await client.ExecuteTaskAsync (request);

but I have get it done without RestSharp.

demonplus
  • 5,613
  • 12
  • 49
  • 68
Tomasz Kowalczyk
  • 1,873
  • 2
  • 23
  • 33
  • [Possible place to start.](http://stackoverflow.com/questions/12022965/adding-http-headers-to-httpclient-asp-net-web-api) Also check out the MSDN article for [HttpRequestMessage](http://msdn.microsoft.com/en-us/library/system.net.http.httprequestmessage(v=vs.118).aspx). – Bradford Dillon Jan 20 '15 at 20:50

4 Answers4

99

Although it might be late to answer this question but I've faced a similar problem and the following code worked for me.

HttpRequestMessage request = new HttpRequestMessage
{
    Content = new StringContent("[YOUR JSON GOES HERE]", Encoding.UTF8, "application/json"),
    Method = HttpMethod.Delete,
    RequestUri = new Uri("[YOUR URL GOES HERE]")
};
await httpClient.SendAsync(request);

UPDATE on .NET 5

.NET 5 introduced JsonContent. Here is an extension method using JsonContent:

public static async Task<HttpResponseMessage> DeleteAsJsonAsync<TValue>(this HttpClient httpClient, string requestUri, TValue value)
{
    HttpRequestMessage request = new HttpRequestMessage
    {
        Content = JsonContent.Create(value),
        Method = HttpMethod.Delete,
        RequestUri = new Uri(requestUri, UriKind.Relative)
    };
    return await httpClient.SendAsync(request);
}
Farzan Hajian
  • 1,799
  • 17
  • 27
37

You can use these extension methods:

public static class HttpClientExtensions
{
    public static Task<HttpResponseMessage> DeleteAsJsonAsync<T>(this HttpClient httpClient, string requestUri, T data)
        => httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Delete, requestUri) { Content = Serialize(data) });

    public static Task<HttpResponseMessage> DeleteAsJsonAsync<T>(this HttpClient httpClient, string requestUri, T data, CancellationToken cancellationToken)
        => httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Delete, requestUri) { Content = Serialize(data) }, cancellationToken);

    public static Task<HttpResponseMessage> DeleteAsJsonAsync<T>(this HttpClient httpClient, Uri requestUri, T data)
        => httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Delete, requestUri) { Content = Serialize(data) });

    public static Task<HttpResponseMessage> DeleteAsJsonAsync<T>(this HttpClient httpClient, Uri requestUri, T data, CancellationToken cancellationToken)
        => httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Delete, requestUri) { Content = Serialize(data) }, cancellationToken);

    private static HttpContent Serialize(object data) => new StringContent(JsonSerializer.Serialize(data), Encoding.UTF8, "application/json");
}

If you're still using Newtonsoft.JSON, replace JsonSerializer.Serialize with JsonConvert.SerializeObject.

huysentruitw
  • 27,376
  • 9
  • 90
  • 133
  • Thank you! I wonder why Microsoft didn't add those extensions methods to https://msdn.microsoft.com/en-us/library/system.net.http.httpclientextensions.aspx as it did for POST and PUT. – vkelman Mar 22 '18 at 18:21
  • 1
    the private method uses NewtonsoftJson `JsonConvert.SerializeObject`. If you use `System.Text.Json` call `JsonSerializer.Serialize` instead. – Kebechet Aug 15 '23 at 05:52
  • 1
    @Kebechet thanks for your comment. I have updated my answer to use System.Text.Json by default with info about Newtonsoft. It's 2023 after all – huysentruitw Aug 18 '23 at 12:15
3

The answer from Farzan Hajian still didn't work for me, I could set the request content but it wasn't actually sent to the server.

As an alternative you could look at using the X-HTTP-Method-Override header. This tells the server that you want it to treat the request as if you sent a different verb than the one that you actually sent. You will have to ensure that the server handles this header correctly, but if it does you can just POST the request and add: X-HTTP-Method-Override:DELETE to the headers and it will be the equivalent of a DELETE request with a body.

kevev22
  • 3,737
  • 21
  • 32
  • 2
    Thanks - this worked for me. As far as I can tell, .NET is not happy with DELETE requests that use body content. With the API I'm integrating with, the request looked like it was being sent but the response always timed out. This occurred both with WebClient and HttpClient. Your suggestion of the method override header solved the problem. – ShibbyUK Mar 07 '19 at 13:00
0

Try with

Edited

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.your.url");

request.Method = "DELETE";

request.ContentType = "application/json";
request.Accept = "application/json";

using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
    string json = "{\"key\":\"value\"}";

    streamWriter.Write(json);
    streamWriter.Flush();
}

using (var httpResponse = (HttpWebResponse)request.GetResponse())
{
    // do something with response
}

Here you can find very similar problem.

Edited
I am not sure that passing request body for DELETE request is good approach. Especially when this is only for your authentication purposes. I will prefer to put authentication_token to Headers. It is because in my solution I will not have to parse the whole request body to check that current request is correctly authenticated. What about other request types? Do you always pass authentication_token in request body?

Community
  • 1
  • 1
rraszewski
  • 1,135
  • 7
  • 21
  • Passing a request body for DELETE is perfectly acceptable and necessary in some cases, EG if you are need to pass the entity in for deletion with DynamoDB and you are using a version field. – JohnOpincar Nov 06 '20 at 13:44