ZetCode

C# HttpClient

last modified March 13, 2021

C# HttpClient tutorial shows how to create HTTP requests with HttpClient in C#. In the examples, we create simple GET and POST requests.

The Hypertext Transfer Protocol (HTTP) is an application protocol for distributed, collaborative, hypermedia information systems. HTTP is the foundation of data communication for the World Wide Web.

HttpClient is a base class for sending HTTP requests and receiving HTTP responses from a resource identified by a URI.

C# HttpClient status code

HTTP response status codes indicate whether a specific HTTP request has been successfully completed. Responses are grouped in five classes:

Program.cs
using System;
using System.Net.Http;
using System.Threading.Tasks;

namespace HttpClientStatus
{
    class Program
    {
        static async Task Main(string[] args)
        {
            using var client = new HttpClient();

            var result = await client.GetAsync("http://webcode.me");
            Console.WriteLine(result.StatusCode);
        }
    }
}

The example creates a GET request to a small website. We get the status code of the request.

using var client = new HttpClient();

A new HttpClient is created.

var result = await client.GetAsync("http://webcode.me");

The GetAsync method sends a GET request to the specified Uri as an asynchronous operation. The await operator suspends the evaluation of the enclosing async method until the asynchronous operation completes. When the asynchronous operation completes, the await operator returns the result of the operation, if any.

$ dotnet run
OK

We get the 200 OK status code; the website is up.

C# HttpClient GET request

The GET method requests a representation of the specified resource.

Program.cs
using System;
using System.Net.Http;
using System.Threading.Tasks;

namespace HttpClientEx
{
    class Program
    {
        static async Task Main(string[] args)
        {
            using var client = new HttpClient();
            var content = await client.GetStringAsync("http://webcode.me");

            Console.WriteLine(content);
        }
    }
}

The example issues a GET request to the webcode.me website. It outputs the simple HTML code of the home page.

var content = await client.GetStringAsync("http://webcode.me");

The GetStringAsync sends a GET request to the specified Uri and returns the response body as a string in an asynchronous operation.

$ dotnet run
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My html page</title>
</head>
<body>

    <p>
        Today is a beautiful day. We go swimming and fishing.
    </p>

    <p>
         Hello there. How are you?
    </p>

</body>
</html>

C# HttpClient HEAD request

The HTTP HEAD method requests the headers that are returned if the specified resource would be requested with an HTTP GET method.

Program.cs
using System;
using System.Net.Http;

var url = "http://webcode.me";
using var client = new HttpClient();

var result = await client.SendAsync(new HttpRequestMessage(HttpMethod.Head, url));

Console.WriteLine(result);

The example issues a HEAD request.

$ # dotnet run
StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, 
Content: System.Net.Http.HttpConnectionResponseContent, Headers:
{
  Server: nginx/1.6.2
  Date: Tue, 12 Jan 2021 12:01:07 GMT
  Connection: keep-alive
  ETag: "5d32ffc5-15c"
  Accept-Ranges: bytes
  Content-Type: text/html
  Content-Length: 348
  Last-Modified: Sat, 20 Jul 2019 11:49:25 GMT
}

These are the header fields of the response.

C# HttpClient multiple GET requests

In the following example, we generate multiple asynchronous GET requests.

Program.cs
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using System.Text.RegularExpressions;

var urls = new string[] {"http://webcode.me", "http://example.com",
    "http://httpbin.org"};

using var client = new HttpClient();

var tasks = new List<Task<string>>();

foreach (var url in urls)
{
    tasks.Add(client.GetStringAsync(url));
}

Task.WaitAll(tasks.ToArray());

var data = new List<string> { await tasks[0], await tasks[1], await tasks[2] };

var rx = new Regex(@"<title>\s*(.+?)\s*</title>", RegexOptions.Compiled);

foreach (var content in data)
{
    var matches = rx.Matches(content);
    
    foreach (var match in matches)
    {
        Console.WriteLine(match);
    }
}

We download three web pages asynchronously and print their HTML title tags.

tasks.Add(client.GetStringAsync(url));

The GetStringAsync creates a new task. It sends a GET request to the specified url and returns the response body as a string in an asynchronous operation.

Task.WaitAll(tasks.ToArray());

The Task.WaitAll waits for all tasks to complete execution.

var rx = new Regex(@"<title>\s*(.+?)\s*</title>", RegexOptions.Compiled);

foreach (var content in data)
{
    var matches = rx.Matches(content);
    
    foreach (var match in matches)
    {
        Console.WriteLine(match);
    }
}

With the help of a regular expression, we get the title tags from the retrieved pages.

$ dotnet run
<title>My html page</title>
<title>Example Domain</title>
<title>httpbin.org</title>

C# HttpClient POST request

The HTTP POST method sends data to the server. The type of the body of the request is indicated by the Content-Type header.

$ dotnet add package Newtonsoft.Json

We need to add the Newtonsoft.Json package to process JSON data.

Program.cs
using System;
using System.Text;
using System.Net.Http;
using Newtonsoft.Json;

var person = new Person("John Doe", "gardener");

var json = JsonConvert.SerializeObject(person);
var data = new StringContent(json, Encoding.UTF8, "application/json");

var url = "https://httpbin.org/post";
using var client = new HttpClient();

var response = await client.PostAsync(url, data);

string result = response.Content.ReadAsStringAsync().Result;
Console.WriteLine(result);

record Person(string Name, string Occupation);

In the example, we send a POST request to https://httpbin.org/post website, which is an online testing service for developers.

