129

This is my first time ever using JSON as well as System.Net and the WebRequest in any of my applications. My application is supposed to send a JSON payload, similar to the one below to an authentication server:

{
 "agent": { 
 "name": "Agent Name", 
 "version": 1 
 },
 "username": "Username", 
 "password": "User Password",
 "token": "xxxxxx"
}

To create this payload, I used the JSON.NET library. How would I send this data to the authentication server and receive its JSON response back? Here is what I have seen in some examples, but no JSON content:

var http = (HttpWebRequest)WebRequest.Create(new Uri(baseUrl));
http.Accept = "application/json";
http.ContentType = "application/json";
http.Method = "POST";
string parsedContent = "Parsed JSON Content needs to go here";
ASCIIEncoding encoding = new ASCIIEncoding();
Byte[] bytes = encoding.GetBytes(parsedContent);
Stream newStream = http.GetRequestStream();
newStream.Write(bytes, 0, bytes.Length);
newStream.Close();
var response = http.GetResponse();
var stream = response.GetResponseStream();
var sr = new StreamReader(stream);
var content = sr.ReadToEnd();

However, this seems to be a lot of code compaired to using other languages I have used in the past. Am I doing this correctly? And how would I get the JSON response back so I can parse it?

Thanks, Elite.

Updated Code

// Send the POST Request to the Authentication Server
// Error Here
string json = await Task.Run(() => JsonConvert.SerializeObject(createLoginPayload(usernameTextBox.Text, password)));
var httpContent = new StringContent(json, Encoding.UTF8, "application/json");
using (var httpClient = new HttpClient())
{
 // Error here
 var httpResponse = await httpClient.PostAsync("URL HERE", httpContent);
 if (httpResponse.Content != null)
 {
 // Error Here
 var responseContent = await httpResponse.Content.ReadAsStringAsync();
 }
}
Douglas Reid
3,8186 gold badges33 silver badges50 bronze badges
asked May 10, 2014 at 20:23
1
  • 2
    You can try WebClient.UploadString(JsonConvert.SerializeObjectobj(yourobj)) or HttpClient.PostAsJsonAsync
    L.B
    Commented May 10, 2014 at 20:58

5 Answers 5

191

I found myself using the HttpClient library to query RESTful APIs as the code is very straightforward and fully async'ed. To send this JSON payload:

{
 "agent": { 
 "name": "Agent Name", 
 "version": 1 
 },
 "username": "Username", 
 "password": "User Password",
 "token": "xxxxxx"
}

With two classes representing the JSON structure you posted that may look like this:

public class Credentials
{
 public Agent Agent { get; set; }
 
 public string Username { get; set; }
 
 public string Password { get; set; }
 
 public string Token { get; set; }
}
public class Agent
{
 public string Name { get; set; }
 
 public int Version { get; set; }
}

You could have a method like this, which would do your POST request:

var payload = new Credentials { 
 Agent = new Agent { 
 Name = "Agent Name",
 Version = 1 
 },
 Username = "Username",
 Password = "User Password",
 Token = "xxxxx"
};
// Serialize our concrete class into a JSON String
var stringPayload = JsonConvert.SerializeObject(payload);
// Wrap our JSON inside a StringContent which then can be used by the HttpClient class
var httpContent = new StringContent(stringPayload, Encoding.UTF8, "application/json");
var httpClient = new HttpClient()
 
