最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#封裝HttpClient實(shí)現(xiàn)HTTP請求處理

 更新時間:2025年06月06日 11:06:33   作者:阿蒙Armon  
HttpClient作為.NET框架中處理HTTP請求的核心組件,為我們提供了強(qiáng)大而靈活的API,本文將介紹一個完整的HttpRequest類封裝實(shí)現(xiàn),并深入探討HTTP請求處理的最佳實(shí)踐

在現(xiàn)代的.NET應(yīng)用程序開發(fā)中,與外部服務(wù)進(jìn)行HTTP通信是一項(xiàng)常見需求。HttpClient作為.NET框架中處理HTTP請求的核心組件,為我們提供了強(qiáng)大而靈活的API。然而,直接使用原生的HttpClient可能會導(dǎo)致代碼重復(fù)、錯誤處理不完善等問題。為了提高代碼的可維護(hù)性和可測試性,我們通常會對HttpClient進(jìn)行封裝。本文將介紹一個完整的HttpRequest類封裝實(shí)現(xiàn),并深入探討HTTP請求處理的最佳實(shí)踐。

一、完整的HttpRequest類實(shí)現(xiàn)

首先,讓我們來看一下完整的HttpRequest類實(shí)現(xiàn)代碼:

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

???????public class Response
{
    public bool Success { get; set; }
    public string Message { get; set; }
    public object Data { get; set; }
    public HttpStatusCode StatusCode { get; set; }
}

public static class JsonConverterExtensions
{
    public static readonly JsonSerializerOptions SerializerSettings = new JsonSerializerOptions
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
        IgnoreNullValues = true,
        WriteIndented = false
    };
}

public class HttpRequest : IDisposable
{
    private readonly HttpClient client;
    private bool disposed = false;
    
    public HttpRequest(HttpClient client)
    {
        this.client = client ?? throw new ArgumentNullException(nameof(client));
    }
    
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    
    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                client?.Dispose();
            }
            disposed = true;
        }
    }
    
    public async Task<Response> GetAsync(string resource)
    {
        try
        {
            var response = await client.GetAsync(resource);
            return await ProcessResponseAsync(response);
        }
        catch (HttpRequestException ex)
        {
            return HandleException(ex);
        }
        catch (Exception ex)
        {
            return HandleUnexpectedException(ex);
        }
    }
    
    public async Task<Response> PostAsync(string resource, object body)
    {
        try
        {
            var content = CreateJsonContent(body);
            var response = await client.PostAsync(resource, content);
            return await ProcessResponseAsync(response);
        }
        catch (HttpRequestException ex)
        {
            return HandleException(ex);
        }
        catch (Exception ex)
        {
            return HandleUnexpectedException(ex);
        }
    }
    
    public async Task<Response> PutAsync(string resource, object body)
    {
        try
        {
            var content = CreateJsonContent(body);
            var response = await client.PutAsync(resource, content);
            return await ProcessResponseAsync(response);
        }
        catch (HttpRequestException ex)
        {
            return HandleException(ex);
        }
        catch (Exception ex)
        {
            return HandleUnexpectedException(ex);
        }
    }
    
    public async Task<Response> DeleteAsync(string resource)
    {
        try
        {
            var response = await client.DeleteAsync(resource);
            return await ProcessResponseAsync(response);
        }
        catch (HttpRequestException ex)
        {
            return HandleException(ex);
        }
        catch (Exception ex)
        {
            return HandleUnexpectedException(ex);
        }
    }
    
    public HttpRequest WithBaseAddress(string baseAddress)
    {
        if (!string.IsNullOrEmpty(baseAddress))
        {
            client.BaseAddress = new Uri(baseAddress);
        }
        return this;
    }
    
    public HttpRequest WithTimeout(TimeSpan timeout)
    {
        client.Timeout = timeout;
        return this;
    }
    
    public HttpRequest WithHeader(string name, string value)
    {
        if (!client.DefaultRequestHeaders.Contains(name))
        {
            client.DefaultRequestHeaders.Add(name, value);
        }
        return this;
    }
    
    public HttpRequest WithHeaders(IDictionary<string, string> headers)
    {
        if (headers != null)
        {
            foreach (var header in headers)
            {
                WithHeader(header.Key, header.Value);
            }
        }
        return this;
    }
    
    public HttpRequest WithAuthorization(string scheme, string parameter)
    {
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(scheme, parameter);
        return this;
    }
    
    public HttpRequest WithBearerToken(string token)
    {
        return WithAuthorization("Bearer", token);
    }
    
    private StringContent CreateJsonContent(object body)
    {
        if (body == null)
        {
            return new StringContent("{}", Encoding.UTF8, "application/json");
        }
        
        var json = JsonSerializer.Serialize(body, JsonConverterExtensions.SerializerSettings);
        return new StringContent(json, Encoding.UTF8, "application/json");
    }
    
    private async Task<Response> ProcessResponseAsync(HttpResponseMessage response)
    {
        var responseContent = await response.Content.ReadAsStringAsync();
        
        try
        {
            // 嘗試解析JSON響應(yīng)
            var responseObject = JsonSerializer.Deserialize<Response>(responseContent, JsonConverterExtensions.SerializerSettings);
            
            if (responseObject != null)
            {
                responseObject.StatusCode = response.StatusCode;
                return responseObject;
            }
        }
        catch (JsonException)
        {
            // 如果JSON解析失敗,創(chuàng)建一個基于HTTP狀態(tài)碼的響應(yīng)
        }
        
        // 對于非JSON響應(yīng)或解析失敗的情況
        return new Response
        {
            Success = response.IsSuccessStatusCode,
            Message = response.ReasonPhrase,
            StatusCode = response.StatusCode,
            Data = responseContent
        };
    }
    
    private Response HandleException(HttpRequestException ex)
    {
        return new Response
        {
            Success = false,
            Message = $"HTTP請求錯誤: {ex.Message}",
            StatusCode = ex.StatusCode ?? HttpStatusCode.InternalServerError,
            Data = ex
        };
    }
    
    private Response HandleUnexpectedException(Exception ex)
    {
        return new Response
        {
            Success = false,
            Message = $"處理請求時發(fā)生意外錯誤: {ex.Message}",
            StatusCode = HttpStatusCode.InternalServerError,
            Data = ex
        };
    }
}

