How can I make an HTTP POST request and send data in the body?
17 Answers
There are several ways to perform HTTP GET and POST requests:
Method A: HttpClient (Preferred)
Available in: .NET Framework 4.5+, .NET Standard 1.1+, and .NET Core 1.0+.
It is currently the preferred approach, and is asynchronous and high performance. Use the built-in version in most cases, but for very old platforms there is a NuGet package.
using System.Net.Http;
Setup
It is recommended to instantiate one HttpClient
for your application's lifetime and share it unless you have a specific reason not to.
private static readonly HttpClient client = new HttpClient();
See HttpClientFactory
for a dependency injection solution.
POST
var values = new Dictionary<string, string> { { "thing1", "hello" }, { "thing2", "world" } }; var content = new FormUrlEncodedContent(values); var response = await client.PostAsync("http://www.example.com/recepticle.aspx", content); var responseString = await response.Content.ReadAsStringAsync();
GET
var responseString = await client.GetStringAsync("http://www.example.com/recepticle.aspx");
Method B: Third-Party Libraries
POST
var client = new RestClient("http://example.com"); // client.Authenticator = new HttpBasicAuthenticator(username, password); var request = new RestRequest("resource/{id}"); request.AddParameter("thing1", "Hello"); request.AddParameter("thing2", "world"); request.AddHeader("header", "value"); request.AddFile("file", path); var response = client.Post(request); var content = response.Content; // Raw content as string var response2 = client.Post<Person>(request); var name = response2.Data.Name;
It is a newer library sporting a fluent API, testing helpers, uses HttpClient under the hood, and is portable. It is available via NuGet.
using Flurl.Http;
POST
var responseString = await "http://www.example.com/recepticle.aspx" .PostUrlEncodedAsync(new { thing1 = "hello", thing2 = "world" }) .ReceiveString();
GET
var responseString = await "http://www.example.com/recepticle.aspx" .GetStringAsync();
Method C: HttpWebRequest (not recommended for new work)
Available in: .NET Framework 1.1+, .NET Standard 2.0+, .NET Core 1.0+. In .NET Core, it is mostly for compatibility -- it wraps HttpClient
, is less performant, and won't get new features.
using System.Net;
using System.Text; // For class Encoding
using System.IO; // For StreamReader
POST
var request = (HttpWebRequest)WebRequest.Create("http://www.example.com/recepticle.aspx"); var postData = "thing1=" + Uri.EscapeDataString("hello"); postData += "&thing2=" + Uri.EscapeDataString("world"); var data = Encoding.ASCII.GetBytes(postData); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = data.Length; using (var stream = request.GetRequestStream()) { stream.Write(data, 0, data.Length); } var response = (HttpWebResponse)request.GetResponse(); var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
GET
var request = (HttpWebRequest)WebRequest.Create("http://www.example.com/recepticle.aspx"); var response = (HttpWebResponse)request.GetResponse(); var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
Method D: WebClient (Not recommended for new work)
This is a wrapper around HttpWebRequest
. Compare with HttpClient
.
Available in: .NET Framework 1.1+, NET Standard 2.0+, and .NET Core 2.0+.
In some circumstances (.NET Framework 4.5-4.8), if you need to do a HTTP request synchronously, WebClient
can still be used.
using System.Net;
using System.Collections.Specialized;
POST
using (var client = new WebClient()) { var values = new NameValueCollection(); values["thing1"] = "hello"; values["thing2"] = "world"; var response = client.UploadValues("http://www.example.com/recepticle.aspx", values); var responseString = Encoding.Default.GetString(response); }
GET
using (var client = new WebClient()) { var responseString = client.DownloadString("http://www.example.com/recepticle.aspx"); }

- 30,738
- 21
- 105
- 131

