.NET 4.5 引入 `System.Net.Http.HttpClient`,設計理念貼近 HTTP 簡潔本質。本文對比 `HttpWebRequest` 與 `HttpClient` 關鍵差異,重點解決 `UserAgent` 設定無屬性的問題。
var request = (HttpWebRequest)WebRequest.Create(url);
request.UserAgent = "CNBlogs"; // 直接屬性
var client = new HttpClient();
// client.UserAgent = "CNBlogs"; // 編譯錯誤:無此屬性
// 發現 DefaultRequestHeaders.UserAgent 僅有 getter
// client.DefaultRequestHeaders.UserAgent // 唯讀集合
var client = new HttpClient();
client.DefaultRequestHeaders.UserAgent.ParseAdd("CNBlogs/1.0 (+https://example.com)");
// 或
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("CNBlogs", "1.0"));
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("(+https://example.com)"));
`UserAgent` 標頭值為 `ProductInfoHeaderValue` 集合,需用 `ParseAdd` 或 `Add` 方法。
| 特性 | HttpWebRequest | HttpClient |
|---|---|---|
| API 風格 | 同步/APM (Begin/End) | Task-based 非同步 (await) |
| 連線管理 | 手動/ConnectionGroup | 內建連線池、自動重用 |
| 標頭操作 | 字串索引器 | 強型別 `HttpRequestHeaders` |
| 內容序列化 | 手動寫入 Stream | `HttpContent` 衍生類 (`StringContent`, `FormUrlEncodedContent`, `MultipartFormDataContent`) |
| 可測試性 | 難 (靜態/密封) | 易 (可 Mock `HttpMessageHandler`) |
// POST Form Data
// HttpWebRequest
var req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
using (var sw = new StreamWriter(req.GetRequestStream()))
sw.Write("a=1&b=2");
// HttpClient
var client = new HttpClient();
var form = new Dictionary<string,string> {{"a","1"},{"b","2"}};
var response = await client.PostAsync(url, new FormUrlEncodedContent(form));
// POST JSON
// HttpClient
var json = JsonConvert.SerializeObject(model);
var response = await client.PostAsync(url, new StringContent(json, Encoding.UTF8, "application/json"));
// 下載檔案
// HttpClient
using (var stream = await client.GetStreamAsync(url))
using (var file = File.Create(localPath))
await stream.CopyToAsync(file);
// 記錄請求/回應、重試、熔斷
public class LoggingHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken ct)
{
_logger.LogRequest(request);
var response = await base.SendAsync(request, ct);
_logger.LogResponse(response);
return response;
}
}
// 註冊
var client = new HttpClient(new LoggingHandler(new HttpClientHandler()));
HttpClient 是現代 .NET HTTP 呼叫的標準入口,掌握 `HttpRequestHeaders`、`HttpContent`、`HttpMessageHandler` 三大核心抽象,即可靈活應對各種整合場景。