352

Here's the code I'm using:

// create a request
HttpWebRequest request = (HttpWebRequest)
WebRequest.Create(url); request.KeepAlive = false;
request.ProtocolVersion = HttpVersion.Version10;
request.Method = "POST";
// turn our request string into a byte stream
byte[] postBytes = Encoding.UTF8.GetBytes(json);
// this is important - make sure you specify type this way
request.ContentType = "application/json; charset=UTF-8";
request.Accept = "application/json";
request.ContentLength = postBytes.Length;
request.CookieContainer = Cookies;
request.UserAgent = currentUserAgent;
Stream requestStream = request.GetRequestStream();
// now send it
requestStream.Write(postBytes, 0, postBytes.Length);
requestStream.Close();
// grab te response and print it out to the console along with the status code
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
string result;
using (StreamReader rdr = new StreamReader(response.GetResponseStream()))
{
 result = rdr.ReadToEnd();
}
return result;

When I'm running this, I'm always getting 500 internal server error.

What am I doing wrong?

jww
103k104 gold badges451 silver badges963 bronze badges
asked Feb 4, 2012 at 23:46
4
  • 3
    First, make sure that the data you post is what the server expects. Commented Feb 4, 2012 at 23:55
  • actually, it looks like I was posting invalid data... Commented Feb 4, 2012 at 23:57
  • For ease of work you can add json library to your visual studio too Commented Apr 21, 2013 at 11:49
  • 3
    @Arsen - The server should not crash with malformed data. File a bug report. Commented Sep 9, 2018 at 5:27

16 Answers 16

498

The way I do it and is working is:

var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://url");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
 string json = "{\"user\":\"test\"," +
 "\"password\":\"bla\"}";
 streamWriter.Write(json);
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
 var result = streamReader.ReadToEnd();
}

I wrote a library to perform this task in a simpler way, it is here: https://github.com/ademargomes/JsonRequest

Muhammad Dyas Yaskur
8,30811 gold badges62 silver badges89 bronze badges
answered Apr 5, 2012 at 11:15
13
  • 3
    I think the json string line should be: string json = "{\"user\":\"test\"," + "\"password\":\"bla\"}"; It looks like you are missing a \ Commented Feb 26, 2013 at 17:00
  • 3
    Always use "application/json" (unless for some other reason text/json is needed for example: entwicklungsgedanken.de/2008/06/06/…). Creding goes to: stackoverflow.com/questions/477816/…. Commented May 9, 2015 at 21:43
  • 39
    I would've thought the streamWriter.Flush(); and streamWriter.Close(); is not necessary as you are inside a using block. At the end of the using block, stream writer will close anyway. Commented Jan 19, 2016 at 0:04
  • 1
    Don't build JSON manually. It is easy to make mistakes that allow for JSON injection. Commented Feb 27, 2017 at 14:08
  • 9
    @user3772108 See stackoverflow.com/a/16380064/2279059. Use a JSON library, such as Newtonsoft JSON.Net, and render the JSON string from an object, or use serialization. I understand that this was omitted here for simplicity (although the simplicity gain is minimal), but formatting structured data strings (JSON, XML, ...) is too dangerous to do it even in trivial scenarios and to encourage people to copy such code. Commented Oct 25, 2017 at 8:37
174

Ademar's solution can be improved by leveraging JavaScriptSerializer's Serialize method to provide implicit conversion of the object to JSON.

Additionally, it is possible to leverage the using statement's default functionality in order to omit explicitly calling Flush and Close.

var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://url");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
 string json = new JavaScriptSerializer().Serialize(new
 {
 user = "Foo",
 password = "Baz"
 });
 streamWriter.Write(json);
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
 var result = streamReader.ReadToEnd();
}
answered May 4, 2013 at 23:56
7
  • 1
    What's the difference between this and the above code, am I missing something? Commented Jun 24, 2014 at 19:07
  • 18
    This uses the JavaScriptSerializer's Serialize method to create valid JSON instead of hand-crafting it. Commented Jun 24, 2014 at 22:26
  • See Jean F's answer below - should be a comment. Take care with the content type application/json is correct. Commented Jun 2, 2015 at 2:30
  • 3
    @LuzanBaral you just need an assembly: System.Web.Extensions Commented May 24, 2017 at 11:58
  • 2
    JavaScriptSerializer not works in dot net core. alternative is using Newtonsoft.Json and calling like: ` string json = JsonConvert.SerializeObject(new {Username="Blahblah"});` Commented Dec 2, 2021 at 6:16
