it编程 > 编程语言 > Asp.net

C#封装HttpClient实现HTTP请求处理

18人参与 2025-06-06 Asp.net

在现代的.net应用程序开发中,与外部服务进行http通信是一项常见需求。httpclient作为.net框架中处理http请求的核心组件,为我们提供了强大而灵活的api。然而,直接使用原生的httpclient可能会导致代码重复、错误处理不完善等问题。为了提高代码的可维护性和可测试性,我们通常会对httpclient进行封装。本文将介绍一个完整的httprequest类封装实现,并深入探讨http请求处理的最佳实践。

一、完整的httprequest类实现

首先,让我们来看一下完整的httprequest类实现代码:

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响应
            var responseobject = jsonserializer.deserialize<response>(responsecontent, jsonconverterextensions.serializersettings);
            
            if (responseobject != null)
            {
                responseobject.statuscode = response.statuscode;
                return responseobject;
            }
        }
        catch (jsonexception)
        {
            // 如果json解析失败,创建一个基于http状态码的响应
        }
        
        // 对于非json响应或解析失败的情况
        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 = $"处理请求时发生意外错误: {ex.message}",
            statuscode = httpstatuscode.internalservererror,
            data = ex
        };
    }
}

二、设计思路与实现要点

1. 依赖注入与生命周期管理

这个封装类采用了依赖注入模式,通过构造函数接收一个httpclient实例。这样做有几个重要好处:

遵循单一职责原则,httprequest类专注于http请求处理

便于单元测试,可以轻松注入模拟的httpclient

利用.net的ihttpclientfactory进行正确的httpclient生命周期管理,避免资源泄漏

同时,类实现了idisposable接口,确保在不再需要时正确释放httpclient资源。

2. 流畅接口设计

为了提供更友好的api体验,封装类实现了流畅接口模式:

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" });

这种链式调用方式使代码更加简洁易读,同时保持了良好的可扩展性。

3. 统一的错误处理

在每个http方法中,我们都实现了统一的异常处理机制:

这种统一的错误处理方式使上层调用代码更加简洁,无需重复处理各种异常情况。

4. 灵活的响应处理

processresponseasync方法负责处理http响应,它尝试将响应内容解析为json格式的response对象:

这种设计使封装类能够处理各种类型的http响应,同时提供一致的返回格式。

三、实际使用示例

下面是一个使用这个封装类的完整示例:

using system;
using system.net.http;
using system.threading.tasks;

​​​​​​​public class program
{
    public static async task main()
    {
        try
        {
            // 创建httpclient实例(实际应用中建议使用ihttpclientfactory)
            using var httpclient = new httpclient();
            
            // 创建请求实例并配置
            var request = new httprequest(httpclient)
                .withbaseaddress("https://api.example.com")
                .withbearertoken("your-auth-token");
                
            // 发送get请求
            var getresponse = await request.getasync("/api/users");
            console.writeline($"get请求结果: {getresponse.success}, 状态码: {getresponse.statuscode}");
            
            // 发送post请求
            var postdata = new { name = "john doe", email = "john@example.com" };
            var postresponse = await request.postasync("/api/users", postdata);
            console.writeline($"post请求结果: {postresponse.success}, 状态码: {postresponse.statuscode}");
            
            // 发送put请求
            var putdata = new { id = 1, name = "jane doe" };
            var putresponse = await request.putasync("/api/users/1", putdata);
            console.writeline($"put请求结果: {putresponse.success}, 状态码: {putresponse.statuscode}");
            
            // 发送delete请求
            var deleteresponse = await request.deleteasync("/api/users/1");
            console.writeline($"delete请求结果: {deleteresponse.success}, 状态码: {deleteresponse.statuscode}");
        }
        catch (exception ex)
        {
            console.writeline($"发生未处理的异常: {ex.message}");
        }
    }
}

四、httpclient使用最佳实践

在使用httpclient和这个封装类时,还需要注意以下最佳实践:

通过这个完整的httprequest类封装,我们可以更加高效、安全地处理http通信,同时保持代码的整洁和可维护性。希望这篇文章对你理解c#中的http请求处理有所帮助。

这个实现提供了完整的http请求功能,包括get、post、put、delete方法,以及灵活的请求配置和统一的响应处理。

到此这篇关于c#封装httpclient实现http请求处理的文章就介绍到这了,更多相关c#封装httpclient内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

您想发表意见!!点此发布评论

推荐阅读

Nacos注册中心和配置中心的底层原理全面解读

06-06

C#实现Struct结构体与IntPtr转换的示例详解

06-05

C#提取文件时间戳实现实现与性能优化

06-08

C#使用BarcodeLib生成条形码的完整代码

06-04

C#代码实现解析WTGPS和BD数据

06-04

C#基于Whisper.net实现语音识别功能的示例详解

06-03

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论