In modern web development, sending JSON objects over HTTP has become a common practice for exchanging data between clients and servers. In this article, we will explore how to send a JSON object using HttpClient.

To download the source code for this article, you can visit our GitHub repository.

With that, let’s get started.

Preparation to Send a JSON Object Using HttpClient

To start, let’s define a simple DTO object for the responses we expect from the https://petstore.swagger.io/v2 API:

Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
Become a patron at Patreon!
public class PetCategory
{
    [JsonPropertyName("name")]
    public string? Name { get; set; }
}

public class PetDto
{
    [JsonPropertyName("id")]
    public long Id { get; set; }

    [JsonPropertyName("category")]
    public PetCategory? Category { get; set; }

    [JsonPropertyName("name")]
    public string? Name { get; set; }

    [JsonPropertyName("status")]
    public string? Status { get; set; }
}

Initially, we define a category for the pet with the PetCategory class that defines only a Name property and use that in our PetDto class. Additionally, along the Category, we have an Id, Name and Status property.

Send a JSON Object Using HttpClient and StringContent Class

In C#, it is easy to generate and send JSON Objects using HttpClient class along with the StringContent class while making API calls

Let’s see this in an example:

new StringContent("{ \"status\": \"available\" }", Encoding.UTF8);

The constructor accepts a JSON string as the required first argument and an optional second argument being the encoding format.

Keeping this in our head, we can convert a C# object to a JSON string using JsonSerializer class from the NuGet package System.Text.Json. We can also use JsonConvert class from Newtonsoft.Json NuGet package, but we will focus on using JsonSerializer class in our examples.

Send a JSON Object Using StringContent Class

Let’s use StringContent, starting with an interface:

public interface IPetService
{
    Task<PetDto?> PostAsStringContentAsync();
}

Firstly, we define an IPetService interface with the PostAsStringContent() method.

Next, let’s implement this interface:

public class PetService : IPetService
{
    private readonly HttpClient _httpClient;

    public PetService(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    public async Task<PetDto?> PostAsStringContentAsync()
    {
        var petData = CreatePet();

        var pet = JsonSerializer.Serialize(petData);

        var request = new HttpRequestMessage(HttpMethod.Post, "pet");
        request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        request.Content = new StringContent(pet, Encoding.UTF8);
        request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

        var response = await _httpClient.SendAsync(request);
        response.EnsureSuccessStatusCode();

        var content = await response.Content.ReadAsStringAsync();
        var createdPet = JsonSerializer.Deserialize<PetDto>(content);

        return createdPet;
    }

    private PetDto CreatePet()
    {
        return new PetDto
        {
            Name = "German Shepherd",
            Status = "Available",
            Category = new PetCategory
            {
                Name = "Canines"
            }
        };
    }
}

Firstly, we create a PetService class and implement our interface IPetService. Then, in our PostAsStringContentAsync() method we implement a POST request to create a new pet. Moreover, we create a new PetDto object and serialize it into a JSON string using the JsonSerialization.Serialize() method.

Then, we create an HttpRequestMessage object for the POST request to the /pet endpoint of our test API.

Furthermore, we pass the JSON string, pet, as an argument to the constructor of StringContent class, then this is assigned to the request.Content variable. Additionally, we also define that the content is of type application/json to indicate that we are sending JSON content. Moreover, the Accept header we define, tells the server that our client accepts only application/json content. We send the request asynchronously using the SendAsync() method of the HttpClient instance.

Following that, we receive an asynchronous response. Furthermore, we make sure with the EnsureSuccessStatusCode() method that we continue with a successful response. Using the response object we read the response string using the ReadAsStringAsync() method.

Finally, we deserialize the response content which is a JSON string into an object, createdPet using the JsonSerializer.Deserialize() method. The deserialized object is returned as the result of the service method.

Let’s have a look at how we register a HttpClient instance:

builder.Services.AddHttpClient<IPetService, PetService>(client =>
{
    client.BaseAddress = new Uri("https://petstore.swagger.io/v2/");
});

In our Program class we call the AddHttpClient() method to register an instance for our PetService. This method ensures that we efficiently use HttpClient instances for our class. Additionally, we set the BaseAddress property for the instance to our https://petstore.swagger.io/v2 API.

If you want to know more about how we can use HttpClient in ASP.NET Core check out our tutorial HttpClient with ASP.NET Core Tutorial.

Now, let’s register an API endpoint in our Program class:

app.MapPost("/postAsStringContent", async (IPetService petService)
    => await petService.PostAsStringContent());

In the MapPost() method, we add the API route postAsStringContent in which we invoke the PostAsStringContentAsync() method of our IPetService.

Testing the PostAsStringContent Endpoint

Moving forward, let’s run our application make a POST request to our endpoint:

{
    "id": 9223372036854776000,
    "category": {
        "name": "Canines"
    },
    "name": "German Shepherd",
    "status": "Available"
}

We execute our endpoint /postAsStringContent and get a successful JSON response from the URL where we posted our pet object.

If you want to know more on how to setup Swagger UI for your ASP.NET core application, check out our article Configuring and Using Swagger UI in ASP.NET Core Web API

Send a JSON Object Using HttpClient and PostAsJsonAsync Method

With the advent of .NET 5 and higher versions, C# made sending POST requests with JSON contents easier and the implementation simpler with fewer lines of code. It hides the process of serializing objects into JSON formats, setting the headers, and sending the request. Thereby making the code shorter and easier to read.

Let’s have a look at how we can leverage this method:

await _httpClient.PostAsJsonAsync("pet", petData);

All we need to do is pass our URL and the object that we would like to send as JSON to the method and that’s it. 

Using the PostAsJsonAsync() method, developers can focus on what they want to achieve instead of dealing with the technical details of HttpClient.  

We have to keep in mind that the PostAsJsonAsync() method uses JsonSerializerDefaults.Web option for serialization by default, unlike the JsonSerializer.Serialize() method.

Send a JSON Object Using PostAsJsonAsync Method

Let’s enhance our PetService code using this approach and showcase it in a new method:

public class PetService : IPetService
{
    public async Task<PetDto?> PostAsJsonAsync()
    {
        var petData = CreatePet();

        var response = await _httpClient.PostAsJsonAsync("pet", petData);
        response.EnsureSuccessStatusCode();

        var content = await response.Content.ReadAsStringAsync();
        var createdPet = JsonSerializer.Deserialize<PetDto>(content);

        return createdPet;
    }
}

We add the PostAsJsonAsync() method to our IPetService interface and the PetService class. We re-use the CreatePet() method to send the petData object via the PostAsJsonAsync() extension method for HttpClient. The PostAsJsonAsync() extension method encapsulates the serialization and setting of headers and contents. This is way cleaner and easier to read. Furthermore, we have significantly streamlined our code down to just six lines. 

Now, let’s register a new API endpoint in our Program class:

app.MapPost("/postAsJson", async (IPetService petService)
    => await petService.PostAsJsonAsync());

In the MapPost() method, we register the API route postAsJson where we invoke the PostAsJson() method.

Testing the PostAsJson Endpoint

Once again, let’s run our application and make a POST request to our newly added endpoint:

{
    "id": 9223372036854776000,
    "category": {
        "name": "Canines"
    },
    "name": "German Shepherd",
    "status": "Available"
}

We execute our newly implemented endpoint /postAsJson and get a successful JSON response from the target URL.

Conclusion

In conclusion, C# makes it easy to send JSON objects using HttpClient methods. We demonstrated how to use JSON serialization to convert objects to JSON strings and send them over HTTP requests. Now we know how to send JSON objects without racking our brains.

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!