22

I have an ASP.NET MVC 5 website - in C# client code I am using HttpClient.PutAsJsonAsync(path, myObject) fine to call a Json API (the API is also mine created in Web API).

client.BaseAddress = new Uri("http://mydomain");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.PutAsJsonAsync("api/something", myObj);

I would like to do the same with a Delete verb. However client.DeleteAsync does not allow an object to be passed in the body. (I would like to record the reason for deletion alongside the Id of the item to delete in the URI).

Is there a way to do this?

niico
  • 11,206
  • 23
  • 78
  • 161
  • 1
    Can I know why you want to pass an Object in Delete method ? You can pass an Id in your URL – Basanta Matia Mar 25 '17 at 16:16
  • 1
    pass it as a parameter. and reconstruct your complex object model on the action – Nkosi Mar 25 '17 at 16:17
  • Because I may be sending lots of additional information - like reasons for the deletion. I would rather not pass a lot of information in the URI. Is this possible in the body of a delete? – niico Mar 25 '17 at 16:18
  • @niico, No. HTTP DELETE requests do not allow a request body. – Nkosi Mar 25 '17 at 16:19
  • OK - so what do people do if they want to include reasons for the deletion - just pass it in the URI and I guess keep it shorter? Or do they just not use DELETE and use POST instead say? – niico Mar 25 '17 at 16:20
  • @niico, It Depends. And that is more a matter of opinion. – Nkosi Mar 25 '17 at 16:22
  • 1
    @niico take a look at some of the answers here. http://stackoverflow.com/questions/14323716/restful-alternatives-to-delete-request-body – Nkosi Mar 25 '17 at 16:24
  • 1
    I am more partial to `DELETE /api/path/{id}/{reason}` but again (primarily opinion based) – Nkosi Mar 25 '17 at 16:25
  • doesn't DELETE /api/path/{id}/{reason} violate REST rules?! – niico Mar 25 '17 at 16:35
  • @niico for strict REST yes. it would make the api Rest-ful. – Nkosi Mar 25 '17 at 16:39
  • @Nkosi Perhaps "rest-ish" might be a better word for it ;) As there is no perfect solution here this may be a good option, going to consider this thanks. – niico Mar 25 '17 at 16:46
  • 1
    A 3rd option to consider it is the query string. Putting it in the path violates REST in that it's not part of the resource's identity/location, so I would not do that. Since it's just a single string value, query string would be my first choice, body my second. – Todd Menier Mar 25 '17 at 16:48
  • seems like there is little agreement on this - and therefore no best practice exists?! – niico Mar 25 '17 at 16:50
  • RFC 7231 stipulates: "DELETE - No defined body semantics." - so body is a bad idea no? – niico Mar 25 '17 at 16:50
  • sorry I will quote it directly - not somebody's analysis of it from another question "A payload within a DELETE request message has no defined semantics" – niico Mar 25 '17 at 17:09
  • Ah, I missed that when searching the spec, wasn't trying to be nit picky :) – Todd Menier Mar 25 '17 at 17:34

1 Answers1

45

You'll have to give up a little in terms of convenience since the higher-level DeleteAsync doesn't support a body, but it's still pretty straightforward to do it the "long way":

var request = new HttpRequestMessage {
    Method = HttpMethod.Delete,
    RequestUri = new Uri("http://mydomain/api/something"),
    Content = new StringContent(JsonConvert.SerializeObject(myObj), Encoding.UTF8, "application/json")
};
var response = await client.SendAsync(request);
Todd Menier
  • 37,557
  • 17
  • 150
  • 173
  • 2
    Thanks. Seems like using body in a DELETE is unconventional and therefore not a good idea though?! – niico Mar 25 '17 at 16:42
  • 2
    Not typical but not unheard of. I got a [request](https://github.com/tmenier/Flurl/issues/91) to accommodate it in my Flurl library not long ago. – Todd Menier Mar 25 '17 at 16:46
  • 1
    Apparently RFC 7231 stipulates: "DELETE - No defined body semantics." - seems a bad idea going against standards no? – niico Mar 25 '17 at 16:49
  • Where in the spec did you see that? I'm looking at it right now and I don't see that anywhere. – Todd Menier Mar 25 '17 at 16:54
  • answer by alix axel: http://stackoverflow.com/questions/5905916/payloads-of-http-request-methods?rq=1 – niico Mar 25 '17 at 16:55
  • So the spec does't say it, and even if it did that's very different from saying it's not allowed, which is certainly is. That said, I concede that it further supports your argument that it's unconventional, and reinforces my recommendation to put it in the query string. – Todd Menier Mar 25 '17 at 17:03
  • sorry I will quote it directly - not somebody's analysis of it from another question "A payload within a DELETE request message has no defined semantics" – niico Mar 25 '17 at 17:09
  • querystring is interesting - but super gross, but then what isn't. I feel like all options have been presented to me at this point - there's no perfect solution to this, everything is a compromise?! – niico Mar 25 '17 at 17:10
  • The fact c# doesn't provide a body in a client.DeleteAsync is also an indication that it is a bit naughty / unconventional right? – niico Mar 25 '17 at 17:14
  • Agreed. Capturing a reason for a delete is a very valid use case, and using the query string is the lesser of 3 evils in my mind. – Todd Menier Mar 25 '17 at 17:31
  • If you make a new answer with the querystring suggestion I'll accept it - thx. – niico Mar 27 '17 at 08:11
  • 1
    I would but that wouldn't answer the question you asked. This one does, which is more useful to others who find it via search. If the querystring suggestion was helpful, cool, I don't need points for it. :) – Todd Menier Mar 27 '17 at 19:30
  • Lol ok - I think intent wise it does answer it, it's how I will solve this and maybe how others will too - but of course your call. – niico Mar 27 '17 at 19:37
  • A bit late to the party but I just need to do this for a batched-delete where the body was a json collection of int's for the productids I wanted deleted. – Thomas Feb 11 '21 at 14:03