curl PUT, DELETE and PATCH requests in C#
To send curl PUT, DELETE and PATCH requests in C#, pass -X <METHOD> in the command string to Curl.ExecuteAsync, with -d for the body where the method takes one. Every verb curl accepts works the same way, so the command from an API’s documentation can be used as-is.
PUT - replace a resource
using CurlDotNet;
var result = await Curl.ExecuteAsync(@"
curl -X PUT https://httpbin.org/put \
-H 'Content-Type: application/json' \
-d '{""name"":""Ada"",""role"":""admin""}'");
Console.WriteLine(result.StatusCode); // 200
PATCH - partial update
var result = await Curl.ExecuteAsync(@"
curl -X PATCH https://httpbin.org/patch \
-H 'Content-Type: application/json' \
-d '{""role"":""editor""}'");
Console.WriteLine(result.Body);
DELETE
var result = await Curl.ExecuteAsync("curl -X DELETE https://httpbin.org/delete");
Console.WriteLine(result.IsSuccess ? "deleted" : $"HTTP {result.StatusCode}");
Many APIs answer DELETE with 204 No Content; IsSuccess is true for any 2xx and Body is empty.
Builder style
using CurlDotNet.Core;
var put = await CurlRequestBuilder.Put("https://httpbin.org/put")
.WithJson(new { name = "Ada", role = "admin" })
.ExecuteAsync();
var patch = await CurlRequestBuilder.Patch("https://httpbin.org/patch")
.WithJson(new { role = "editor" })
.ExecuteAsync();
var del = await CurlRequestBuilder.Delete("https://httpbin.org/delete").ExecuteAsync();
Console.WriteLine($"{put.StatusCode} {patch.StatusCode} {del.StatusCode}");
WithJson serialises the object and sets Content-Type: application/json. For a raw string body use WithData("..."), and for any other verb CurlRequestBuilder.Request("OPTIONS", url).
Reusable client
using CurlDotNet.Lib;
using var api = new LibCurl()
.WithBearerToken(Environment.GetEnvironmentVariable("API_TOKEN"))
.WithTimeout(TimeSpan.FromSeconds(15));
await api.PutAsync("https://httpbin.org/put", new { name = "Ada" });
await api.PatchAsync("https://httpbin.org/patch", new { role = "editor" });
var deleted = await api.DeleteAsync("https://httpbin.org/delete");
Console.WriteLine(deleted.StatusCode);
Object bodies on PutAsync/PatchAsync are sent as JSON.
Check the outcome
var result = await Curl.ExecuteAsync("curl -X DELETE https://httpbin.org/status/404");
if (!result.IsSuccess)
Console.WriteLine($"Delete failed: {result.StatusCode} {result.Body}");
Without -f, HTTP errors are returned, not thrown. Call result.EnsureSuccess() if you prefer an exception, or add -f / --fail-with-body to the command to get CurlHttpReturnedErrorException (curl exit code 22).
Gotchas
-dwithout-Xmeans POST, as in curl. Add-X PUTor-X PATCHexplicitly when you want those verbs.-Xonly changes the method name:-X GET -d 'q=1'really sends a GET with a body. Use-Gto put the data in the query string instead.-T fileuploads a file’s bytes with PUT, no-Xneeded; see Upload a file.- Options that ask for different kinds of request, such as
-Iwith-dor-Fwith-d, are rejected with aCurlExceptioncarrying exit code 2, just as curl refuses them. - With
-L, an-Xmethod is reused on every redirect hop (curl’s behaviour); see follow redirects. - Quotes inside the JSON body: in a C# verbatim string (
@"...") double each", or build the JSON withJsonSerializer.Serializeand interpolate it. - A DELETE with a body is legal but some servers ignore it; prefer ids in the URL.