查看原文
其他

.NET 中如何选择 WebClient,HttpClient,HttpWebRequest

DotNet 2021-09-23

The following article is from 码农读书 Author 码农读书

当我们在用 .NET 调用 RestAPI 时通常有三种选择,分别为:WebClient, HttpWebRequest,HttpClient,这篇文章我们将会讨论如何使用这三种方式去调用 RestAPI,我还会提供相应的代码案例来帮助你更好的理解这三者的概念和使用方式,简单来说:

  • HttpWebRequest 是一种相对底层的处理 Http request/response 的方式。
  • WebClient 提供了对 HttpWebRequest 的高层封装,来简化使用者的调用。
  • HttpClient 是一种新的处理 Http request/response 工具包,具有更高的性能。

接下来我们讨论一下抽象类 WebRequest

WebRequest

WebRequest 是一种基于特定的 http 实现, 它是一个抽象类, 所以在处理 Reqeust 请求时底层会根据传进来的 url 生成相应的子类,如:HttpWebRequest 或 FileWebRequest ,下面的代码展示了如何使用 WebRequest。

WebRequest webRequest = WebRequest.Create(uri);
webRequest.Credentials = CredentialCache.DefaultCredentials;
webRequest.Method ="GET";
HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();

WebRequest 是 .NET Framework 中第一个用来处理 Http 请求的类,在处理 Http请求和响应 方面给调用者提供了诸多的灵活性,你还可以使用这个类来存取 headers, cookies, protocols 和 timeouts 等等,下面的代码展示了其实现子类 HttpWebRequest 是如何使用的。

HttpWebRequest http = HttpWebRequest)WebRequest.Create(“http://localhost:8900/api/default”);
WebResponse response = http.GetResponse();
MemoryStream memoryStream = response.GetResponseStream();
StreamReader streamReader = new StreamReader(memoryStream);
string data = streamReader.ReadToEnd();

WebClient

WebClient 是 HttpWebRequest 的高层封装,它给调用者提供了更便捷的使用方式,理所当然做出的牺牲就是 WebClient 的性能略逊于 HttpWebRequest,如果你的业务场景只是简单访问第三方的 Http Service,那么我建议你使用 WebClient ,同理如果你有更多的精细化配置则使用 HttpWebRequest,下面的代码展示了如何使用 WebClient 。

string data = null;

using (var webClient = new WebClient())
{
    data = webClient.DownloadString(url);
}

HttpClient

HttpClient 是在 .NET Framework 4.5 中被引入的,如果你的项目是基于 .NET 4.5 以上版本,除一些特定的原因之外,建议你优先使用 HttpClient,本质上来说,HttpClient 作为后来之物,它吸取了 HttpWebRequest 的灵活性及 WebClient 的便捷性,所以说 🐟 和 🐻 可兼得。

HttpWebRequest 在 request/response 对象上提供了非常精细化的配置,同时你也要注意 HttpClient 的出现并不是为了取代 WebClient,言外之意就是 HttpClient 也有缺点,比如说:不能提供 进度处理URI 定制,不支持 FTP 等等,HttpClient 的优点也有很多,它所有关于 IO 操作的方法都是异步的,当然有特殊原因的话也可以使用同步方式,下面的代码展示了如何使用 HttpClient。

public async Task<Author> GetAuthorsAsync(string uri)
{
    Author author = null;
    HttpResponseMessage response = await client.GetAsync(uri);
    if (response.IsSuccessStatusCode)
    {
        author = await response.Content.ReadAsAsync<Author>();
    }
    return author;
}

值得注意的是当 response 出现错误时,默认情况下 HttpClient 并不会抛出异常,如果你一定要求 HttpClient 在这种情况下抛出异常,可更改 IsSuccessStatusCode = false 来改变这种默认行为,做法就是调用 response.EnsureSuccessStatusCode();

public async Task<Author> GetAuthorsAsync(string uri)
{
    Author author = null;

    HttpResponseMessage response = await client.GetAsync(uri);

    response.EnsureSuccessStatusCode();
    
    if (response.IsSuccessStatusCode)
    {
        author = await response.Content.ReadAsAsync<Author>();
    }

    return author;
}

在项目开发中,推荐的做法是保持 HttpClient 的单例化,如果不这么做的话,每次 Request 请求实例化一次 HttpClient ,那么大量的请求必将你的 socket 耗尽并抛出 SocketException 异常。

- EOF -

推荐阅读  点击标题可跳转
.NET Core IOC 循环依赖问题及其相关思考之DispatchProxy如何在 .NET 程序万种死法中有效的生成 DumpEF Core 3.1+编写自定义的EF.Functions扩展方法


看完本文有收获?请转发分享给更多人

推荐关注「DotNet」,提升.Net技能 

点赞和在看就是最大的支持❤️

: . Video Mini Program Like ,轻点两下取消赞 Wow ,轻点两下取消在看

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存