介绍:为什么在 C# 中需要正确的 HTTP 客户端
在现代 .NET 平台开发中,几乎没有任何应用程序能避免与远程服务器交互。无论是从 REST API 获取数据、向 Web 服务器发送表单还是下载文件,所有这些都需要正确实现 HTTP 请求。在 C# 中有几种方法,但最现代且推荐使用的是来自 System.Net.Http 命名空间的 HttpClient 类。在本文中,我们将分析如何在 C# 中正确创建 HTTP 客户端,避免典型错误并编写高效代码。
C# (.NET) 中用于 HTTP 工作的主要类
在进入示例之前,了解 .NET 平台提供了哪些工具很重要。主要类有:
- HttpClient — 用于发送请求和接收响应的主要类。它应该作为单例使用(整个应用程序一个实例)。
- HttpRequestMessage — 允许详细配置请求:方法、标头、正文、协议版本。
- HttpResponseMessage — 包含来自服务器的响应:状态、标头、正文。
- HttpContent — 用于表示请求或响应正文的基类(例如
StringContent、ByteArrayContent、MultipartFormDataContent)。
关键规则:不要为每个请求创建新的 HttpClient 实例。这会导致套接字耗尽和性能下降。使用一个静态或注入的实例。
配置 HttpClient:基本示例
考虑最小配置。创建一个 HttpClient 实例并设置基本地址:
using System;
using System.Net.Http;
using System.Threading.Tasks;
public class ApiService
{
private static readonly HttpClient client = new HttpClient();
public ApiService()
{
client.BaseAddress = new Uri("https://api.example.com/");
client.DefaultRequestHeaders.Add("User-Agent", "C# HttpClient App");
client.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
}
public async Task<string> GetDataAsync(string endpoint)
{
HttpResponseMessage response = await client.GetAsync(endpoint);
response.EnsureSuccessStatusCode(); // 出错时抛出异常
return await response.Content.ReadAsStringAsync();
}
}
注意 response.EnsureSuccessStatusCode() — 这是检查请求是否成功(2xx 状态码)的简单方法。
C# 中 HTTP 请求的实践示例
现在让我们进入具体场景。我们将考虑 GET 和 POST 请求,以及标头处理和错误处理。
1. 带参数的 GET 请求
要在查询字符串中传递参数,可以使用来自 Microsoft.AspNetCore.WebUtilities 的 QueryHelpers 集合,或者手动构建 URL。下面是手动构建的示例:
public async Task<string> SearchUsersAsync(string name, int page)
{
var query = $"/users?name={Uri.EscapeDataString(name)}&page={page}";
HttpResponseMessage response = await client.GetAsync(query);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
始终使用 Uri.EscapeDataString() 来转义参数,以避免特殊字符导致的错误。
2. 带 JSON 正文的 POST 请求
要以 JSON 格式发送数据,方便使用 System.Text.Json 库(或 Newtonsoft.Json)。将对象转换为 JSON 并发送:
using System.Text;
using System.Text.Json;
public