【CSharp】高级HTTP请求辅助类 - HttpHelper
主要功能
支持所有HTTP方法
GET,POST,PUT,DELETE,PATCH每个方法都有同步和异步版本
多种内容类型支持
JSON (
application/json)Form表单 (
application/x-www-form-urlencoded)文件上传 (
multipart/form-data)
灵活的请求头管理
支持每个请求自定义请求头
支持全局默认请求头
提供扩展方法快速添加常用请求头
完善的响应处理
自动JSON反序列化
详细的错误信息
HTTP状态码
响应头信息
代码示例
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace YourNamespace.Helpers
{
/// <summary>
/// HTTP请求辅助类,支持同步和异步操作
/// </summary>
public class HttpHelper : IDisposable
{
private static readonly Lazy<HttpClient> _lazyHttpClient = new Lazy<HttpClient>(() => CreateHttpClient());
private static HttpClient DefaultHttpClient => _lazyHttpClient.Value;
private readonly HttpClient _httpClient;
private bool _disposed;
#region 构造函数
/// <summary>
/// 使用默认HttpClient实例
/// </summary>
public HttpHelper()
{
_httpClient = DefaultHttpClient;
}
/// <summary>
/// 使用自定义HttpClient实例
/// </summary>
public HttpHelper(HttpClient httpClient)
{
_httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
}
/// <summary>
/// 使用自定义配置创建HttpClient
/// </summary>
public HttpHelper(HttpClientConfig config)
{
_httpClient = CreateHttpClient(config);
}
#endregion
#region 静态工厂方法
private static HttpClient CreateHttpClient(HttpClientConfig config = null)
{
// 忽略SSL证书验证(生产环境慎用)
// 使用全局方式,兼容 .NET Framework 4.5+
if (config?.IgnoreSslErrors ?? false)
{
ServicePointManager.ServerCertificateValidationCallback =
new RemoteCertificateValidationCallback(
(sender, certificate, chain, sslPolicyErrors) => true
);
// 同时设置安全协议(支持 TLS 1.2)
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
| SecurityProtocolType.Tls11
| SecurityProtocolType.Tls;
}
var handler = new HttpClientHandler
{
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
UseCookies = config?.UseCookies ?? true,
AllowAutoRedirect = config?.AllowAutoRedirect ?? true,
MaxAutomaticRedirections = config?.MaxRedirections ?? 50
};
// .NET Framework 4.7.1+ 可以使用此方式
#if NET471_OR_GREATER || NETCOREAPP || NETSTANDARD2_1_OR_GREATER
if (config?.IgnoreSslErrors ?? false)
{
handler.ServerCertificateCustomValidationCallback =
(message, cert, chain, errors) => true;
}
#endif
var client = new HttpClient(handler)
{
Timeout = TimeSpan.FromSeconds(config?.TimeoutSeconds ?? 100)
};
// 设置默认请求头
if (config?.DefaultHeaders != null)
{
foreach (var header in config.DefaultHeaders)
{
client.DefaultRequestHeaders.TryAddWithoutValidation(header.Key, header.Value);
}
}
return client;
}
#endregion
#region GET 请求
/// <summary>
/// 异步GET请求
/// </summary>
public async Task<HttpResponse<string>> GetAsync(
string url,
Dictionary<string, string> headers = null,
CancellationToken cancellationToken = default)
{
return await SendRequestAsync(HttpMethod.Get, url, null, headers, cancellationToken);
}
/// <summary>
/// 异步GET请求并反序列化为指定类型
/// </summary>
public async Task<HttpResponse<T>> GetAsync<T>(
string url,
Dictionary<string, string> headers = null,
CancellationToken cancellationToken = default)
{
var response = await GetAsync(url, headers, cancellationToken);
return ConvertResponse<T>(response);
}
/// <summary>
/// 同步GET请求
/// </summary>
public HttpResponse<string> Get(string url, Dictionary<string, string> headers = null)
{
return GetAsync(url, headers).GetAwaiter().GetResult();
}
/// <summary>
/// 同步GET请求并反序列化为指定类型
/// </summary>
public HttpResponse<T> Get<T>(string url, Dictionary<string, string> headers = null)
{
return GetAsync<T>(url, headers).GetAwaiter().GetResult();
}
#endregion
#region POST 请求
/// <summary>
/// 异步POST请求(JSON)
/// </summary>
public async Task<HttpResponse<string>> PostJsonAsync(
string url,
object data,
Dictionary<string, string> headers = null,
CancellationToken cancellationToken = default)
{
var content = CreateJsonContent(data);
return await SendRequestAsync(HttpMethod.Post, url, content, headers, cancellationToken);
}
/// <summary>
/// 异步POST请求(JSON)并反序列化
/// </summary>
public async Task<HttpResponse<T>> PostJsonAsync<T>(
string url,
object data,
Dictionary<string, string> headers = null,
CancellationToken cancellationToken = default)
{
var response = await PostJsonAsync(url, data, headers, cancellationToken);
return ConvertResponse<T>(response);
}
/// <summary>
/// 同步POST请求(JSON)
/// </summary>
public HttpResponse<string> PostJson(string url, object data, Dictionary<string, string> headers = null)
{
return PostJsonAsync(url, data, headers).GetAwaiter().GetResult();
}
/// <summary>
/// 同步POST请求(JSON)并反序列化
/// </summary>
public HttpResponse<T> PostJson<T>(string url, object data, Dictionary<string, string> headers = null)
{
return PostJsonAsync<T>(url, data, headers).GetAwaiter().GetResult();
}
/// <summary>
/// 异步POST请求(Form表单)
/// </summary>
public async Task<HttpResponse<string>> PostFormAsync(
string url,
Dictionary<string, string> formData,
Dictionary<string, string> headers = null,
CancellationToken cancellationToken = default)
{
var content = new FormUrlEncodedContent(formData);
return await SendRequestAsync(HttpMethod.Post, url, content, headers, cancellationToken);
}
/// <summary>
/// 同步POST请求(Form表单)
/// </summary>
public HttpResponse<string> PostForm(
string url,
Dictionary<string, string> formData,
Dictionary<string, string> headers = null)
{
return PostFormAsync(url, formData, headers).GetAwaiter().GetResult();
}
/// <summary>
/// 异步POST请求(Multipart文件上传)
/// </summary>
public async Task<HttpResponse<string>> PostFileAsync(
string url,
byte[] fileContent,
string fileName,
Dictionary<string, string> formData = null,
Dictionary<string, string> headers = null,
CancellationToken cancellationToken = default)
{
var content = new MultipartFormDataContent();
// 添加文件
var fileContent2 = new ByteArrayContent(fileContent);
fileContent2.Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream");
content.Add(fileContent2, "file", fileName);
// 添加其他表单数据
if (formData != null)
{
foreach (var item in formData)
{
content.Add(new StringContent(item.Value), item.Key);
}
}
return await SendRequestAsync(HttpMethod.Post, url, content, headers, cancellationToken);
}
#endregion
#region PUT 请求
/// <summary>
/// 异步PUT请求(JSON)
/// </summary>
public async Task<HttpResponse<string>> PutJsonAsync(
string url,
object data,
Dictionary<string, string> headers = null,
CancellationToken cancellationToken = default)
{
var content = CreateJsonContent(data);
return await SendRequestAsync(HttpMethod.Put, url, content, headers, cancellationToken);
}
/// <summary>
/// 异步PUT请求(JSON)并反序列化
/// </summary>
public async Task<HttpResponse<T>> PutJsonAsync<T>(
string url,
object data,
Dictionary<string, string> headers = null,
CancellationToken cancellationToken = default)
{
var response = await PutJsonAsync(url, data, headers, cancellationToken);
return ConvertResponse<T>(response);
}
/// <summary>
/// 同步PUT请求(JSON)
/// </summary>
public HttpResponse<string> PutJson(string url, object data, Dictionary<string, string> headers = null)
{
return PutJsonAsync(url, data, headers).GetAwaiter().GetResult();
}
/// <summary>
/// 同步PUT请求(JSON)并反序列化
/// </summary>
public HttpResponse<T> PutJson<T>(string url, object data, Dictionary<string, string> headers = null)
{
return PutJsonAsync<T>(url, data, headers).GetAwaiter().GetResult();
}
#endregion
#region DELETE 请求
/// <summary>
/// 异步DELETE请求
/// </summary>
public async Task<HttpResponse<string>> DeleteAsync(
string url,
Dictionary<string, string> headers = null,
CancellationToken cancellationToken = default)
{
return await SendRequestAsync(HttpMethod.Delete, url, null, headers, cancellationToken);
}
/// <summary>
/// 异步DELETE请求并反序列化
/// </summary>
public async Task<HttpResponse<T>> DeleteAsync<T>(
string url,
Dictionary<string, string> headers = null,
CancellationToken cancellationToken = default)
{
var response = await DeleteAsync(url, headers, cancellationToken);
return ConvertResponse<T>(response);
}
/// <summary>
/// 同步DELETE请求
/// </summary>
public HttpResponse<string> Delete(string url, Dictionary<string, string> headers = null)
{
return DeleteAsync(url, headers).GetAwaiter().GetResult();
}
/// <summary>
/// 同步DELETE请求并反序列化
/// </summary>
public HttpResponse<T> Delete<T>(string url, Dictionary<string, string> headers = null)
{
return DeleteAsync<T>(url, headers).GetAwaiter().GetResult();
}
#endregion
#region PATCH 请求
/// <summary>
/// 异步PATCH请求(JSON)
/// </summary>
public async Task<HttpResponse<string>> PatchJsonAsync(
string url,
object data,
Dictionary<string, string> headers = null,
CancellationToken cancellationToken = default)
{
var content = CreateJsonContent(data);
return await SendRequestAsync(new HttpMethod("PATCH"), url, content, headers, cancellationToken);
}
/// <summary>
/// 异步PATCH请求(JSON)并反序列化
/// </summary>
public async Task<HttpResponse<T>> PatchJsonAsync<T>(
string url,
object data,
Dictionary<string, string> headers = null,
CancellationToken cancellationToken = default)
{
var response = await PatchJsonAsync(url, data, headers, cancellationToken);
return ConvertResponse<T>(response);
}
/// <summary>
/// 同步PATCH请求(JSON)
/// </summary>
public HttpResponse<string> PatchJson(string url, object data, Dictionary<string, string> headers = null)
{
return PatchJsonAsync(url, data, headers).GetAwaiter().GetResult();
}
#endregion
#region 核心请求方法
/// <summary>
/// 发送HTTP请求的核心方法
/// </summary>
private async Task<HttpResponse<string>> SendRequestAsync(
HttpMethod method,
string url,
HttpContent content,
Dictionary<string, string> headers,
CancellationToken cancellationToken)
{
var response = new HttpResponse<string>();
try
{
using (var request = new HttpRequestMessage(method, url))
{
// 添加请求头
if (headers != null)
{
foreach (var header in headers)
{
request.Headers.TryAddWithoutValidation(header.Key, header.Value);
}
}
// 添加请求内容
if (content != null)
{
request.Content = content;
}
// 发送请求
using (var httpResponse = await _httpClient.SendAsync(request, cancellationToken))
{
response.StatusCode = (int)httpResponse.StatusCode;
response.IsSuccess = httpResponse.IsSuccessStatusCode;
response.Content = await httpResponse.Content.ReadAsStringAsync();
response.Headers = new Dictionary<string, string>();
// 获取响应头
foreach (var header in httpResponse.Headers)
{
response.Headers[header.Key] = string.Join(",", header.Value);
}
if (!httpResponse.IsSuccessStatusCode)
{
response.ErrorMessage = $"HTTP请求失败: {httpResponse.StatusCode} - {httpResponse.ReasonPhrase}";
}
}
}
}
catch (TaskCanceledException ex)
{
response.IsSuccess = false;
response.ErrorMessage = "请求超时";
response.Exception = ex;
}
catch (HttpRequestException ex)
{
response.IsSuccess = false;
response.ErrorMessage = $"HTTP请求异常: {ex.Message}";
response.Exception = ex;
}
catch (Exception ex)
{
response.IsSuccess = false;
response.ErrorMessage = $"请求发生异常: {ex.Message}";
response.Exception = ex;
}
return response;
}
#endregion
#region 辅助方法
/// <summary>
/// 创建JSON内容
/// </summary>
private StringContent CreateJsonContent(object data)
{
var json = data is string str ? str : JsonConvert.SerializeObject(data);
return new StringContent(json, Encoding.UTF8, "application/json");
}
/// <summary>
/// 转换响应类型
/// </summary>
private HttpResponse<T> ConvertResponse<T>(HttpResponse<string> response)
{
var result = new HttpResponse<T>
{
StatusCode = response.StatusCode,
IsSuccess = response.IsSuccess,
ErrorMessage = response.ErrorMessage,
Exception = response.Exception,
Headers = response.Headers
};
if (response.IsSuccess && !string.IsNullOrWhiteSpace(response.Content))
{
try
{
result.Data = JsonConvert.DeserializeObject<T>(response.Content);
}
catch (JsonException ex)
{
result.IsSuccess = false;
result.ErrorMessage = $"JSON反序列化失败: {ex.Message}";
result.Exception = ex;
}
}
return result;
}
#endregion
#region IDisposable
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing)
{
// 只有非默认实例才释放
if (_httpClient != DefaultHttpClient)
{
_httpClient?.Dispose();
}
}
_disposed = true;
}
#endregion
}
#region 配置类和响应类
/// <summary>
/// HttpClient配置
/// </summary>
public class HttpClientConfig
{
/// <summary>
/// 超时时间(秒)
/// </summary>
public int TimeoutSeconds { get; set; } = 100;
/// <summary>
/// 是否使用Cookie
/// </summary>
public bool UseCookies { get; set; } = true;
/// <summary>
/// 是否允许自动重定向
/// </summary>
public bool AllowAutoRedirect { get; set; } = true;
/// <summary>
/// 最大重定向次数
/// </summary>
public int MaxRedirections { get; set; } = 50;
/// <summary>
/// 是否忽略SSL证书错误(生产环境不建议使用)
/// </summary>
public bool IgnoreSslErrors { get; set; } = false;
/// <summary>
/// 默认请求头
/// </summary>
public Dictionary<string, string> DefaultHeaders { get; set; }
}
/// <summary>
/// HTTP响应结果
/// </summary>
public class HttpResponse<T>
{
/// <summary>
/// 是否成功
/// </summary>
public bool IsSuccess { get; set; }
/// <summary>
/// HTTP状态码
/// </summary>
public int StatusCode { get; set; }
/// <summary>
/// 响应内容(泛型)
/// </summary>
public T Data { get; set; }
/// <summary>
/// 原始响应内容(仅string类型)
/// </summary>
public string Content { get; set; }
/// <summary>
/// 错误信息
/// </summary>
public string ErrorMessage { get; set; }
/// <summary>
/// 异常信息
/// </summary>
public Exception Exception { get; set; }
/// <summary>
/// 响应头
/// </summary>
public Dictionary<string, string> Headers { get; set; }
}
#endregion
#region 扩展方法
/// <summary>
/// HttpHelper扩展方法
/// </summary>
public static class HttpHelperExtensions
{
/// <summary>
/// 添加Bearer Token
/// </summary>
public static Dictionary<string, string> WithBearerToken(this Dictionary<string, string> headers, string token)
{
headers = headers ?? new Dictionary<string, string>();
headers["Authorization"] = $"Bearer {token}";
return headers;
}
/// <summary>
/// 添加自定义请求头
/// </summary>
public static Dictionary<string, string> WithHeader(this Dictionary<string, string> headers, string key, string value)
{
headers = headers ?? new Dictionary<string, string>();
headers[key] = value;
return headers;
}
/// <summary>
/// 创建请求头
/// </summary>
public static Dictionary<string, string> CreateHeaders(string key, string value)
{
return new Dictionary<string, string> { { key, value } };
}
}
#endregion
}使用示例
// ============= 基本使用 =============
// 1. GET请求
var httpHelper = new HttpHelper();
// 异步方式
var response = await httpHelper.GetAsync<User>("https://api.example.com/users/1");
if (response.IsSuccess)
{
var user = response.Data;
}
// 同步方式
var response2 = httpHelper.Get<User>("https://api.example.com/users/1");
// 2. POST请求(JSON)
var loginForm = new { username = "admin", password = "123456" };
// 异步
var result = await httpHelper.PostJsonAsync<LoginResponse>(
"https://api.example.com/login",
loginForm
);
// 同步
var result2 = httpHelper.PostJson<LoginResponse>(
"https://api.example.com/login",
loginForm
);
// ============= 带请求头的使用 =============
// 方式1:直接传入字典
var headers = new Dictionary<string, string>
{
{ "Authorization", "Bearer your_token_here" },
{ "Custom-Header", "value" }
};
var response3 = await httpHelper.GetAsync<User>(
"https://api.example.com/users/1",
headers
);
// 方式2:使用扩展方法(推荐)
var response4 = await httpHelper.GetAsync<User>(
"https://api.example.com/users/1",
new Dictionary<string, string>()
.WithBearerToken("your_token_here")
.WithHeader("Custom-Header", "value")
);
// 方式3:创建请求头
var response5 = await httpHelper.GetAsync<User>(
"https://api.example.com/users/1",
HttpHelperExtensions.CreateHeaders("Authorization", "Bearer token")
);
// ============= 自定义配置 =============
var config = new HttpClientConfig
{
TimeoutSeconds = 30,
IgnoreSslErrors = true, // 仅用于测试环境
DefaultHeaders = new Dictionary<string, string>
{
{ "User-Agent", "MyApp/1.0" }
}
};
var customHelper = new HttpHelper(config);
// ============= 表单提交 =============
var formData = new Dictionary<string, string>
{
{ "username", "admin" },
{ "password", "123456" }
};
var formResult = await httpHelper.PostFormAsync(
"https://api.example.com/login",
formData
);
// ============= 文件上传 =============
byte[] fileBytes = File.ReadAllBytes("document.pdf");
var uploadResult = await httpHelper.PostFileAsync(
"https://api.example.com/upload",
fileBytes,
"document.pdf",
formData: new Dictionary<string, string> { { "description", "My file" } }
);
// ============= 完整的错误处理示例 =============
var response6 = await httpHelper.GetAsync<User>(
"https://api.example.com/users/1",
headers
);
if (response6.IsSuccess)
{
Console.WriteLine($"用户名: {response6.Data.Name}");
}
else
{
Console.WriteLine($"请求失败: {response6.ErrorMessage}");
Console.WriteLine($"状态码: {response6.StatusCode}");
if (response6.Exception != null)
{
Console.WriteLine($"异常: {response6.Exception.Message}");
}
}
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果


