In C#, how do you send an HTTP POST request to a URL?
Let’s take a simple example you can run in a terminal with curl
to a test site, and see if we can recreate it in .NET:
curl -X POST https://httpbin.org/post -H "Content-Type: application/json" -d '{"name":"Alice"}' # Result returned by httpbin.org: { "args": {}, "data": "{\"name\":\"Alice\"}", "files": {}, "form": {}, "headers": { "Accept": "*/*", "Content-Length": "16", "Content-Type": "application/json", "Host": "httpbin.org", "User-Agent": "curl/7.81.0", "X-Amzn-Trace-Id": "Root=1-6571815c-1743cbd01a39a04a466fd1ab" }, "json": { "name": "Alice" }, "origin": "5.157.13.3", "url": "https://httpbin.org/post" }
Microsoft recommends using the HttpClient
for web requests.
Here’s a C# example that has the same result as the curl
command above:
using System; using System.Collections.Generic; using System.Net.Http; // for HttpClient using System.Threading.Tasks; public class Program { public static async Task Main() { using var client = new HttpClient(); var values = new Dictionary<string, string> { { "name", "alice" } }; var content = new FormUrlEncodedContent(values); var response = await client.PostAsync("https://httpbin.org/post", content); var responseString = await response.Content.ReadAsStringAsync(); Console.WriteLine(responseString); } }
We use an asynchronous Main
method, instead of the traditional public static void Main()
. This allows us to use await
so our app can do other work while waiting for a response from the website.
Your app should only have one instance of HttpClient
, to use as few network resources as possible. Every class in your app can share a single HttpClient. Here we are also instantiating HttpClient
with a using
statement so that .NET immediately frees its network resources when it is no longer in use.
To make the request, we create a dictionary with whatever POST key-value pairs we want to send and use the client
’s PostAsync
method to send the encoded data. The response is returned as a string, which we print.
If you prefer a more fluent or functional style of coding with fewer temporary variables, you can refactor this function as:
using var client = new HttpClient(); var data = new FormUrlEncodedContent(new Dictionary<string, string> { { "name", "alice" } }); var responseString = await client.PostAsync("https://httpbin.org/post", data) .Result .Content .ReadAsStringAsync(); Console.WriteLine(responseString);
Here’s how to make a GET request instead of a POST:
using System; using System.Net.Http; using System.Threading.Tasks; public class Program { public static async Task Main() { using var client = new HttpClient(); var response = await client.GetAsync("https://httpbin.org/get"); var responseString = await response.Content.ReadAsStringAsync(); Console.WriteLine(responseString); } } /* Response: { "args": {}, "headers": { "Host": "httpbin.org", "X-Amzn-Trace-Id": "Root=1-65718c3b-35fba5f01f87156337c46655" }, "origin": "40.112.208.75", "url": "https://httpbin.org/get" } */
We have only removed code from the POST request example, and changed PostAsync
to GetAsync
.
If you want to serialize and deserialize .NET objects to JSON strings to transfer them in HTTP requests, you can use Microsoft’s JsonSerializer
class. We have a simple example of this in this article.
You can also use the shortcut package System.Net.Http.Json
. It provides two methods to read and write JSON:
var data = new Person(Id: 1, Name: "Alice"); var response = await httpClient.PostAsJsonAsync("data", data); var todo = await response.Content.ReadFromJsonAsync<Person>();
Read Microsoft’s detailed documentation on the HttpClient
class here. It explains how to catch timeout exceptions and check status codes.
Loved by over 4 million developers and more than 90,000 organizations worldwide, Sentry provides code-level observability to many of the world’s best-known companies like Disney, Peloton, Cloudflare, Eventbrite, Slack, Supercell, and Rockstar Games. Each month we process billions of exceptions from the most popular products on the internet.