- 54,662
- 15
- 117
- 144
-
1How do you get the response from that? – Lloyd Mar 25 '11 at 17:38
-
3@Lloyd: `HttpWebResponse response = (HttpWebResponse)HttpWReq.GetResponse();` – Evan Mulawski Mar 25 '11 at 17:44
-
after the newStream is closed? – Lloyd Mar 25 '11 at 18:52
-
@Lloyd: If you are posting data to the stream (using the last three lines) it would make sense to check the response beforehand. – Evan Mulawski Mar 25 '11 at 19:07
-
1Why are you instantiating the ASCIIEncoding object instead of using the static `System.Text.Encoding.ASCII`? – Mathias Lykkegaard Lorenzen Aug 09 '13 at 07:59
-
3Why do you even use ASCII? What if someone needs an xml with UTF-8? – Gero Aug 09 '13 at 11:04
-
After so long time. I switched accepted answer to yours. As it is so much more detailed and I like that you shown old, obsolete methods. – Hooch Nov 20 '14 at 10:30
-
13I hate to beat a dead horse but you should do `response.Result.Content.ReadAsStringAsync()` – David S. Jan 25 '15 at 23:19
-
@DavidS. `response` should be a `HttpResponseMessage` - are you missing an `await` when calling `PostAsync`? – Evan Mulawski Jan 25 '15 at 23:43
-
19why did you say WebRequest and WebClient are legacy? MSDN doesn't say that they are deprecated or anything. Am I missing something? – Hiep Nov 18 '15 at 13:27
-
27@Hiep: They are not deprecated, there are just newer (and is most cases, better and more flexible) ways of making web requests. In my opinion, for simple, non-critical operations, the old ways are just fine - but it's up to you and whatever you are most comfortable with. – Evan Mulawski Nov 18 '15 at 14:47
-
I know you said the preferred method is to instantiate a private readonly HttpClient but I think it is cleaner (and safer) to do a using statement instead. `using (var client = new HttpClient()) { }` – Greg A May 30 '17 at 16:04
-
2@GregA: It's not just me. The developers of `HttpClient` recommend one instantiation per application. In reality, it may be necessary to instantiate more, depending on what your application does. Just because it implements `IDisposable` does not mean you must put it in a `using` block. – Evan Mulawski May 30 '17 at 17:42
-
@EvanMulawski Evan, in my application I am using dependency injection in a web api. In my case i believe taking advantage of the `using` block is the correct way to go. – Greg A May 31 '17 at 18:55
-
`RestSharp` seems to be dead. Simply dead. – hellboy Jul 14 '17 at 12:06
-
I wish this answer mentioned that it is possible to post raw `byte[]` content by substituting a [`ByteArrayContent`](https://learn.microsoft.com/en-us/previous-versions/visualstudio/hh193557%28v%3dvs.118%29) for the example's `FormUrlEncodedContent` and to read raw `byte[]` content with [`response.Content.ReadAsByteArrayAsync()`](https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpcontent.readasbytearrayasync?view=netframework-4.8). – Wyck Jun 17 '19 at 20:44
-
What are advantages of HttpClient over HttpWebRequest and WebClient beyond asyncronism? Why the last two has become legacy? – Douglas Ferreira Aug 01 '19 at 14:51
-
2@DouglasFerreira `HttpClient` and `WebClient` are higher-level wrappers around `HttpWebRequest`. The real question is when to use `HttpClient` as opposed to `WebClient` (or vice versa); this is best described in https://stackoverflow.com/questions/20530152/deciding-between-httpclient-and-webclient/27737601#27737601. – Evan Mulawski Aug 06 '19 at 12:13
-
Thank you very much for your complete and useful answer. I learned a whole new way by reading it, because I've just started learning C # programming. – elnaz jangi Jun 12 '20 at 19:25
-
For method A - adding headers: client.DefaultRequestHeaders.Add("name", "value"); – Rony Tesler Apr 15 '22 at 13:31
-
HttpClient has properties like `BaseAddress` and handy methods like `CancelPendingRequests()`. "Instantiat[ing] one HttpClient for your application's lifetime" would be a very brave thing to do. I believe the intention is to create 1 HttpClient per use case or group of use cases attacking a same origin, in a singleton scoped service class or something like that. So there's a whole bunch of complexity you didn't ask for and likely don't need. 3 cheers for OO. – bbsimonbb Jun 08 '22 at 08:39
-
HttpClient is a bish to test since it has no interface https://stackoverflow.com/questions/36425008/mocking-httpclient-in-unit-tests You need all kinds of workarounds to write a unit test for it, just a consideration – obesechicken13 Jun 08 '22 at 16:00
-
@obesechicken13 You would typically mock the underlying handler instead of HttpClient itself (see `Moq.Contrib.HttpClient` package). – Evan Mulawski Jun 13 '22 at 16:20
-
How to get the return URL generated by the POST using method A? – Franco Jul 08 '22 at 06:42
Simple GET request
using System.Net;
...
using (var wb = new WebClient())
{
var response = wb.DownloadString(url);
}
Simple POST request
using System.Net;
using System.Collections.Specialized;
...
using (var wb = new WebClient())
{
var data = new NameValueCollection();
data["username"] = "myUser";
data["password"] = "myPassword";
var response = wb.UploadValues(url, "POST", data);
string responseInString = Encoding.UTF8.GetString(response);
}

- 3
- 2

- 7,438
- 3
- 28
- 28
-
20+1 For regular stuff POST it is great to have such short piece of code. – user_v Sep 11 '13 at 06:15
-
3Tim - If you right click the literal that can't be resolved, you will find a Resolve context menu, which contains actions to add the Using statements for you. If the Resolve context menu doesn't show up, it means you need to add references first. – Cameron Wilby Nov 09 '13 at 02:45
-
1I accepted your answer as good because it is much more simpler and clearer. – Hooch Jan 03 '14 at 22:09
-
15I would like to add that the response variable for the POST request is a byte array. In order to get the string response you just do Encoding.ASCII.GetString(response); (using System.Text) – Sindre Jan 17 '14 at 19:52
-
-
1Further, you can send a bit complex array $_POST['user'] as: data["user[username]"] = "myUsername"; data["user[password]"] = "myPassword"; – Bimal Poudel Jul 17 '16 at 00:19
-
-
[**Beware of WebClient as slow method**](https://stackoverflow.com/questions/4415443/system-net-webclient-unreasonably-slow) – T.Todua Nov 23 '21 at 07:36
MSDN has a sample.
using System;
using System.IO;
using System.Net;
using System.Text;
namespace Examples.System.Net
{
public class WebRequestPostExample
{
public static void Main()
{
// Create a request using a URL that can receive a post.
WebRequest request = WebRequest.Create("http://www.contoso.com/PostAccepter.aspx");
// Set the Method property of the request to POST.
request.Method = "POST";
// Create POST data and convert it to a byte array.
string postData = "This is a test that posts this string to a Web server.";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Set the ContentType property of the WebRequest.
request.ContentType = "application/x-www-form-urlencoded";
// Set the ContentLength property of the WebRequest.
request.ContentLength = byteArray.Length;
// Get the request stream.
Stream dataStream = request.GetRequestStream();
// Write the data to the request stream.
dataStream.Write(byteArray, 0, byteArray.Length);
// Close the Stream object.
dataStream.Close();
// Get the response.
WebResponse response = request.GetResponse();
// Display the status.
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
// Get the stream containing content returned by the server.
dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Display the content.
Console.WriteLine(responseFromServer);
// Clean up the streams.
reader.Close();
dataStream.Close();
response.Close();
}
}
}

- 23
- 2
- 11

- 73,752
- 17
- 161
- 228
-
1
-
@AnKing there is scope for that to be server limits rather than the client sending it. – Epirocks Oct 12 '20 at 12:52
This is a complete working example of sending/receiving data in JSON format, I used Visual Studio 2013 Express Edition:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web.Script.Serialization;
namespace ConsoleApplication1
{
class Customer
{
public string Name { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
}
public class Program
{
private static readonly HttpClient _Client = new HttpClient();
private static JavaScriptSerializer _Serializer = new JavaScriptSerializer();
static void Main(string[] args)
{
Run().Wait();
}
static async Task Run()
{
string url = "http://www.example.com/api/Customer";
Customer cust = new Customer() { Name = "Example Customer", Address = "Some example address", Phone = "Some phone number" };
var json = _Serializer.Serialize(cust);
var response = await Request(HttpMethod.Post, url, json, new Dictionary<string, string>());
string responseText = await response.Content.ReadAsStringAsync();
List<YourCustomClassModel> serializedResult = _Serializer.Deserialize<List<YourCustomClassModel>>(responseText);
Console.WriteLine(responseText);
Console.ReadLine();
}
/// <summary>
/// Makes an async HTTP Request
/// </summary>
/// <param name="pMethod">Those methods you know: GET, POST, HEAD, etc...</param>
/// <param name="pUrl">Very predictable...</param>
/// <param name="pJsonContent">String data to POST on the server</param>
/// <param name="pHeaders">If you use some kind of Authorization you should use this</param>
/// <returns></returns>
static async Task<HttpResponseMessage> Request(HttpMethod pMethod, string pUrl, string pJsonContent, Dictionary<string, string> pHeaders)
{
var httpRequestMessage = new HttpRequestMessage();
httpRequestMessage.Method = pMethod;
httpRequestMessage.RequestUri = new Uri(pUrl);
foreach (var head in pHeaders)
{
httpRequestMessage.Headers.Add(head.Key, head.Value);
}
switch (pMethod.Method)
{
case "POST":
HttpContent httpContent = new StringContent(pJsonContent, Encoding.UTF8, "application/json");
httpRequestMessage.Content = httpContent;
break;
}
return await _Client.SendAsync(httpRequestMessage);
}
}
}

- 30,738
- 21
- 105
- 131
There are some really good answers on here. Let me post a different way to set your headers with the WebClient(). I will also show you how to set an API key.
var client = new WebClient();
string credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes(userName + ":" + passWord));
client.Headers[HttpRequestHeader.Authorization] = $"Basic {credentials}";
//If you have your data stored in an object serialize it into json to pass to the webclient with Newtonsoft's JsonConvert
var encodedJson = JsonConvert.SerializeObject(newAccount);
client.Headers.Add($"x-api-key:{ApiKey}");
client.Headers.Add("Content-Type:application/json");
try
{
var response = client.UploadString($"{apiurl}", encodedJson);
//if you have a model to deserialize the json into Newtonsoft will help bind the data to the model, this is an extremely useful trick for GET calls when you have a lot of data, you can strongly type a model and dump it into an instance of that class.
Response response1 = JsonConvert.DeserializeObject<Response>(response);

- 395
- 4
- 9
-
Useful, thanks. BTW It looks like the above technique for setting header-properties also works for the older (deprecated?), HttpWebRequest approach. e.g. myReq.Headers[HttpRequestHeader.Authorization] = $"Basic {credentials}"; – Zeek2 Jun 24 '19 at 15:04
Simple (one-liner, no error checking, no wait for response) solution I've found so far:
(new WebClient()).UploadStringAsync(new Uri(Address), dataString);
Use with caution!

- 30,738
- 21
- 105
- 131

- 5,756
- 3
- 39
- 36
-
7That is quite bad. I don't recommend it as there is no error handling of any kind and debugging it is pain. Additionally there already is great answer to this question. – Hooch Sep 25 '17 at 11:24
-
1@Hooch others might be interested in this type of answers, even if it's not the best one. – Mitulát báti Dec 30 '17 at 16:11
-
Agreed, the only context in which this would be useful is code golfing and who golfs in C# ;) – Extragorey May 09 '19 at 03:58
-
I wrote this answer looking for http based logging solution, I guess some other people might find it usefull similarly. – Ohad Cohen Jun 16 '20 at 10:45
-
why (at least in a real life application), a "no error checking", "no wait for response" instruction would be an applicable answer? – Andrew Nov 30 '22 at 18:23
If you like a fluent API you can use Tiny.RestClient. It's available at NuGet.
var client = new TinyRestClient(new HttpClient(), "http://MyAPI.com/api");
// POST
var city = new City() { Name = "Paris", Country = "France" };
// With content
var response = await client.PostRequest("City", city)
.ExecuteAsync<bool>();

- 30,738
- 21
- 105
- 131

- 126
- 1
- 5
This solution uses nothing but standard .NET calls.
Tested:
- In use in an enterprise WPF application. Uses async/await to avoid blocking the UI.
- Compatible with .NET 4.5+.
- Tested with no parameters (requires a "GET" behind the scenes).
- Tested with parameters (requires a "POST" behind the scenes).
- Tested with a standard web page such as Google.
- Tested with an internal Java-based web service.
Reference:
// Add a Reference to the assembly System.Web
Code:
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
private async Task<WebResponse> CallUri(string url, TimeSpan timeout)
{
var uri = new Uri(url);
NameValueCollection rawParameters = HttpUtility.ParseQueryString(uri.Query);
var parameters = new Dictionary<string, string>();
foreach (string p in rawParameters.Keys)
{
parameters[p] = rawParameters[p];
}
var client = new HttpClient { Timeout = timeout };
HttpResponseMessage response;
if (parameters.Count == 0)
{
response = await client.GetAsync(url);
}
else
{
var content = new FormUrlEncodedContent(parameters);
string urlMinusParameters = uri.OriginalString.Split('?')[0]; // Parameters always follow the '?' symbol.
response = await client.PostAsync(urlMinusParameters, content);
}
var responseString = await response.Content.ReadAsStringAsync();
return new WebResponse(response.StatusCode, responseString);
}
private class WebResponse
{
public WebResponse(HttpStatusCode httpStatusCode, string response)
{
this.HttpStatusCode = httpStatusCode;
this.Response = response;
}
public HttpStatusCode HttpStatusCode { get; }
public string Response { get; }
}
To call with no parameters (uses a "GET" behind the scenes):
var timeout = TimeSpan.FromSeconds(300);
WebResponse response = await this.CallUri("http://www.google.com/", timeout);
if (response.HttpStatusCode == HttpStatusCode.OK)
{
Console.Write(response.Response); // Print HTML.
}
To call with parameters (uses a "POST" behind the scenes):
var timeout = TimeSpan.FromSeconds(300);
WebResponse response = await this.CallUri("http://example.com/path/to/page?name=ferret&color=purple", timeout);
if (response.HttpStatusCode == HttpStatusCode.OK)
{
Console.Write(response.Response); // Print HTML.
}

- 30,738
- 21
- 105
- 131

- 76,540
- 58
- 260
- 305
When using the Windows.Web.Http namespace, for POST instead of FormUrlEncodedContent, we write HttpFormUrlEncodedContent. Also the response is type of HttpResponseMessage. The rest is as Evan Mulawski wrote down.

- 30,738
- 21
- 105
- 131

- 71
- 1
- 7
- 19
Yet another way of doing it:
using (HttpClient httpClient = new HttpClient())
using (MultipartFormDataContent form = new MultipartFormDataContent())
{
form.Add(new StringContent(param1), "param1");
form.Add(new StringContent(param2), "param2");
using (HttpResponseMessage response = await httpClient.PostAsync(url, form))
{
response.EnsureSuccessStatusCode();
string res = await response.Content.ReadAsStringAsync();
return res;
}
}
This way you can easily post a stream.

- 1,044
- 1
- 12
- 24
-
1An explanation would be in order. E.g., how is it different? What are the pros and cons compared to some other answers? From [the Help Center](https://stackoverflow.com/help/promotion): *"...always explain why the solution you're presenting is appropriate and how it works"*. Please respond by [editing (changing) your answer](https://stackoverflow.com/posts/63488415/edit), not here in comments (***without*** "Edit:", "Update:", or similar - the answer should appear as if it was written today). – Peter Mortensen Jul 11 '22 at 21:22
c# .Net
using System.Net.Http;
private static readonly HttpClient httpClient = new HttpClient();
//POST
var values = new Object();
values[0] = "Value1";
values[2] = "Value2";
values[n] = "ValueN";
var content = new FormUrlEncodedContent(values);
var response = await httpClient.PostAsync("URL", content);
var responseString = await response.Content.ReadAsStringAsync();
//GET
var response = await httpClient.GetStringAsync("URL");

- 59
- 4
Why is this not totally trivial? Doing the request is not and especially not dealing with the results. And it seems like there are some .NET bugs involved as well - see Bug in HttpClient.GetAsync should throw WebException, not TaskCanceledException
I ended up with this code:
static async Task<(bool Success, WebExceptionStatus WebExceptionStatus, HttpStatusCode? HttpStatusCode, string ResponseAsString)> HttpRequestAsync(HttpClient httpClient, string url, string postBuffer = null, CancellationTokenSource cts = null) {
try {
HttpResponseMessage resp = null;
if (postBuffer is null) {
resp = cts is null ? await httpClient.GetAsync(url) : await httpClient.GetAsync(url, cts.Token);
} else {
using (var httpContent = new StringContent(postBuffer)) {
resp = cts is null ? await httpClient.PostAsync(url, httpContent) : await httpClient.PostAsync(url, httpContent, cts.Token);
}
}
var respString = await resp.Content.ReadAsStringAsync();
return (resp.IsSuccessStatusCode, WebExceptionStatus.Success, resp.StatusCode, respString);
} catch (WebException ex) {
WebExceptionStatus status = ex.Status;
if (status == WebExceptionStatus.ProtocolError) {
// Get HttpWebResponse so that you can check the HTTP status code.
using (HttpWebResponse httpResponse = (HttpWebResponse)ex.Response) {
return (false, status, httpResponse.StatusCode, httpResponse.StatusDescription);
}
} else {
return (false, status, null, ex.ToString());
}
// https://devblogs.microsoft.com/dotnet/net-5-new-networking-improvements/
} catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException) {
return (false, ex.ToString(), null, WebExceptionStatus.Timeout);
} catch (TaskCanceledException ex) {
return (false, ex.ToString(), null, WebExceptionStatus.RequestCanceled);
} catch (Exception ex) {
return (false, WebExceptionStatus.UnknownError, null, ex.ToString());
}
}
This will do a GET or POST depending on if postBuffer
is null or not.
If Success is true, the response will then be in ResponseAsString
.
If Success is false, you can check WebExceptionStatus
, HttpStatusCode
and ResponseAsString
to try to see what went wrong.

- 30,738
- 21
- 105
- 131

- 17,260
- 17
- 99
- 173
-
1I have been working on this for too long. Soooo far from trivial... in Java I need about 6-8 lines. – Danimal111 Jan 27 '21 at 23:33
-
1seems like things are getting better see https://devblogs.microsoft.com/dotnet/net-5-new-networking-improvements/ – kofifus Jan 28 '21 at 00:50
This an example of an HTTPS web request. You can echo any results in a PHP script. Finally, a PHP echo string will be shown as an alert on the C# client side.
string url = "https://mydomain.ir/test1.php";
StringBuilder postData = new StringBuilder();
postData.Append(String.Format("{0}={1}&", HttpUtility.HtmlEncode("username"), HttpUtility.HtmlEncode("ali")));
postData.Append(String.Format("{0}={1}", HttpUtility.HtmlEncode("password"), HttpUtility.HtmlEncode("123456789")));
StringContent myStringContent = new StringContent(postData.ToString(), Encoding.UTF8, "application/x-www-form-urlencoded");
HttpClient client = new HttpClient();
HttpResponseMessage message = client.PostAsync(url, myStringContent).GetAwaiter().GetResult();
string responseContent = message.Content.ReadAsStringAsync().GetAwaiter().GetResult();
DisplayAlert("Your Feedback", responseContent, "OK");
PHP server side:
<?php
if (isset($_POST["username"]) && $_POST["username"] == "ali") {
echo "Yes, hi Ali";
}
else {
echo "No, where is Ali?";
}
?>
The result will be "Yes, hi Ali".
This is for Xamarin Forms. For a C# .NET application, replace DisplayAlert with:
MessageBox.show(responseContent);

- 30,738
- 21
- 105
- 131
If you need to POST a JSON message body, you could use the following. Assuming you have a class instance named m.
string jsonMessage = JsonConvert.SerializeObject(m);
// Make POST call
using (HttpClient client = new HttpClient())
{
HttpRequestMessage requestMessage = new
HttpRequestMessage(HttpMethod.Post, "<url here>");
requestMessage.Content = new StringContent(jsonMessage, Encoding.UTF8, "application/json");
HttpResponseMessage response = client.SendAsync(requestMessage).Result;
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
// Do something here
}
}

- 30,738
- 21
- 105
- 131

- 370
- 2
- 9
In .NET Core you can make a POST call with the following code. Here I added some extra features to this code, so you can make your code work behind a proxy and with network credentials if any.
Also here I mention that you can change the encoding of your message.
HttpClient client = GetHttpClient(_config);
if (headers != null)
{
foreach (var header in headers)
{
client.DefaultRequestHeaders.TryAddWithoutValidation(header.Key, header.Value);
}
}
client.BaseAddress = new Uri(baseAddress);
Encoding encoding = Encoding.UTF8;
var result = await client.PostAsync(url, new StringContent(body, encoding, "application/json")).ConfigureAwait(false);
if (result.IsSuccessStatusCode)
{
return new RequestResponse { severity = "Success", httpResponse = result.Content.ReadAsStringAsync().Result, StatusCode = result.StatusCode };
}
else
{
return new RequestResponse { severity = "failure", httpResponse = result.Content.ReadAsStringAsync().Result, StatusCode = result.StatusCode };
}
public HttpClient GetHttpClient(IConfiguration _config)
{
bool ProxyEnable = Convert.ToBoolean(_config["GlobalSettings:ProxyEnable"]);
HttpClient client = null;
if (!ProxyEnable)
{
client = new HttpClient();
}
else
{
string ProxyURL = _config["GlobalSettings:ProxyURL"];
string ProxyUserName = _config["GlobalSettings:ProxyUserName"];
string ProxyPassword = _config["GlobalSettings:ProxyPassword"];
string[] ExceptionURL = _config["GlobalSettings:ExceptionURL"].Split(';');
bool BypassProxyOnLocal = Convert.ToBoolean(_config["GlobalSettings:BypassProxyOnLocal"]);
bool UseDefaultCredentials = Convert.ToBoolean(_config["GlobalSettings:UseDefaultCredentials"]);
WebProxy proxy = new WebProxy
{
Address = new Uri(ProxyURL),
BypassProxyOnLocal = BypassProxyOnLocal,
UseDefaultCredentials = UseDefaultCredentials,
BypassList = ExceptionURL,
Credentials = new NetworkCredential(ProxyUserName, ProxyPassword)
};
HttpClientHandler handler = new HttpClientHandler { Proxy = proxy };
client = new HttpClient(handler, true);
}
return client;
}

- 30,738
- 21
- 105
- 131

- 59
- 1
- 4
Very nice different approaches given in answers. Sharing one more approach. This is tested with .Net 6.
- Create a Proxy class for you API functionality
- inject it or create instance of it when you want it.
Proxy class:
public class ApiProxy
{
private readonly string _baseUrl;
public ApiProxy(string baseUrl)
{
_baseUrl = baseUrl;
}
public async Task<List<ResponseClass>> CallAPI(RequestClass requestObject)
{
try
{
string endpoint = $"{baseUrl}/your_api_endpoint";
var _client = new HttpClient();
string token = "your bearer token";
string requestBodyString = System.Text.Json.JsonSerializer.Serialize(requestObject);
var request = new HttpRequestMessage
{
Content = new StringContent(requestBodyString, Encoding.UTF8, "application/json"),
Method = HttpMethod.Post,
RequestUri = new Uri(endpoint)
};
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
request.Headers.Add("correlationId", correlationId);
var result = await _client.SendAsync(request);
var content = result.Content.ReadAsStringAsync().Result;
var response = JsonConvert.DeserializeObject<List<ResponseClass>>(content);
return response;
}
catch (Exception ex)
{
throw;
}
}
}
Create instance of it or inject it via constructor injection when you need to call in Consumer class:
await apiProxy.CallAPI(requestObject);
Happy coding !!

- 1,716
- 6
- 27
- 41
Here's what I use in .NET 4.8 to make an HTTP POST request. With this code, one can send multiple POST requests at a time asynchronously.
At the end of each request an event is raised. And also at the end of all requests another event is raised.
The one below is the core class:
Imports System.ComponentModel
Imports System.Text.RegularExpressions
Imports System.Timers
Imports System.Windows.Forms
Imports AeonLabs
Imports AeonLabs.Environment
Imports Newtonsoft.Json
Public Class HttpDataCore
Public Property url As String
Public Property state As New environmentVarsCore
Public Property errorMessage As String = ""
Public Property statusMessage As String
Public Property threadCount As Integer = 25
Public Property numberOfRetryAttempts = 5
Public Property queue As List(Of _queue_data_struct)
Public Property queueBWorker As Integer() ' has the size of threadCount
Public Property queueLock As New Object
Public Property retryAttempts As New _retry_attempts
Public Property dataStatistics As List(Of _data_statistics)
Public Property loadingCounter As Integer
Public Property CompletionPercentage As Integer ' value range 0-100
Public Property IsBusy As Boolean
Public Structure _queue_data_struct
Dim vars As Dictionary(Of String, String)
Dim filenameOrSavePath As String ' full address file name or full adress folder path
Dim misc As Dictionary(Of String, String)
Dim status As Integer ' -1 - completed; 0- not sent yet; 1-already sent / processing
End Structure
Public Structure _retry_attempts
Dim counter As Integer
Dim pattern As Integer
Dim previousPattern As Integer
Dim errorMessage As String
End Structure
Public Structure _data_statistics
Dim filesize As Double
Dim bytesSentReceived As Double
Dim speed As Double
End Structure
Public WithEvents RestartQueueTimer As New Timers.Timer
Public bwDataRequest() As BackgroundWorker
Public Event requestCompleted(sender As Object, requestData As String) 'TODO add misc vars
Private sendToQueue As Boolean
Public Sub New(ByVal Optional _state As environmentVarsCore = Nothing, ByVal Optional _url As String = "")
queue = New List(Of _queue_data_struct)
dataStatistics = New List(Of _data_statistics)
loadingCounter = 0
sendToQueue = False
If _state IsNot Nothing AndAlso _url.Equals("") Then
url = _state.ServerBaseAddr & _state.ApiServerAddrPath
ElseIf Not _url.Equals("") Then
url = _url
Else
Throw New System.Exception("Initialization err: state and url cannot be both null at same time")
End If
If _state IsNot Nothing Then
state = _state
End If
End Sub
Public Sub loadQueue(ByVal vars As Dictionary(Of String, String), ByVal Optional misc As Dictionary(Of String, String) = Nothing, ByVal Optional filenameOrSavePath As String = Nothing)
Dim queueItem As New _queue_data_struct
queueItem.vars = New Dictionary(Of String, String)
queueItem.misc = New Dictionary(Of String, String)
queueItem.vars = vars
queueItem.status = 0
queueItem.misc = misc
queueItem.filenameOrSavePath = filenameOrSavePath
queue.Add(queueItem)
End Sub
Public Sub clearQueue()
loadingCounter = 0
queue = New List(Of _queue_data_struct)
End Sub
Public Sub startRequest()
If bwDataRequest(0) Is Nothing Then
Throw New Exception("You need to call initialze first")
Exit Sub
End If
'startSendQueue()
IsBusy = True
AddHandler RestartQueueTimer.Elapsed, New ElapsedEventHandler(AddressOf QueueTimerTick)
With RestartQueueTimer
.Enabled = True
.Interval = 500
.Start()
End With
End Sub
Private Sub QueueTimerTick(ByVal sender As Object, ByVal e As ElapsedEventArgs)
If QueuesToComplete(queue).Equals(0) And QueuesToSend(queue).Equals(0) Then
RestartQueueTimer.Stop()
queue = New List(Of _queue_data_struct)
RaiseEvent requestCompleted(Me, Nothing)
IsBusy = False
Exit Sub
End If
If retryAttempts.counter >= numberOfRetryAttempts Then 'ToDo a retry number of attempts before quits
Threading.Thread.CurrentThread.CurrentUICulture = Globalization.CultureInfo.GetCultureInfo(state.currentLang)
Dim MsgBox As messageBoxForm
MsgBox = New messageBoxForm(retryAttempts.errorMessage & ". " & My.Resources.strings.tryAgain & " ?", My.Resources.strings.question, MessageBoxButtons.YesNo, MessageBoxIcon.Question)
If MsgBox.ShowDialog() = DialogResult.Yes Then
Dim retry As _retry_attempts
With retry
.counter = 0
.previousPattern = -1
.pattern = 0
.errorMessage = ""
End With
retryAttempts = retry
startSendQueue()
Else
RestartQueueTimer.Stop()
queue = New List(Of _queue_data_struct)
RaiseEvent requestCompleted(Me, Nothing)
IsBusy = False
Exit Sub
End If
Exit Sub
ElseIf Not sendToQueue And QueuesToSend(queue) > 0 Then
startSendQueue()
End If
End Sub
Private Sub startSendQueue()
sendToQueue = True
While QueuesToSend(queue) > 0
For shtIndex = 0 To threadCount
For i = 0 To queue.Count - 1
If Not bwDataRequest(shtIndex).IsBusy Then
SyncLock queueLock
If queue.ElementAt(i).status.Equals(0) Then
Dim data As New _queue_data_struct
data.vars = queue.ElementAt(i).vars
data.status = 1
data.misc = queue.ElementAt(i).misc
data.filenameOrSavePath = queue.ElementAt(i).filenameOrSavePath
queue(i) = data
queueBWorker(shtIndex) = i
dataStatistics(shtIndex) = (New _data_statistics)
bwDataRequest(shtIndex).RunWorkerAsync(queue(i))
Threading.Thread.Sleep(50)
End If
End SyncLock
End If
Next i
Next shtIndex
End While
sendToQueue = False
End Sub
Public Function QueuesToSend(queue As List(Of _queue_data_struct)) As Integer
Dim counter As Integer = 0
For i = 0 To queue.Count - 1
If queue(i).status.Equals(0) Then
counter += 1
End If
Next i
Return counter
End Function
Public Function QueuesToComplete(queue As List(Of _queue_data_struct)) As Integer
Dim counter As Integer = 0
For i = 0 To queue.Count - 1
If queue(i).status.Equals(1) Then
counter += 1
End If
Next i
Return counter
End Function
Public Function QueuesMultiHash(queue As List(Of _queue_data_struct)) As Integer
Dim counter As Integer = 0
For i = 0 To queue.Count - 1
If queue(i).status.Equals(1) Then
counter += i
End If
Next i
Return counter
End Function
Public Function IsBase64String(ByVal s As String) As Boolean
s = s.Trim()
Return (s.Length Mod 4 = 0) AndAlso Regex.IsMatch(s, "^[a-zA-Z0-9\+/]*={0,3}$", RegexOptions.None)
End Function
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Public Function ConvertDataToArray(key As String, fields As String(), response As String) As Dictionary(Of String, List(Of String))
If GetMessage(response).Equals("1001") Then
Threading.Thread.CurrentThread.CurrentUICulture = Globalization.CultureInfo.GetCultureInfo(state.currentLang)
errorMessage = "{'error':true,'message':'" & My.Resources.strings.errorNoRecordsFound & "'}"
Return Nothing
End If
Try
Dim jsonResult = JsonConvert.DeserializeObject(Of Dictionary(Of String, Object))(response)
If jsonResult.ContainsKey(key) Then
If Not jsonResult.Item(key).item(0).Count.Equals(fields.Length) Then
Threading.Thread.CurrentThread.CurrentUICulture = Globalization.CultureInfo.GetCultureInfo(state.currentLang)
errorMessage = "{'error':true,'message':'" & My.Resources.strings.JsonFieldsMismatch & ". table(" & key & "'}"
Return Nothing
Else
Dim results = New Dictionary(Of String, List(Of String))
For k = 0 To fields.Length - 1
Dim fieldValues As List(Of String) = New List(Of String)
For i = 0 To jsonResult.Item(key).Count - 1
fieldValues.Add(jsonResult.Item(key).item(i).item(k).ToString)
Next i
results.Add(fields(k), fieldValues)
Next k
Return results
End If
Else
Threading.Thread.CurrentThread.CurrentUICulture = Globalization.CultureInfo.GetCultureInfo(state.currentLang)
errorMessage = "{'error':true,'message':'" & My.Resources.strings.JsonkeyNotFound & " (" & key & "'}"
Return Nothing
End If
Catch ex As Exception
errorMessage = "{'error':true,'message':'" & ex.ToString & "'}"
errorMessage = ex.ToString
Return Nothing
End Try
End Function
End Class
the AeonLabs.Envoriment
is a class with a collection or fields and properties.
And the one bellow is for making a POST request:
Imports System.ComponentModel
Imports System.IO
Imports System.Net
Imports System.Text
Imports System.Web
Imports System.Web.Script.Serialization
Imports System.Windows.Forms
Imports AeonLabs.Environment
Imports AeonLabs.Security
Public Class HttpDataPostData
Inherits HttpDataCore
Public Event updateProgress(sender As Object, misc As Dictionary(Of String, String))
Public Event dataArrived(sender As Object, requestData As String, misc As Dictionary(Of String, String))
Public Sub New(ByVal Optional _state As environmentVarsCore = Nothing, ByVal Optional _url As String = "")
MyBase.New(_state, _url)
End Sub
Public Sub initialize(ByVal Optional _threadCount As Integer = 0)
If Not _threadCount.Equals(0) Then
threadCount = _threadCount
End If
ReDim bwDataRequest(threadCount)
ReDim queueBWorker(threadCount)
For shtIndex = 0 To threadCount
dataStatistics.Add(New _data_statistics)
bwDataRequest(shtIndex) = New System.ComponentModel.BackgroundWorker
bwDataRequest(shtIndex).WorkerReportsProgress = True
bwDataRequest(shtIndex).WorkerSupportsCancellation = True
AddHandler bwDataRequest(shtIndex).DoWork, AddressOf bwDataRequest_DoWork
AddHandler bwDataRequest(shtIndex).RunWorkerCompleted, AddressOf bwDataRequest_RunWorkerCompleted
Next shtIndex
Dim retry As _retry_attempts
With retry
.counter = 0
.previousPattern = -1
.pattern = 0
.errorMessage = ""
End With
retryAttempts = retry
End Sub
Private Sub bwDataRequest_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs)
' Find out the Index of the bWorker that called this DoWork (could be cleaner, I know)
Dim Y As Integer
Dim Index As Integer = Nothing
For Y = 0 To UBound(bwDataRequest)
If sender.Equals(bwDataRequest(Y)) Then
Index = Y
Exit For
End If
Next Y
Dim queue As _queue_data_struct
queue = e.Argument
Dim vars As New Dictionary(Of String, String)
vars = queue.vars
'TODO translation need to be local
If Not System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable() Then
Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo(state.currentLang)
e.Result = "{'error':true,'message':'" & My.Resources.strings.errorNoNetwork & "'}"
Exit Sub
End If
If vars Is Nothing Then
e.Result = "{'error':true,'message':'missconfiguration vars'}"
Exit Sub
End If
If Not vars.ContainsKey("id") Then
vars.Add("id", state.userId)
End If
If Not vars.ContainsKey("pid") Then
Dim appId As New FingerPrint
vars.Add("pid", appId.Value)
End If
If Not vars.ContainsKey("language") Then
vars.Add("language", state.currentLang)
End If
If Not vars.ContainsKey("origin") Then
vars.Add("origin", state.softwareAccessMode)
End If
Dim serializer As New JavaScriptSerializer()
Dim json As String = serializer.Serialize(vars)
Dim encryption As New AesCipher(state)
Dim encrypted As String = HttpUtility.UrlEncode(encryption.encrypt(json))
Dim PostData = "origin=" & state.softwareAccessMode & "&data=" & encrypted
Dim request As WebRequest = WebRequest.Create(url)
Dim responseFromServer As String = ""
Dim decrypted As String = ""
request.Method = "POST"
Dim byteArray As Byte() = Encoding.UTF8.GetBytes(PostData)
request.ContentType = "application/x-www-form-urlencoded"
request.Headers.Add("Authorization", state.ApiHttpHeaderToken & "-" & state.softwareAccessMode)
request.ContentLength = byteArray.Length
Try
Dim dataStream As Stream = request.GetRequestStream()
dataStream.Write(byteArray, 0, byteArray.Length)
dataStream.Close()
Dim response As HttpWebResponse = CType(request.GetResponse(), HttpWebResponse)
dataStream = response.GetResponseStream()
Dim reader As New StreamReader(dataStream)
responseFromServer = reader.ReadToEnd()
reader.Close()
dataStream.Close()
response.Close()
If response.StatusCode = HttpStatusCode.Accepted Or response.StatusCode = 200 Then
If IsBase64String(responseFromServer) And Not responseFromServer.Equals("") Then
decrypted = encryption.decrypt((responseFromServer)).Replace("\'", "'")
Else
Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo(state.currentLang)
decrypted = "{'error':true,'encrypted':false,'message':'" & My.Resources.strings.contactingCommServer & " |" & responseFromServer & "|'}"
End If
Else
Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo(state.currentLang)
decrypted = "{'error':true,'message':'" & My.Resources.strings.contactingCommServer & " (" & response.StatusCode & ")', 'statuscode':'" & response.StatusCode & "'}"
End If
Catch ex As Exception
Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo(state.currentLang)
decrypted = "{'error':true,'message':'" & My.Resources.strings.contactingCommServer & " (" & ex.Message.ToString.Replace("'", "\'") & ")'}"
End Try
e.Result = decrypted.Replace("\'", "'")
End Sub
Private Sub bwDataRequest_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs)
' Find out the Index of the bWorker that called this DoWork (could be cleaner, I know)
Dim Y As Integer
Dim Index As Integer = Nothing
Dim data As New _queue_data_struct
For Y = 0 To UBound(bwDataRequest)
If sender.Equals(bwDataRequest(Y)) Then
Index = Y
Exit For
End If
Next Y
If IsResponseOk(e.Result, "statuscode") Then
data = New _queue_data_struct
data = queue(queueBWorker(Index))
data.status = 0 're queue the file
SyncLock queueLock
queue(queueBWorker(Index)) = data
End SyncLock
Dim errorMsg As String = GetMessage(e.Result)
Dim retry As _retry_attempts
With retry
.counter = retryAttempts.counter
.previousPattern = retryAttempts.previousPattern
.pattern = retryAttempts.pattern
.errorMessage = retryAttempts.errorMessage
End With
retry.errorMessage = If(retryAttempts.errorMessage.IndexOf(errorMsg) > -1, retryAttempts.errorMessage, retryAttempts.errorMessage & System.Environment.NewLine & errorMsg)
retry.pattern = QueuesMultiHash(queue)
If retry.previousPattern.Equals(retry.pattern) Then
retry.counter += 1
Else
retry.counter = 1
retry.previousPattern = retryAttempts.pattern
End If
retryAttempts = retry
Exit Sub
End If
data = New _queue_data_struct
data = queue(queueBWorker(Index))
data.status = -1 'completed sucessfully status
SyncLock queueLock
queue(queueBWorker(Index)) = data
End SyncLock
loadingCounter += 1
CompletionPercentage = (loadingCounter / queue.Count) * 100
statusMessage = "Loading data from the cloud..."
RaiseEvent updateProgress(Me, queue(queueBWorker(Index)).misc)
RaiseEvent dataArrived(Me, e.Result, queue(queueBWorker(Index)).misc)
End Sub
End Class
The Aoenlabs.Security is a class for sending POST data encrypted using standard encryption algorithms.

- 30,738
- 21
- 105
- 131

- 1,714
- 1
- 13
- 23
-
1
-
@KVN and you are correct. And you can convert easily my code into C# with a click of a button – Miguel Tomás Jan 05 '23 at 22:30