二、設(shè)計(jì)思路與實(shí)現(xiàn)要點(diǎn)

1. 依賴注入與生命周期管理

這個封裝類采用了依賴注入模式,通過構(gòu)造函數(shù)接收一個HttpClient實(shí)例。這樣做有幾個重要好處:

遵循單一職責(zé)原則,HttpRequest類專注于HTTP請求處理

便于單元測試,可以輕松注入模擬的HttpClient

利用.NET的IHttpClientFactory進(jìn)行正確的HttpClient生命周期管理,避免資源泄漏

同時,類實(shí)現(xiàn)了IDisposable接口,確保在不再需要時正確釋放HttpClient資源。

2. 流暢接口設(shè)計(jì)

為了提供更友好的API體驗(yàn),封裝類實(shí)現(xiàn)了流暢接口模式:

var response = await new HttpRequest(httpClient)
    .WithBaseAddress("https://api.example.com")
    .WithBearerToken("your-token-here")
    .WithHeader("X-Custom-Header", "value")
    .PostAsync("/resource", new { Key = "value" });

這種鏈?zhǔn)秸{(diào)用方式使代碼更加簡潔易讀,同時保持了良好的可擴(kuò)展性。

3. 統(tǒng)一的錯誤處理

在每個HTTP方法中,我們都實(shí)現(xiàn)了統(tǒng)一的異常處理機(jī)制:

  • 捕獲HttpRequestException處理HTTP特定錯誤
  • 捕獲其他異常處理意外錯誤
  • 將所有錯誤轉(zhuǎn)換為統(tǒng)一的Response對象
  • 保留原始異常信息以便調(diào)試

這種統(tǒng)一的錯誤處理方式使上層調(diào)用代碼更加簡潔,無需重復(fù)處理各種異常情況。

4. 靈活的響應(yīng)處理

ProcessResponseAsync方法負(fù)責(zé)處理HTTP響應(yīng),它嘗試將響應(yīng)內(nèi)容解析為JSON格式的Response對象:

  • 如果解析成功,返回包含完整信息的Response對象
  • 如果解析失敗,創(chuàng)建一個基于HTTP狀態(tài)碼的Response對象
  • 始終保留原始響應(yīng)內(nèi)容和狀態(tài)碼信息

這種設(shè)計(jì)使封裝類能夠處理各種類型的HTTP響應(yīng),同時提供一致的返回格式。

三、實(shí)際使用示例

下面是一個使用這個封裝類的完整示例:

using System;
using System.Net.Http;
using System.Threading.Tasks;

???????public class Program
{
    public static async Task Main()
    {
        try
        {
            // 創(chuàng)建HttpClient實(shí)例(實(shí)際應(yīng)用中建議使用IHttpClientFactory)
            using var httpClient = new HttpClient();
            
            // 創(chuàng)建請求實(shí)例并配置
            var request = new HttpRequest(httpClient)
                .WithBaseAddress("https://api.example.com")
                .WithBearerToken("your-auth-token");
                
            // 發(fā)送GET請求
            var getResponse = await request.GetAsync("/api/users");
            Console.WriteLine($"GET請求結(jié)果: {getResponse.Success}, 狀態(tài)碼: {getResponse.StatusCode}");
            
            // 發(fā)送POST請求
            var postData = new { Name = "John Doe", Email = "john@example.com" };
            var postResponse = await request.PostAsync("/api/users", postData);
            Console.WriteLine($"POST請求結(jié)果: {postResponse.Success}, 狀態(tài)碼: {postResponse.StatusCode}");
            
            // 發(fā)送PUT請求
            var putData = new { Id = 1, Name = "Jane Doe" };
            var putResponse = await request.PutAsync("/api/users/1", putData);
            Console.WriteLine($"PUT請求結(jié)果: {putResponse.Success}, 狀態(tài)碼: {putResponse.StatusCode}");
            
            // 發(fā)送DELETE請求
            var deleteResponse = await request.DeleteAsync("/api/users/1");
            Console.WriteLine($"DELETE請求結(jié)果: {deleteResponse.Success}, 狀態(tài)碼: {deleteResponse.StatusCode}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"發(fā)生未處理的異常: {ex.Message}");
        }
    }
}

四、HttpClient使用最佳實(shí)踐

在使用HttpClient和這個封裝類時,還需要注意以下最佳實(shí)踐:

  • 使用IHttpClientFactory:在ASP.NET Core應(yīng)用中,始終使用IHttpClientFactory創(chuàng)建HttpClient實(shí)例,避免直接實(shí)例化HttpClient。
  • 設(shè)置合理的超時時間:默認(rèn)情況下,HttpClient的超時時間是100秒,根據(jù)實(shí)際需求調(diào)整這個值,防止長時間阻塞。
  • 處理取消請求:考慮實(shí)現(xiàn)請求取消機(jī)制,通過CancellationToken參數(shù)傳遞取消令牌。
  • 處理重試邏輯:對于臨時性網(wǎng)絡(luò)錯誤,考慮實(shí)現(xiàn)重試機(jī)制。可以使用Polly等庫來簡化重試策略的實(shí)現(xiàn)。
  • 監(jiān)控HTTP請求性能:記錄HTTP請求的執(zhí)行時間、成功率等指標(biāo),便于性能分析和問題排查。

通過這個完整的HttpRequest類封裝,我們可以更加高效、安全地處理HTTP通信,同時保持代碼的整潔和可維護(hù)性。希望這篇文章對你理解C#中的HTTP請求處理有所幫助。

這個實(shí)現(xiàn)提供了完整的HTTP請求功能,包括GET、POST、PUT、DELETE方法,以及靈活的請求配置和統(tǒng)一的響應(yīng)處理。

到此這篇關(guān)于C#封裝HttpClient實(shí)現(xiàn)HTTP請求處理的文章就介紹到這了,更多相關(guān)C#封裝HttpClient內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C#實(shí)現(xiàn)將字符串轉(zhuǎn)化為日期格式的方法詳解

    C#實(shí)現(xiàn)將字符串轉(zhuǎn)化為日期格式的方法詳解

    這篇文章主要為大家詳細(xì)介紹了C#如何使用DateTime結(jié)構(gòu)的ParseExact方法和Parse方法分別將字符串轉(zhuǎn)化為日期格式,有需要的小伙伴可以了解一下
    2024-01-01
  • C# 去除首尾字符或字符串的方法

    C# 去除首尾字符或字符串的方法

    C# 去除首尾字符或字符串的方法,需要的朋友可以參考一下
    2013-04-04
  • C#使用GZipStream實(shí)現(xiàn)文件的壓縮與解壓

    C#使用GZipStream實(shí)現(xiàn)文件的壓縮與解壓

    這篇文章主要為大家詳細(xì)介紹了C#使用GZipStream實(shí)現(xiàn)文件的壓縮與解壓,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-10-10
  • C++實(shí)現(xiàn)日期類的示例詳解

    C++實(shí)現(xiàn)日期類的示例詳解

    這篇文章主要為大家詳細(xì)介紹了四個C++常用的日期類的實(shí)現(xiàn),文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)C++有一定的幫助,需要的可以參考一下
    2023-02-02
  • C#串口關(guān)閉時主界面卡死的原因分析和解決方案

    C#串口關(guān)閉時主界面卡死的原因分析和解決方案

    最近在使用SerialPort類開發(fā)一個串口調(diào)試工具時,遇到了一個經(jīng)典但令人頭疼的問題:點(diǎn)擊關(guān)閉串口按鈕后,UI 界面直接卡死(假死),本文將帶你從現(xiàn)象出發(fā),深入.NET源碼,一步步揭開這個界面卡死背后的真相,并提供一個優(yōu)雅且根本性的解決方案,需要的朋友可以參考下
    2025-11-11
  • Unity游戲開發(fā)之射擊小游戲的實(shí)現(xiàn)

    Unity游戲開發(fā)之射擊小游戲的實(shí)現(xiàn)

    本篇文章為大家?guī)硪粋€橫版2D射擊小游戲,游戲制作超級簡單,玩法一學(xué)就會。文中的示例代碼講解詳細(xì),快跟隨小編一起動手試一試
    2022-03-03
  • C#?wpf實(shí)現(xiàn)任意控件更多拖動功能

    C#?wpf實(shí)現(xiàn)任意控件更多拖動功能

    這篇文章主要為大家詳細(xì)介紹了C#?wpf如何實(shí)現(xiàn)任意控件(包括窗口)更多拖動功能,文中的示例代碼講解詳細(xì),有興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-11-11
  • C#使用System.Environment獲取電腦的相關(guān)屬性

    C#使用System.Environment獲取電腦的相關(guān)屬性

    這篇文章主要為大家詳細(xì)介紹了C#使用System.Environment獲取電腦的相關(guān)屬性,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-10-10
  • VS2015為console.readkey添加代碼片段的方法

    VS2015為console.readkey添加代碼片段的方法

    這篇文章主要介紹了VS2015為console.readkey添加代碼片段的方法,需要的朋友可以參考下
    2016-12-12
  • C#關(guān)鍵字Check簡單介紹

    C#關(guān)鍵字Check簡單介紹

    這篇文章主要介紹了C#關(guān)鍵字Check功能描述及注意事項(xiàng),checke關(guān)鍵字主要用于對整型類型算術(shù)運(yùn)算和轉(zhuǎn)換顯式啟用溢出檢查,本文通過程序演示給大家詳細(xì)介紹,需要的朋友一起看看吧
    2022-04-04

最新評論

塔河县| 桐乡市| 西乌珠穆沁旗| 湾仔区| 马关县| 松原市| 东城区| 安庆市| 桂林市| 定州市| 诸城市| 惠州市| 罗江县| 高要市| 古蔺县| 怀集县| 兴化市| 铁力市| 旌德县| 北流市| 富顺县| 南乐县| 台东县| 堆龙德庆县| 龙里县| 东乌珠穆沁旗| 曲周县| 郁南县| 彭山县| 定远县| 古蔺县| 大宁县| 翁源县| 静宁县| 类乌齐县| 丹寨县| 碌曲县| 浦北县| 句容市| 塔城市| 南阳市|