伺服器端代碼需主動呼叫外部 HTTP API(支付回調、第三方介面、微服務聚合)。本文詳細示範 HttpWebRequest 同步 GET/POST 完整流程,含參數編碼、流處理、異常處理、超時控制。
using System.Net; // HttpWebRequest, HttpWebResponse
using System.IO; // Stream, StreamReader, StreamWriter
using System.Text; // Encoding
public string HttpGet(string url) {
var uri = new Uri(url);
if (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps)
throw new ArgumentException("僅支援 HTTP/HTTPS");
var request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "GET";
request.Timeout = 10000; // 10 秒
request.UserAgent = "MyApp/1.0";
using (var response = (HttpWebResponse)request.GetResponse())
using (var stream = response.GetResponseStream())
using (var reader = new StreamReader(stream, Encoding.UTF8))
return reader.ReadToEnd();
}
public string HttpPost(string url, Dictionary<string, string> parameters) {
var uri = new Uri(url);
var request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.Timeout = 15000;
// 參數編碼:UrlEncode 每個值,再用 & 連接
var postData = string.Join("&",
parameters.Select(kvp => $"{WebUtility.UrlEncode(kvp.Key)}={WebUtility.UrlEncode(kvp.Value)}"));
var byteData = Encoding.UTF8.GetBytes(postData);
request.ContentLength = byteData.Length;
using (var stream = request.GetRequestStream())
stream.Write(byteData, 0, byteData.Length);
using (var response = (HttpWebResponse)request.GetResponse())
using (var stream = response.GetResponseStream())
using (var reader = new StreamReader(stream, Encoding.UTF8))
return reader.ReadToEnd();
}
| 陷阱 | 症狀 | 解決方案 |
|---|---|---|
| 參數未 UrlEncode | 特殊字符 (+, &, =, 空格, 中文) 導致伺服器解析錯誤 | WebUtility.UrlEncode 每個值(.NET 4.5+) |
| 未設定 ContentLength | POST 請求被伺服器拒絕 (411 Length Required) | 寫入流前設定 request.ContentLength = byteData.Length |
| 同步阻塞執行緒 | 高併發下執行緒池耗盡、回應延遲 | 改用 HttpClient + async/await(.NET 4.5+) |
| 忽略 SSL 憑證驗證 | 測試環境自簽憑證拋出異常 | ServicePointManager.ServerCertificateValidationCallback += (s, c, ch, e) => true;(僅開發/測試) |
| 未關閉響應流 | 連線洩漏、連線池耗盡 | using 區塊確保釋放 |
| 編碼不一致 | 中文亂碼 | 統一 UTF-8:請求流、響應流、UrlEncode 均指定 Encoding.UTF8 |
private static readonly HttpClient _client = new HttpClient { Timeout = TimeSpan.FromSeconds(15) };
public async Task<string> GetAsync(string url)
=> await _client.GetStringAsync(url);
public async Task<string> PostAsync(string url, Dictionary<string, string> parameters) {
var content = new FormUrlEncodedContent(parameters); // 自動 UrlEncode
var response = await _client.PostAsync(url, content);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
HttpClient 為線程安全、支援連線池、非同步優先、自動處理壓縮/重導向/Keep-Alive。HttpClient 設計為長壽命)。IHttpClientFactory 管理生命週期、啟用 Polly 重試/熔斷。EnsureSuccessStatusCode),處理 4xx/5xx 業務邏輯。Timeout,避免慢速下游拖垮上游。