var person = new Person("John Doe", "gardener");

var json = JsonConvert.SerializeObject(person);
var data = new StringContent(json, Encoding.UTF8, "application/json");

We turn an object into a JSON data with the help of the Newtonsoft.Json package.

var response = await client.PostAsync(url, data);

We send an asynchronous POST request with the PostAsync method.

string result = response.Content.ReadAsStringAsync().Result;
Console.WriteLine(result);

We read the returned data and print it to the console.

$ dotnet run
{
  "args": {}, 
  "data": "{\"Name\":\"John Doe\",\"Occupation\":\"gardener\"}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "43", 
    "Content-Type": "application/json; charset=utf-8", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-5ffd917e-349220186065913c2544d3ba"
  }, 
  "json": {
    "Name": "John Doe", 
    "Occupation": "gardener"
  }, 
  ...
  "url": "https://httpbin.org/post"
}

C# HttpClient JSON request

JSON (JavaScript Object Notation) is a lightweight data-interchange format. This format is easy for humans to read and write and for machines to parse and generate. It is a less verbose and more readable alternative to XML. The official Internet media type for JSON is application/json.

Program.cs
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json;

using var client = new HttpClient();

client.BaseAddress = new Uri("https://api.github.com");
client.DefaultRequestHeaders.Add("User-Agent", "C# console program");
client.DefaultRequestHeaders.Accept.Add(
        new MediaTypeWithQualityHeaderValue("application/json"));

var url = "repos/symfony/symfony/contributors";
HttpResponseMessage response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
var resp = await response.Content.ReadAsStringAsync();

List<Contributor> contributors = JsonConvert.DeserializeObject<List<Contributor>>(resp);
contributors.ForEach(Console.WriteLine);

record Contributor(string Login, short Contributions);

The example generates a GET request to to Github. It finds out the top contributors of the Symfony framework. It uses the Newtonsoft.Json to work with JSON.

client.DefaultRequestHeaders.Add("User-Agent", "C# console program");

In the request header, we specify the user agent.

client.DefaultRequestHeaders.Accept.Add(
    new MediaTypeWithQualityHeaderValue("application/json"));

In the accept header value, we tell that JSON is an acceptable response type.

var url = "repos/symfony/symfony/contributors";
HttpResponseMessage response = await client.GetAsync(url);
var resp = await response.Content.ReadAsStringAsync();

We generate a request and read the content asynchronously.

List<Contributor> contributors = JsonConvert.DeserializeObject<List<Contributor>>(resp);
contributors.ForEach(Console.WriteLine);

We transform the JSON response into a list of Contributor objects with the JsonConvert.DeserializeObject method.

C# HttpClient download image

The GetByteArrayAsync sends a GET request to the specified Uri and returns the response body as a byte array in an asynchronous operation.

Program.cs
using System;
using System.IO;
using System.Net.Http;

using var httpClient = new HttpClient();
var url = "http://webcode.me/favicon.ico";
byte[] imageBytes = await httpClient.GetByteArrayAsync(url);

string documentsPath = System.Environment.GetFolderPath(
        System.Environment.SpecialFolder.Personal);

string localFilename = "favicon.ico";
string localPath = Path.Combine(documentsPath, localFilename);

Console.WriteLine(localPath);
File.WriteAllBytes(localPath, imageBytes);

In the example, we download an image from the webcode.me website. The image is written to the user's Documents folder.

byte[] imageBytes = await httpClient.GetByteArrayAsync(url);

The GetByteArrayAsync returns the image as an array of bytes.

string documentsPath = System.Environment.GetFolderPath(
    System.Environment.SpecialFolder.Personal);

We determine the Documents folder with the GetFolderPath method.

File.WriteAllBytes(localPath, imageBytes);

The bytes are written to the disk with the File.WriteAllBytes method.

C# HttpClient Basic authentication

In HTTP protocol, basic access authentication is a method for an HTTP user agent (such as a web browser or a console application) to provide a user name and password when making a request. In basic HTTP authentication, a request contains a header field in the form of Authorization: Basic <credentials>, where credentials is the base64 encoding of id and password joined by a single colon :.

Note: The credentials are not encrypted; therefore, HTTP basic authentication must be used with the HTTPS protocol.

HTTP Basic authentication is the simplest technique for enforcing access controls to web resources. It does not require cookies, session identifiers, or login pages; rather, HTTP Basic authentication uses standard fields in the HTTP header.

Program.cs
using System;
using System.Text;
using System.Net.Http;
using System.Net.Http.Headers;

var userName = "user7";
var passwd = "passwd";
var url = "https://httpbin.org/basic-auth/user7/passwd";

using var client = new HttpClient();

var authToken = Encoding.ASCII.GetBytes($"{userName}:{passwd}");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
        Convert.ToBase64String(authToken));

var result = await client.GetAsync(url);

var content = await result.Content.ReadAsStringAsync();
Console.WriteLine(content);

The example sends credentials to the httpbin.org website.

var authToken = Encoding.ASCII.GetBytes($"{userName}:{passwd}");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
        Convert.ToBase64String(authToken));

Here we build the authentication header.

var url = "https://httpbin.org/basic-auth/user7/passwd";

The URL contains authentication details because we test it with the httpbin.org website. This way we don't need to set up our own server. Authentication details are never put into the URL, of course.

$ dotnet run
{
    "authenticated": true,
    "user": "user7"
}

In this tutorial, we have used C# HttpClient to create HTTP requests.

List all C# tutorials.