如何在.Net中利用HttpClient发送HTTP请求

本文介绍了在.Net中如何初始化和利用HttpClient发送HTTP请求,强调了HttpClient实例的共享和线程安全,以及如何设置默认凭据。同时,讨论了在单元测试中如何模拟HttpClient的行为,以确保代码的健壮性。

初始化

HttpClient位于System.Net.Http命名空间下,用于发送 HTTP 请求和接收来自通过 URI 确认的资源的 HTTP 响应。HttpClient设计意旨可共享实例,且在使用得当的情况下其实例是线程安全的。对于服务器端应用程序而言,如若为每个HTTP请求均创建一个新的HttpClient实例,则在系统压力较高的情况下可能造成socket端口被耗尽,并导致SocketException。所以,比较推荐的使用方式是利用static关键字创建一个可共享的实例。对于.Net Core2.1及以上版本的应用程序,还可以使用HttpClientFactory来创建共享的HttpClient实例。

public class DemoController: ApiController
{
    private static readonly HttpClient client = new HttpClient();
    ... ...
}

在某些应用中,我们希望随请求一起发送一个默认凭据,以供资源服务进行身份验证。此时,可以通过设置HttpClientHandler.UseDefaultCredentials属性来实现。如果使用默认凭据,则为将该属性设置为 true;否则为 false。其默认值为 false

var client = new HttpClient(
    new HttpClientHandler {
        UseDefaultCredentials = true,
    }
);

发送HTTP请求

在利用HttpClient发送HTTP请求时,需要将请求的信息封装到一个HttpRequestMessage实例中,之后利用SendAsync方法进行发送。

public async Task GetAsync(string uri) {
    using (var request = new HttpRequestMessage(HttpMethod.Get, uri))
    {
        using (var response = await client.SendAsync(request) 
        {
            if (response.IsSuccessStatusCode) {
                var dataString = response.Content.ReadAsString();
                ... ...
            }
            else {
                Console.WriteLine($"{response.StatusCode}: {response.ReasePhrase}");
            }
        }
    }
}


public async Task PostAsync(string uri, MyClass data) {
    using (var request = new HttpRequestMessage(HttpMethod.Post, uri))
    {
        var json = JsonConvert.SerializeObject(data); // Newtonsoft.Json package is needed
        request.Content = new StringContent(json, Encoding.UTF8, "application/json");
        using (var response = await client.SendAsync(request) 
        {
            // do something
        }
    }
}

单元测试

为每一个public函数都提供相应的单元测试函数是一个良好的开发习惯,在为HttpClient相关的应用程序开发单元测试项目时,我们可以考虑通过internal的构造函数来根据需求设置相应的Mock的HttpClient实例,而发送真正的HTTP请求。而Mock的HttpClient可以通过自定义的HttpClientHandler来实现。

为了使单元测试project(假设名为Demo.Tests)可以访问业务逻辑project(假设名为Demo.Business)中的internal函数,我们需要在业务逻辑project的Properties下的AssemblyInfo.cs中为其开放访问权限。

[assembly: AssemblyTitle("Demo.Business")]
... ...
[assembly: InternalsVisibleTo("Demo.Tests")]

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值