138

The HttpClient type is a newer implementation than the WebClient and HttpWebRequest. Both the WebClient and WebRequest have been marked as obsolete. [1]

You can simply use the following lines.

string myJson = "{'Username': 'myusername','Password':'pass'}";
using (var client = new HttpClient())
{
 var response = await client.PostAsync(
 "http://yourUrl", 
 new StringContent(myJson, Encoding.UTF8, "application/json"));
}

When you need your HttpClient more than once it's recommended to only create one instance and reuse it or use the new HttpClientFactory. [2]

For FTP, since HttpClient doesn't support it, we recommend using a third-party library.

@learn.microsoft.com [3]


Since dotnet core 3.1 you can use the JsonSerializer from System.Text.Json to create your json string.

string myJson = JsonSerializer.Serialize(credentialsObj);
answered Mar 13, 2018 at 22:25
2
  • 9
    A little note on HttpClient, the general consensus is that you should not dispose it. Even it implements IDisposable the object is Thread-Safe and meant to be reused. stackoverflow.com/questions/15705092/… Commented Nov 14, 2018 at 23:07
  • 1
    @JeanF. Hey Thanks for the input. As I have allready noted you should only create one instance or use the HttpClientFactory. I did not read all answers in the linked issue but I think it needs updating as it doesn't mention the factory. Commented Nov 15, 2018 at 8:03
38

Further to Sean's post, it isn't necessary to nest the using statements. By using the StreamWriter it will be flushed and closed at the end of the block so no need to explicitly call the Flush() and Close() methods:

var request = (HttpWebRequest)WebRequest.Create("http://url");
request.ContentType = "application/json";
request.Method = "POST";
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
 string json = new JavaScriptSerializer().Serialize(new
 {
 user = "Foo",
 password = "Baz"
 });
 streamWriter.Write(json);
}
var response = (HttpWebResponse)request.GetResponse();
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
 var result = streamReader.ReadToEnd();
}
lynn
10.9k48 silver badges81 bronze badges
answered Mar 13, 2014 at 2:12
3
  • 1
    now this answer and Sean Anderson's answer are exactly the same, as Sean has edited his post. Commented Apr 8, 2018 at 2:55
  • Hey this is so great.Thanks.But how are we going to pass data if we have child nodes on our json? Commented Jun 26, 2019 at 5:09
  • 1
    The serializer can handle child nodes in json - you just have to provide it a valid json object. Commented Jun 26, 2019 at 10:34
16

If you need to call is asynchronously then use

var request = HttpWebRequest.Create("http://www.maplegraphservices.com/tokkri/webservices/updateProfile.php?oldEmailID=" + App.currentUser.email) as HttpWebRequest;
 request.Method = "POST";
 request.ContentType = "text/json";
 request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);
private void GetRequestStreamCallback(IAsyncResult asynchronousResult)
 {
 HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
 // End the stream request operation
 Stream postStream = request.EndGetRequestStream(asynchronousResult);
 // Create the post data
 string postData = JsonConvert.SerializeObject(edit).ToString();
 byte[] byteArray = Encoding.UTF8.GetBytes(postData);
 postStream.Write(byteArray, 0, byteArray.Length);
 postStream.Close();
 //Start the web request
 request.BeginGetResponse(new AsyncCallback(GetResponceStreamCallback), request);
 }
 void GetResponceStreamCallback(IAsyncResult callbackResult)
 {
 HttpWebRequest request = (HttpWebRequest)callbackResult.AsyncState;
 HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(callbackResult);
 using (StreamReader httpWebStreamReader = new StreamReader(response.GetResponseStream()))
 {
 string result = httpWebStreamReader.ReadToEnd();
 stat.Text = result;
 }
 }
answered Jan 29, 2014 at 21:54
2
  • 3
    Thanks for posting this solution Vivek. In our scenario we tried another solution in this post, and wound up seeing System.Threading exceptions in our application, due to what I assume were synchronous posts blocking threads. Your code solved our problem. Commented Nov 22, 2016 at 16:02
  • Note that you probably don't have to convert to bytes. You should be able to do postStream.Write(postData); - and depending on the API, might have to use a request.ContentType = "application/json"; instead of text/json. Commented Apr 22, 2020 at 5:19
