Question

How to Send an HTTP POST Request in .NET

csharp.netposthttpwebrequesthttprequest

Question

How can I send an HTTP POST request in .NET and include data in the request body?

For example, I want to make a request to an API endpoint using the POST method and pass some data such as JSON or form values in the body of the request. What is the standard way to do this in modern .NET?

Short Answer

By the end of this page, you will understand how HTTP POST requests work in .NET, how to send data in the request body using HttpClient, and how to handle common formats such as JSON and form data. You will also see common mistakes, practical examples, and how this pattern is used in real applications.

Concept

HTTP POST is used when you want to send data to a server, usually to create something or trigger some server-side action.

In .NET, the standard way to send HTTP requests is with HttpClient. When sending a POST request, the important idea is this:

  • The URL identifies where the request goes
  • The HTTP method (POST) identifies what kind of action you want
  • The request body contains the data you are sending
  • Headers describe how the data is formatted, such as application/json

A common use case is sending JSON to a web API:

var user = new { name = "Alice", age = 30 };

That object is typically serialized to JSON and sent in the body.

Why this matters in real programming:

  • Web APIs often expect POST requests for create operations
  • Authentication endpoints often use POST
  • External services such as payment APIs, messaging APIs, and internal microservices rely on HTTP requests
  • Backend apps, desktop apps, and command-line tools frequently call APIs this way

In modern .NET, HttpClient is preferred over older APIs such as WebRequest. It supports async programming, headers, content types, cancellation, and better overall control.

Mental Model

Think of an HTTP POST request like mailing a package:

  • The address is the URL
  • The delivery type is the HTTP method, such as POST
  • The package contents are the request body
  • The label on the package is the Content-Type header, which tells the receiver what format the contents use

If you send JSON, the server needs to know that the package contains JSON. If you forget the label, the server may not know how to read it correctly.

Take Quiz

Syntax and Examples

Basic JSON POST with HttpClient

using System.Net.Http;
using System.Text;
using System.Text.Json;

var httpClient = new HttpClient();

var data = new
{
    name = "Alice",
    age = 30
};

string json = JsonSerializer.Serialize(data);
var content = new StringContent(json, Encoding.UTF8, "application/json");

HttpResponseMessage response = await httpClient.PostAsync("https://api.example.com/users", content);
string responseBody = await response.Content.ReadAsStringAsync();

Console.WriteLine(response.StatusCode);
Console.WriteLine(responseBody);

What this does

  • Creates an object with data
  • Converts it to JSON
  • Wraps that JSON in StringContent
  • Sets the encoding to UTF-8
  • Sets the content type to application/json
  • Sends the request using PostAsync

Sending form data

Some APIs expect form fields instead of JSON.

using System.Net.Http;

var httpClient = new HttpClient();

var formData = new Dictionary<string, string>
{
    ["username"] = "alice",
    ["password"] = "secret123"
};

var content = new FormUrlEncodedContent(formData);

HttpResponseMessage response = await httpClient.PostAsync("https://api.example.com/login", content);
string responseBody = await response.Content.ReadAsStringAsync();

Console.WriteLine(responseBody);

When to use which

  • Use JSON for most modern APIs
  • Use form data when the API documentation specifically requires it

Step by Step Execution

Consider this example:

using System.Net.Http;
using System.Text;
using System.Text.Json;

var httpClient = new HttpClient();

var product = new
{
    name = "Notebook",
    price = 9.99
};

string json = JsonSerializer.Serialize(product);
var content = new StringContent(json, Encoding.UTF8, "application/json");

HttpResponseMessage response = await httpClient.PostAsync("https://api.example.com/products", content);
string responseText = await response.Content.ReadAsStringAsync();

Step by step:

  1. var httpClient = new HttpClient();

    • Creates an object that can send HTTP requests.
  2. var product = new { ... };

    • Creates the data you want to send.
  3. JsonSerializer.Serialize(product)

    • Converts the C# object into a JSON string.
    • The result looks like:
    {"name":"Notebook","price":9.99}
    
  4. new StringContent(...)

    • Wraps that JSON string as HTTP body content.
    • Also sets encoding and content type.
  5. await httpClient.PostAsync(...)

    • Sends the POST request to the server.
    • The server receives the JSON in the body.
  6. await response.Content.ReadAsStringAsync()

    • Reads the server's reply as text.

If the server accepts the request, it may return a success status such as 200 OK or 201 Created.

Real World Use Cases

Here are common places where POST requests are used:

  • User registration: send a new user's details to an API
  • Login requests: send credentials securely in the request body
  • Create database records: send product, order, or customer data
  • Webhook calls: notify another service that something happened
  • Payment processing: send payment or checkout information to a payment API
  • Internal microservices: one service sends commands or data to another
  • Contact forms: submit message details from an app to a backend

Example scenarios:

  • A desktop app sends feedback text to a support API
  • A background service posts monitoring data to a logging endpoint
  • A CLI tool submits deployment information to an internal server
Take Quiz

Real Codebase Usage

In real projects, developers usually go beyond a single PostAsync call.

Common patterns

Reuse HttpClient

Creating a new HttpClient for every request is usually avoided in larger apps. Instead, developers often reuse it or get it from dependency injection.

