C# 网络编程-关于HttpClient使用方式(三)

前面有讲到比较底层一点的请求方式C# 网络编程-关于HttpWebRequest使用方式(二):,官方是推荐使用HttpClient的常用请求方式,可能为了在跨平台兼容吧,HttpClient涵盖GET、POST、PUT、DELETE等方法


一、基础请求方式

1. GET 请求(获取数据)
csharp 复制代码
using System.Net.Http;
using System.Threading.Tasks;

public async Task<string> GetAsStringAsync(string url)
{
    using (HttpClient client = new HttpClient())
    {
        try
        {
            HttpResponseMessage response = await client.GetAsync(url);
            response.EnsureSuccessStatusCode(); // 检查HTTP状态码(如200)
            return await response.Content.ReadAsStringAsync();
        }
        catch (HttpRequestException ex)
        {
            Console.WriteLine($"请求失败: {ex.Message}");
            return null;
        }
    }
}
2. POST 请求(提交数据)
csharp 复制代码
public async Task<string> PostAsStringAsync(string url, string jsonContent)
{
    using (HttpClient client = new HttpClient())
    {
        try
        {
            // 创建JSON内容
            StringContent content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
            HttpResponseMessage response = await client.PostAsync(url, content);
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync();
        }
        catch (HttpRequestException ex)
        {
            Console.WriteLine($"请求失败: {ex.Message}");
            return null;
        }
    }
}
3. PUT 请求(更新数据)
csharp 复制代码
public async Task<string> PutAsStringAsync(string url, string jsonContent)
{
    using (HttpClient client = new HttpClient())
    {
        try
        {
            StringContent content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
            HttpResponseMessage response = await client.PutAsync(url, content);
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync();
        }
        catch (HttpRequestException ex)
        {
            Console.WriteLine($"请求失败: {ex.Message}");
            return null;
        }
    }
}
4. DELETE 请求(删除数据)
csharp 复制代码
public async Task<string> DeleteAsStringAsync(string url)
{
    using (HttpClient client = new HttpClient())
    {
        try
        {
            HttpResponseMessage response = await client.DeleteAsync(url);
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync();
        }
        catch (HttpRequestException ex)
        {
            Console.WriteLine($"请求失败: {ex.Message}");
            return null;
        }
    }
}

二、配置与最佳实践

1. 配置超时时间
csharp 复制代码
HttpClient client = new HttpClient();
client.Timeout = TimeSpan.FromSeconds(10); // 设置超时时间为10秒
2. 添加请求头(如Authorization、Content-Type)
csharp 复制代码
client.DefaultRequestHeaders.Add("Authorization", "Bearer your_token");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
3. 避免重复创建HttpClient实例
  • 问题 :频繁创建HttpClient可能导致Socket资源耗尽。

  • 解决方案 :在应用程序生命周期中重用单个HttpClient实例:

    csharp 复制代码
    // 使用单例模式
    private static readonly HttpClient _client = new HttpClient();
4. 使用HttpClientFactory(推荐在ASP.NET Core中使用)
csharp 复制代码
// 在Startup.cs中配置:
services.AddHttpClient<IMyService, MyService>()
    .SetBaseAddress(new Uri("https://api.example.com"))
    .AddPolicyHandler(HttpPolicyRegistry); // 添加重试、超时等策略

// 在服务中注入:
public class MyService : IMyService
{
    private readonly HttpClient _client;
    public MyService(HttpClient client) => _client = client;
}

三、处理响应与异常

1. 处理响应内容
  • 字符串响应 :

    csharp 复制代码
    string result = await response.Content.ReadAsStringAsync();
  • JSON反序列化 :

    csharp 复制代码
    var myObject = await response.Content.ReadFromJsonAsync<MyModel>();
    // 或使用Newtonsoft.Json:
    var myObject = JsonConvert.DeserializeObject<MyModel>(result);