14

I recently came up with a much simpler way to post a JSON, with the additional step of converting from a model in my app. Note that you have to make the model [JsonObject] for your controller to get the values and do the conversion.

Request:

 var model = new MyModel(); 
 using (var client = new HttpClient())
 {
 var uri = new Uri("XXXXXXXXX"); 
 var json = new JavaScriptSerializer().Serialize(model);
 var stringContent = new StringContent(json, Encoding.UTF8, "application/json");
 var response = await client.PutAsync(uri,stringContent).Result;
 // ...
 }

Model:

[JsonObject]
[Serializable]
public class MyModel
{
 public Decimal Value { get; set; }
 public string Project { get; set; }
 public string FilePath { get; set; }
 public string FileName { get; set; }
}

Server side:

[HttpPut] 
public async Task<HttpResponseMessage> PutApi([FromBody]MyModel model)
{
 // ...
}
ggorlen
59k8 gold badges118 silver badges170 bronze badges
answered Jan 20, 2017 at 6:46
13

Take care of the Content-Type you are using :

application/json

Sources :

RFC4627

Other post

answered Mar 27, 2014 at 3:07
11

Up to .Net 4.5.1 this option can work:

using (var client = new HttpClient())
{
 client.BaseAddress = new Uri("http://localhost:9000/");
 client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
 var foo = new User
 {
 user = "Foo",
 password = "Baz"
 }
 await client.PostAsJsonAsync("users/add", foo);
}
radrow
7,3534 gold badges34 silver badges67 bronze badges
answered Sep 26, 2016 at 11:29
1
9

WARNING! I have a very strong view on this subject.

.NET’s existing web clients are not developer friendly! WebRequest & WebClient are prime examples of "how to frustrate a developer". They are verbose & complicated to work with; when all you want to do is a simple Post request in C#. HttpClient goes some way in addressing these issues, but it still falls short. On top of that Microsoft’s documentation is bad ... really bad; unless you want to sift through pages and pages of technical blurb.

Open-source to the rescue. There are three excellent open-source, free NuGet libraries as alternatives. Thank goodness! These are all well supported, documented and yes, easy - correction...super easy - to work with.

There is not much between them, but I would give ServiceStack.Text the slight edge ...

  • Github stars are roughly the same.
  • Open Issues & importantly how quickly any issues closed down? ServiceStack takes the award here for the fastest issue resolution & no open issues.
  • Documentation? All have great documentation; however, ServiceStack takes it to the next level & is known for its ‘Golden standard’ for documentation.

Ok - so what does a Post Request in JSON look like within ServiceStack.Text?

var response = "http://example.org/login"
 .PostJsonToUrl(new Login { Username="admin", Password="mypassword" });

That is one line of code. Concise & easy! Compare the above to .NET’s Http libraries.

answered Sep 7, 2019 at 12:51
3
  • It is a crime that it is as hard as it is to do simple REST calls in .net. What takes me a short time in Javascript took a large chunk of the day to figure out in c# and there were like a dozen different opinions on the right way and none of them worked for me? RestSharp finally saved the day - but I had to get past their incomplete docs. Commented Aug 11, 2021 at 4:43
  • I agree with this sentiment. I have a working API call in Postman, but trying to recreate it in .NET 8.0 makes my want to throw my keyboard through the monitor. Even without using Postman, Curl works too. Commented Sep 21, 2024 at 21:24
  • "On top of that Microsoft’s documentation is bad ... really bad; unless you want to sift through pages and pages of technical blurb.".............I thought I was going mad. I wanted to send a very simple POST request in JSON - holy smokes it was a struggle to get through the docs to accomplish this - it felt almost Herculean. I would have to restructure MSFT docs in order to do this. Commented Oct 2, 2024 at 20:13
4

Some different and clean way to achieve this is by using HttpClient like this:

public async Task<HttpResponseMessage> PostResult(string url, ResultObject resultObject)
{
 using (var client = new HttpClient())
 {
 HttpResponseMessage response = new HttpResponseMessage();
 try
 {
 response = await client.PostAsJsonAsync(url, resultObject);
 }
 catch (Exception ex)
 {
 throw ex
 }
 return response;
 }
}
answered Jun 1, 2017 at 7:09
4
  • 4
    Helpful, however PostAsJsonAsync is no longer available since .NET 4.5.2. Use PostAsync instead. More here Commented Jul 17, 2017 at 19:02
  • HttpClient generally shouldn't be used in a using statement like this Commented Oct 31, 2018 at 14:04
  • I think it implements IDisposable interface for a reason Commented Nov 8, 2018 at 14:50
  • This works in .net core 2.1, and is a very clean option. If you inject your httpClient, this becomes a 1 line json Post. Commented Aug 6, 2020 at 0:50
4

I finally invoked in sync mode by including the .Result

HttpResponseMessage response = null;
try
{
 using (var client = new HttpClient())
 {
 response = client.PostAsync(
 "http://localhost:8000/....",
 new StringContent(myJson,Encoding.UTF8,"application/json")).Result;
 if (response.IsSuccessStatusCode)
 {
 MessageBox.Show("OK"); 
 }
 else
 {
 MessageBox.Show("NOK");
 }
 }
}
catch (Exception ex)
{
 MessageBox.Show("ERROR");
}
answered Feb 27, 2018 at 10:34
4

I find this to be the friendliest and most concise way to post an read JSON data:

var url = @"http://www.myapi.com/";
var request = new Request { Greeting = "Hello world!" };
var json = JsonSerializer.Serialize<Request>(request);
using (WebClient client = new WebClient())
{
 var jsonResponse = client.UploadString(url, json);
 var response = JsonSerializer.Deserialize<Response>(jsonResponse);
}

I'm using Microsoft's System.Text.Json for serializing and deserializing JSON. See NuGet.

answered Jul 31, 2020 at 10:33
3

This is how I do it

//URL
var url = "http://www.myapi.com/";
//Request
using var request = new HttpRequestMessage(HttpMethod.Post, url);
//Headers
request.Headers.Add("Accept", "application/json");
request.Headers.Add("Cache-Control", "no-cache");
//Payload
var payload = JsonConvert.SerializeObject(
 new
 {
 Text = "Hello world"
 });
request.Content = new StringContent(payload, Encoding.UTF8, "application/json");
//Send
var response = await _httpClient.SendAsync(request);
//Handle response
if (response.IsSuccessStatusCode)
 return;
answered Nov 15, 2021 at 16:38
2

Dot net core solution

first using Newtonsoft.Json then write a method like this:

 public static string? LoginToken()
 {
 var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://url");
 httpWebRequest.ContentType = "application/json";
 httpWebRequest.Method = "POST";
 using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
 {
 // write your json content here
 string json = JsonConvert.SerializeObject(new
 {
 userName = ApiOptions.Username,
 password = ApiOptions.Password
 }
 );
 streamWriter.Write(json);
 }
 var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
 using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
 {
 var result = streamReader.ReadToEnd();
 return result;
 }
 }

This method return string. if you want to deserialize the string result to JSON, simply add this line at the end of the method:

var result = streamReader.ReadToEnd(); 
var json_result = JsonConvert.DeserializeObject<LoginTokenResponse>(result); // + add this code
 

Which LoginTokenResponse is the custom class you want to Deserialize the string result

answered Dec 2, 2021 at 6:20
0

This is a very old post, but is valid, for NET 5,6,7,8... the solution from Microsoft is:

 private async void button1_Click(object sender, EventArgs e)
 {
 try
 {
 string url = "http://example.com/api/v1/resource";
 HttpClient client = new HttpClient();
 var requestData = new { key = "value" };
 string json = JsonSerializer.Serialize(requestData);
 var content = new StringContent(json, Encoding.UTF8, "application/json");
 var response = await client.PostAsync(url, content);
 string responseContent = await response.Content.ReadAsStringAsync();
 MessageBox.Show(responseContent);
 }
 catch (Exception ex)
 {
 MessageBox.Show(ex.Message);
 }
}

Of course that can be done better by reusing HttpClient.

answered Feb 11 at 22:14
-1

var data = Encoding.ASCII.GetBytes(json);

byte[] postBytes = Encoding.UTF8.GetBytes(json);

Use ASCII instead of UFT8

answered Mar 15, 2017 at 17:51
2
  • 3
    sounds like a pretty bad idea, am i missing something? Commented Apr 24, 2017 at 1:15
  • JSON can contain UTF8 characters, this seems like a terrible idea. Commented Sep 14, 2018 at 18:48

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.