Send JSON via POST in C# and Receive the JSON returned?

267,610

Solution 1

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
}

Solution 2

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);

// ...

Solution 3

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);
            }
        }

Solution 4

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

var requestObj= JsonConvert.SerializeObject(obj);
HttpResponseMessage response = await client.PostAsJsonAsync($"endpoint",requestObj);
Share:
267,610

Related videos on Youtube

Hunter Mitchell
Author by

Hunter Mitchell

Updated on October 28, 2021

Comments

  • Hunter Mitchell
    Hunter Mitchell over 2 years

    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();
        }
    }
    
    • L.B
      L.B about 10 years
      You can try WebClient.UploadString(JsonConvert.SerializeObjectobj(yourob‌​j)) or HttpClient.PostAsJsonAsync
  • Hunter Mitchell
    Hunter Mitchell about 10 years
    perfect, but what is the await Task.run(()?
  • Kai Eichinger
    Kai Eichinger about 10 years
    Task.Run is a shortcut since .NET 4.5 for Task.Factory.StartNew. In this case I async'ify the serialization. You can obviously also do that synchronously. I just figured that, depending on the payload, it may take a bit longer, so I wouldn't want to waste unnecessary resources there.
  • Kai Eichinger
    Kai Eichinger about 10 years
    You mean the HttpClient? Then yes, that's a library made by Microsoft!
  • Hunter Mitchell
    Hunter Mitchell about 10 years
    I keep getting error on the lines that contain await. It says something about async methods.
  • Kai Eichinger
    Kai Eichinger about 10 years
    Yes, you need to mark your method with the async modifier and the return type needs to be either Task (the equivalent for void) or Task<T> (the equivalent for T). e.g. public async Task DoRequest() { /* ... */ } or public async Task<string> DoRequest() { /* ... */ return "hello world"; }. What .NET version are you targeting with your project?
  • Hunter Mitchell
    Hunter Mitchell about 10 years
    Let me post the current code i have right now in my question so you can get a better look. It is under Updated Code. I also added a comment //Error here where the errors where.
  • Kai Eichinger
    Kai Eichinger about 10 years
  • Dagrooms
    Dagrooms about 7 years
    In my codebase we inherit StringContent into a class JsonContent; the constructors take 1) string content, then call base(content, Encoding.Utf8, "application/json") and 2) string content, Encoding encoding, then make the appropriate base() call.
  • Stephen Foster
    Stephen Foster over 6 years
    You shouldn't use Task.Run on synchronous CPU bound methods as you're just firing off a new thread for no benefit!
  • Seafish
    Seafish almost 6 years
    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
  • maxshuty
    maxshuty almost 6 years
    Side note: don't use a using with HttpClient. See: aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
  • Jari Turkia
    Jari Turkia over 5 years
    How do you avoid Exception while executing function. Newtonsoft.Json: Can not add Newtonsoft.Json.Linq.JProperty to Newtonsoft.Json.Linq.JArray errors?
  • hB0
    hB0 over 5 years
    With System.Net.Http.Formatting you have extension methods defined: "await httpClient.PostAsJsonAsync("api/v1/domain", csObjRequest)"
  • Harun Diluka Heshan
    Harun Diluka Heshan over 5 years
    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. docs.microsoft.com/en-us/dotnet/api/…
  • Nilambar Sharma
    Nilambar Sharma almost 5 years
    Can you please add explanation what your code does and how it solves the issue?
  • Rukshala Weerasinghe
    Rukshala Weerasinghe almost 5 years
    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.
  • stomy
    stomy over 4 years
    Why don't you use await JsonConvert.SerializeObjectAsync(payload)?
  • Igor Mironenko
    Igor Mironenko almost 3 years
    FYI there's no PostAsJsonAsync() on the HttpClient since .NET4.5 or so
  • Cale Sweeney
    Cale Sweeney about 2 years
    If you want to skip the object serialization and use a string json you copied from elsewhere, you can escape the json into a string and then use it in the example above. E.g. string stringPayload = "{\"test\": 123}";