// Do the actual request and await the response
var httpResponse = await httpClient.PostAsync("http://localhost/api/path", httpContent);
// If the response contains content we want to read it!
if (httpResponse.Content != null) {
 var responseContent = await httpResponse.Content.ReadAsStringAsync();
 
 // From here on you could deserialize the ResponseContent back again to a concrete C# type using Json.Net
}
CodeCaster
152k24 gold badges234 silver badges286 bronze badges
answered May 10, 2014 at 21:24
14
  • 5
    perfect, but what is the await Task.run(()? Commented May 10, 2014 at 21:27
  • 29
    You shouldn't use Task.Run on synchronous CPU bound methods as you're just firing off a new thread for no benefit! Commented Nov 30, 2017 at 14:24
  • 3
    You don't have to type out the JsonProperty for every property. Just use Json.Net's built in CamelCasePropertyNamesContractResolver or a custom NamingStrategy to customize the serialization process
    Seafish
    Commented Jun 17, 2018 at 2:34
  • 9
    Side note: don't use a using with HttpClient. See: aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
    maxshuty
    Commented Aug 7, 2018 at 12:49
  • 5
    With System.Net.Http.Formatting you have extension methods defined: "await httpClient.PostAsJsonAsync("api/v1/domain", csObjRequest)"
    hB0
    Commented Oct 31, 2018 at 4:01
32

Using the JSON.NET NuGet package and anonymous types, you can simplify what the other posters are suggesting:

// ...
string payload = JsonConvert.SerializeObject(new
{
 agent = new
 {
 name = "Agent Name",
 version = 1,
 },
 username = "username",
 password = "password",
 token = "xxxxx",
});
var client = new HttpClient();
var content = new StringContent(payload, Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync(uri, content);
// ...
answered May 10, 2019 at 13:20
2
  • Clear and concise, it's what I am trying to use currently :) , although I am currently running into a 400/BadRequest response.status_code, and having problem viewing my JSON content string, but problem(s) possibly (& hopefully) due to other things! TBD
    Zeek2
    Commented Apr 29, 2024 at 10:03
  • 1
    There is a built-in constant for "application/json" string so instead of hardcoding we can just use: MediaTypeNames.Application.Json Commented Sep 10, 2024 at 21:26
11

You can also use the PostAsJsonAsync() method available in HttpClient()

var requestObj= JsonConvert.SerializeObject(obj);
HttpResponseMessage response = await client.PostAsJsonAsync($"endpoint",requestObj);
Igor
4093 silver badges6 bronze badges
answered Jun 21, 2019 at 5:42
3
  • 1
    Can you please add explanation what your code does and how it solves the issue? Commented Jun 21, 2019 at 6:02
  • 2
    You can take whatever the object you want to post and serialize it using the SerializeObject(); var obj= new Credentials { Agent = new Agent { Name = "Agent Name", Version = 1 }, Username = "Username", Password = "User Password", Token = "xxxxx" }; And then without having to convert it to httpContent, you can use the PostAsJsonAsync() passing the endpoint URL and the converted JSON object itself. Commented Jun 22, 2019 at 7:13
  • 4
    FYI there's no PostAsJsonAsync() on the HttpClient since .NET4.5 or so
    PandaWood
    Commented Jul 14, 2021 at 0:22
9

You can build your HttpContent using the combination of JObject to avoid and JProperty and then call ToString() on it when building the StringContent:

 /*{
 "agent": { 
 "name": "Agent Name", 
 "version": 1 
 },
 "username": "Username", 
 "password": "User Password",
 "token": "xxxxxx"
 }*/
 JObject payLoad = new JObject(
 new JProperty("agent", 
 new JObject(
 new JProperty("name", "Agent Name"),
 new JProperty("version", 1)
 ),
 new JProperty("username", "Username"),
 new JProperty("password", "User Password"),
 new JProperty("token", "xxxxxx") 
 )
 );
 using (HttpClient client = new HttpClient())
 {
 var httpContent = new StringContent(payLoad.ToString(), Encoding.UTF8, "application/json");
 using (HttpResponseMessage response = await client.PostAsync(requestUri, httpContent))
 {
 response.EnsureSuccessStatusCode();
 string responseBody = await response.Content.ReadAsStringAsync();
 return JObject.Parse(responseBody);
 }
 }
answered Jul 14, 2017 at 16:48
2
  • How do you avoid Exception while executing function. Newtonsoft.Json: Can not add Newtonsoft.Json.Linq.JProperty to Newtonsoft.Json.Linq.JArray errors? Commented Sep 20, 2018 at 6:30
  • 1
    An HttpClient instance is not supposed to create with using construct. The instance should be created once and used throughout the application. This is because it uses its own connection pool. Your code tend mostly to throw SocketException. learn.microsoft.com/en-us/dotnet/api/… Commented Nov 13, 2018 at 12:32
4

System.Net.Http.Json.JsonContent exists to make serializing into json very easy (that is, if you're not already using or unable to use convenience methods like httpClient.PostAsync());

I was using IDownstreamApi with a POST method and needed to pass HttpContent so the code simply looks like:

 var jsonContent = JsonContent.Create(request);
 using var response = await _downstreamApi.CallApiForAppAsync("GraphApi", options =>
 {
 options.RelativePath = "directoryObjects/getByIds";
 options.HttpMethod = HttpMethod.Post;
 }, jsonContent, cancellationToken: cancellationToken);
answered Aug 6, 2023 at 16:23
1
  • Deceptively easy to use. Works for JsonContent.Create(double[] {....}) as well. No need to mess around with any of the other arguments in the documentation
    heyyy
    Commented Jan 2, 2024 at 17:30

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.