# C# `HttpClient`教程

> 原文： [https://zetcode.com/csharp/httpclient/](https://zetcode.com/csharp/httpclient/)

C# `HttpClient`教程展示了如何使用 C# 中的`HttpClient`创建 HTTP 请求。 在示例中，我们创建简单的 GET 和 POST 请求。

超文本传输​​协议（HTTP）是用于分布式，协作式超媒体信息系统的应用协议。 HTTP 是万维网数据通信的基础。

`HttpClient`是用于从 URI 标识的资源发送 HTTP 请求和接收 HTTP 响应的基类。

## C# `HttpClient`状态码

HTTP 响应状态代码指示特定的 HTTP 请求是否已成功完成。 响应分为五类：

*   信息响应（100–199）
*   成功响应（200–299）
*   重定向（300–399）
*   客户端错误（400–499）
*   服务器错误（500–599）

`Program.cs`

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

```

该示例向小型网站创建 GET 请求。 我们获得了请求的状态码。

```cs
using var client = new HttpClient();

```

创建一个新的`HttpClient`。

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

```

`GetAsync()`方法将 GET 请求作为异步操作发送到指定的 Uri。 `await`运算符会暂停对异步方法的求值，直到异步操作完成为止。 异步操作完成后，`await`操作符将返回操作结果（如果有）。

```cs
$ dotnet run
OK

```

我们得到 200 OK 状态码； 网站开通了。

## C# `HttpClient` GET 请求

GET 方法请求指定资源的表示形式。

`Program.cs`

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

```

该示例向`webcode.me`网站发出 GET 请求。 它输出主页的简单 HTML 代码。

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

```

`GetStringAsync()`发送 GET 请求到指定的 Uri，并在异步操作中将响应主体作为字符串返回。

```cs
$ 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 请求

如果将使用 HTTP GET 方法请求指定的资源，则 HTTP HEAD 方法请求返回的标头。

`Program.cs`

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

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

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

            Console.WriteLine(result);
        }
    }
}

```

该示例发出 HEAD 请求。

```cs
$ dotnet run
StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1,
Content: System.Net.Http.HttpConnectionResponseContent, Headers:
{
    Server: nginx/1.6.2
    Date: Sat, 12 Oct 2019 19:55:14 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
}

```

这是响应的标题字段。

## C# `HttpClient` POST 请求

HTTP POST 方法将数据发送到服务器。 请求正文的类型由`Content-Type`标头指示。

```cs
$ dotnet add package Newtonsoft.Json

```

我们需要添加`Newtonsoft.Json`包来处理 JSON 数据。

`Program.cs`

```cs
using System;
using System.Text;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace HttpClientPost
{
    class Person
    {
        public string Name { get; set; }
        public string Occupation { get; set; }

        public override string ToString()
        {
            return $"{Name}: {Occupation}";
        }
    }

    class Program
    {
        static async Task Main(string[] args)
        {
            var person = new Person();
            person.Name = "John Doe";
            person.Occupation = "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);
        }
    }
}

```

在示例中，我们将 POST 请求发送到`https://httpbin.org/post`网站，该网站是面向开发人员的在线测试服务。

```cs
var person = new Person();
person.Name = "John Doe";
person.Occupation = "gardener";

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

```

我们借助`Newtonsoft.Json`包将对象转换为 JSON 数据。

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

```

我们使用`PostAsync()`方法发送异步 POST 请求。

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

```

我们读取返回的数据并将其打印到控制台。

```cs
$ 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"
    },
    "json": {
    "Name": "John Doe",
    "Occupation": "gardener"
    },
    ...
    "url": "https://httpbin.org/post"
}

```

This is the output.

## C# `HttpClient` JSON 请求

JSON（JavaScript 对象表示法）是一种轻量级的数据交换格式。 这种格式对于人类来说很容易读写，对于机器来说，解析和生成都很容易。 它是 XML 的较不冗长且更易读的替代方案。 JSON 的官方互联网媒体类型为`application/json`。

`Program.cs`

```cs
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json;

namespace HttpClientJson
{
    class Contributor
    {
        public string Login { get; set; }
        public short Contributions { get; set; }

        public override string ToString()
        {
            return $"{Login,20}: {Contributions} contributions";
        }
    }

    class Program
    {
        private static async Task Main()
        {
            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);
        }
    }
}

```

该示例生成对 Github 的 GET 请求。 它找出了 Symfony 框架的主要贡献者。 它使用`Newtonsoft.Json`处理 JSON。

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

```

在请求标头中，我们指定用户代理。

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

```

在`accept`标头值中，我们告诉 JSON 是可接受的响应类型。

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

```

我们生成一个请求并异步读取内容。

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

```

我们使用`JsonConvert.DeserializeObject()`方法将 JSON 响应转换为`Contributor`对象的列表。

## C# `HttpClient`下载图像

`GetByteArrayAsync()`将 GET 请求发送到指定的 Uri，并在异步操作中将响应主体作为字节数组返回。

`Program.cs`

```cs
using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;

namespace HttpClientDownloadImage
{
    class Program
    {
        static async Task Main(string[] args)
        {
            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);
            File.WriteAllBytes(localPath, imageBytes);
        }
    }
}

```

在示例中，我们从`webcode.me`网站下载图像。 图像被写入用户的`Documents`文件夹。

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

```

`GetByteArrayAsync()`将图像作为字节数组返回。

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

```

我们用`GetFolderPath()`方法确定`Documents`文件夹。

```cs
File.WriteAllBytes(localPath, imageBytes);

```

使用`File.WriteAllBytes()`方法将字节写入磁盘。

## C# `HttpClient` 基本认证

在 HTTP 协议中，基本访问认证是 HTTP 用户代理（例如 Web 浏览器或控制台应用）在发出请求时提供用户名和密码的方法。 在基本 HTTP 认证中，请求包含`Authorization: Basic <credentials>`形式的标头字段，其中凭据是由单个冒号`:`连接的 id 和密码的 base64 编码。

> **注意**：凭证未加密； 因此，必须将 HTTP 基本认证与 HTTPS 协议一起使用。

HTTP 基本认证是用于实施对 Web 资源的访问控制的最简单技术。 它不需要 cookie，会话标识符或登录页面； 相反，HTTP 基本认证使用 HTTP 标头中的标准字段。

`Program.cs`

```cs
using System;
using System.Text;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace HttpClientAuth
{
    class Program
    {
        static async Task Main(string[] args)
        {
            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);
        }
    }
}

```

该示例将凭据发送到`httpbin.org`网站。

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

```

在这里，我们构建认证标头。

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

```

该 URL 包含认证详细信息，因为我们在`httpbin.org`网站上对其进行了测试。 这样，我们不需要设置自己的服务器。 当然，认证详细信息永远不会放在 URL 中。

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

```

This is the output.

在本教程中，我们使用 C# `HttpClient`创建 HTTP 请求。

您可能也对以下相关教程感兴趣： [C# 教程](/lang/csharp/)， [MySQL C# 教程](/db/mysqlcsharptutorial/)， [C# 中的日期和时间](/articles/csharpdatetime/)， [C# ](/articles/csharpreadwebpage/)或 [C# Winforms 教程](/gui/csharpwinforms/)。