2. 异常处理
csharp 复制代码
try
{
    // 发送请求
}
catch (HttpRequestException ex) when (ex.Message.Contains("404"))
{
    Console.WriteLine("资源未找到");
}
catch (TaskCanceledException ex)
{
    Console.WriteLine("请求超时");
}
catch (Exception ex)
{
    Console.WriteLine($"未知错误: {ex.Message}");
}

四、高级用法

1. 上传文件
csharp 复制代码
public async Task UploadFileAsync(string url, string filePath)
{
    using (HttpClient client = new HttpClient())
    {
        var content = new MultipartFormDataContent();
        var fileContent = new ByteArrayContent(File.ReadAllBytes(filePath));
        fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
        {
            Name = "file",
            FileName = Path.GetFileName(filePath)
        };
        content.Add(fileContent);
        
        await client.PostAsync(url, content);
    }
}
2. 发送表单数据(application/x-www-form-urlencoded)
csharp 复制代码
public async Task PostFormAsync(string url, Dictionary<string, string> formData)
{
    var content = new FormUrlEncodedContent(formData);
    await client.PostAsync(url, content);
}
3. 使用JSON序列化(System.Text.Json)
csharp 复制代码
var myObject = new MyModel { Name = "Test" };
var jsonContent = JsonSerializer.Serialize(myObject);
var content = new StringContent(jsonContent, Encoding.UTF8, "application/json");

五、完整示例

csharp 复制代码
public class ApiService
{
    private readonly HttpClient _client;

    public ApiService(HttpClient client)
    {
        _client = client;
    }

    public async Task<T> GetAsync<T>(string endpoint)
    {
        var response = await _client.GetAsync(endpoint);
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadFromJsonAsync<T>();
    }

    public async Task<T> PostAsync<T>(string endpoint, object data)
    {
        var content = new StringContent(JsonSerializer.Serialize(data), Encoding.UTF8, "application/json");
        var response = await _client.PostAsync(endpoint, content);
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadFromJsonAsync<T>();
    }
}

关键注意事项

  1. 异步编程 :始终使用async/await,避免阻塞。
  2. 资源管理 :重用HttpClient实例,避免创建过多实例。
  3. 异常处理 :捕获HttpRequestException和TaskCanceledException。
  4. 安全性 :对于敏感操作(如身份验证),使用HttpClientFactory和策略模式。
相关推荐
制造业的搬运工10 分钟前
车载 PCB 打样周期与选型指南:从 IATF 16949 到 IPC-6012 的 5 个硬指标
大数据·网络·人工智能·制造·pcb工艺
bksczm14 分钟前
0基础面试2
网络·面试·职场和发展
wdfk_prog17 分钟前
Wi-Fi Direct教程 02:从 wpa_cli main() 到 P2P_FIND——用源码注释追踪 CLI 控制命令发送
运维·服务器·网络·网络协议·ubuntu·p2p·wifi-direct
“AI国潮设计-小江”24 分钟前
【SDXL实战】用AI生成“财神爷蛋糕×英歌舞人物”潮汕国潮甜品IP,附Prompt与批量生成思路
开发语言·人工智能·python·aigc
繁华的地方不一定留下你的脚印25 分钟前
C++线程如何安全停止与唤醒:std::jthread、stop_token与condition_variable
开发语言·c++
caoerzhong34 分钟前
跨境海外仓怎么管:JeeWMS 开源 Java 仓库管理系统打通头程、海外仓与尾程
java·开发语言·开源
码云数智-大飞39 分钟前
新手写 Python 代码,如何规范命名、减少 Bug
开发语言·python·php
福兮说1 小时前
JS 正则的六个坑:带 g 的 test() 一真一假、空匹配死循环、replace 里的 $
开发语言·前端·javascript·正则表达式
码艺-Alimjan1 小时前
Web 网站打包桌面应用的另一种方式,超级简单(C# exe 33Kb)
开发语言·前端·c#
沫璃染墨1 小时前
《从零入门Linux系统篇(五十一):线程篇·四——pthread线程库详解:从线程创建到终止与分离》
linux·运维·服务器·开发语言·c++·系统架构·线程