Validate before sending

Applications often check that required values exist before building the request.

if (string.IsNullOrWhiteSpace(email))
{
    throw new ArgumentException("Email is required.");
}

Check response status

A request may fail even if the code runs correctly.

response.EnsureSuccessStatusCode();

This throws an exception for non-success status codes.

Add headers

Real APIs often need headers such as authentication tokens.

httpClient.DefaultRequestHeaders.Authorization =
    new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);

Wrap API calls in methods

Instead of scattering HTTP logic everywhere, teams often create small service classes.

public async Task<string> CreateUserAsync(object user)
{
    string json = JsonSerializer.Serialize(user);
    var content = new StringContent(json, Encoding.UTF8, "application/json");

    var response = await _httpClient.PostAsync("https://api.example.com/users", content);
    response.EnsureSuccessStatusCode();
    return await response.Content.ReadAsStringAsync();
}

This makes code easier to test, reuse, and maintain.

Common Mistakes

1. Forgetting the content type

If you send JSON but do not label it correctly, the server may reject it.

Broken example:

var content = new StringContent(json);

Better:

var content = new StringContent(json, Encoding.UTF8, "application/json");

2. Not awaiting async calls

Broken example:

HttpResponseMessage response = httpClient.PostAsync(url, content);

PostAsync returns a Task<HttpResponseMessage>, not the final response.

Correct:

HttpResponseMessage response = await httpClient.PostAsync(url, content);

3. Sending the wrong body format

Some APIs expect form data, others expect JSON. Always check the API documentation.

4. Ignoring error responses

Broken example:

var response = await httpClient.PostAsync(url, content);
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);

This reads the body, but does not check whether the request succeeded.

Better:

var response = await httpClient.PostAsync(url, content);
response.EnsureSuccessStatusCode();

5. Recreating HttpClient too often in large applications

For small demos, this is fine. In real applications, prefer reusing HttpClient or using IHttpClientFactory.

6. Confusing query parameters with body data

This is different:

https://api.example.com/users?name=Alice

That sends data in the URL, not in the body. A POST request body is separate from the query string.

Comparisons

ConceptWhat it meansCommon use
GETRetrieve dataLoad users, fetch products
POSTSend data to create or trigger somethingCreate user, log in, submit form
PUTReplace or update a resourceUpdate full record
PATCHPartially update a resourceChange one field
DELETERemove a resourceDelete record

StringContent vs FormUrlEncodedContent

TypeUse whenExample content type
StringContentYou already have text such as JSON or XMLapplication/json
FormUrlEncodedContentAPI expects form fieldsapplication/x-www-form-urlencoded

Older APIs vs modern .NET approach

APIStatusRecommendation
WebRequest / HttpWebRequestOlderAvoid for new code
HttpClientModern standardPreferred

HttpClient is the usual choice because it works well with async code and modern .NET apps.

Take Quiz

Cheat Sheet

Quick reference

Send JSON with POST

var data = new { name = "Alice" };
string json = JsonSerializer.Serialize(data);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync(url, content);

Send form data

var form = new Dictionary<string, string>
{
    ["username"] = "alice",
    ["password"] = "secret"
};
var content = new FormUrlEncodedContent(form);
var response = await httpClient.PostAsync(url, content);

Read the response

string body = await response.Content.ReadAsStringAsync();

Check success

response.EnsureSuccessStatusCode();

Common namespaces

using System.Net.Http;
using System.Text;
using System.Text.Json;

Key rules

  • Use HttpClient in modern .NET
  • Use await with PostAsync
  • Set application/json when sending JSON
  • Use FormUrlEncodedContent for form posts
  • Check the API documentation for expected format
  • Reuse HttpClient in real applications when possible

FAQ

How do I send JSON in an HTTP POST request in .NET?

Serialize a C# object to JSON, wrap it in StringContent, set the content type to application/json, and call PostAsync.

What class should I use for HTTP requests in modern .NET?

Use HttpClient. It is the standard choice for sending HTTP requests in modern .NET applications.

How do I send form data instead of JSON?

Use FormUrlEncodedContent with a dictionary of key-value pairs, then pass it to PostAsync.

Do I need to set headers manually for JSON?

You should set the content type on the request body, usually by using new StringContent(json, Encoding.UTF8, "application/json").

What is the difference between POST body data and query string data?

Query string data goes in the URL. Body data is sent separately as the request content. APIs often use the body for larger or structured data like JSON.

Why is await needed with PostAsync?

PostAsync is asynchronous. await pauses until the HTTP request completes and gives you the actual HttpResponseMessage.

Should I create a new HttpClient every time?

For small examples, it works. In real applications, it is usually better to reuse HttpClient or use IHttpClientFactory.

Take Quiz

Mini Project

Description

Build a small .NET console app that sends a POST request to a public test API. This helps you practice creating a JSON body, sending it with HttpClient, and reading the response. It reflects a common real-world task: sending data from an application to a web service.

Goal

Create a console app that submits a new post as JSON and prints the server response.

Requirements

[ "Create a C# console application", "Build a JSON request body with at least two fields", "Send the data using an HTTP POST request", "Read and print the response status and response body", "Use async/await with HttpClient" ]

Take Quiz

Keep learning

Related questions

View more