WebRequest、WebClient、HttpClient 是C#中常用的三个Http请求的类,时不时也会有人发表对这三个类使用场景的总结,本人是HttpClient 一把梭,也没太关注它们的内部实现,最近比较闲就看了下它们内部实现到底有什么差别。

  WebClient其实就是对WebRequest的二次封装,便于使用。所以主要看WebRequest和HttpClient之间的差别。WebRequest的默认实现是HttpWebRequest我把其中关于今天主题关键的代码贴出来:

  

 1 public override WebResponse GetResponse()
2 {
3 try
4 {
5 _sendRequestCts = new CancellationTokenSource();
6 return SendRequest(async: false).GetAwaiter().GetResult();
7 }
8 catch (Exception ex)
9 {
10 throw WebException.CreateCompatibleException(ex);
11 }
12 }
 1 private async Task<WebResponse> SendRequest(bool async)
2 {
3 if (RequestSubmitted)
4 {
5 throw new InvalidOperationException(SR.net_reqsubmitted);
6 }
7
8 var request = new HttpRequestMessage(new HttpMethod(_originVerb), _requestUri);
9
10 bool disposeRequired = false;
11 HttpClient? client = null;
12 try
13 {
14 client = GetCachedOrCreateHttpClient(async, out disposeRequired);
15 if (_requestStream != null)
16 {
17 ArraySegment<byte> bytes = _requestStream.GetBuffer();
18 request.Content = new ByteArrayContent(bytes.Array!, bytes.Offset, bytes.Count);
19 }
20
21 if (_hostUri != null)
22 {
23 request.Headers.Host = Host;
24 }
25
26 // Copy the HttpWebRequest request headers from the WebHeaderCollection into HttpRequestMessage.Headers and
27 // HttpRequestMessage.Content.Headers.
28 foreach (string headerName in _webHeaderCollection)
29 {
30 // The System.Net.Http APIs require HttpRequestMessage headers to be properly divided between the request headers
31 // collection and the request content headers collection for all well-known header names. And custom headers
32 // are only allowed in the request headers collection and not in the request content headers collection.
33 if (IsWellKnownContentHeader(headerName))
34 {
35 if (request.Content == null)
36 {
37 // Create empty content so that we can send the entity-body header.
38 request.Content = new ByteArrayContent(Array.Empty<byte>());
39 }
40
41 request.Content.Headers.TryAddWithoutValidation(headerName, _webHeaderCollection[headerName!]);
42 }
43 else
44 {
45 request.Headers.TryAddWithoutValidation(headerName, _webHeaderCollection[headerName!]);
46 }
47 }
48
49 request.Headers.TransferEncodingChunked = SendChunked;
50
51 if (KeepAlive)
52 {
53 request.Headers.Connection.Add(HttpKnownHeaderNames.KeepAlive);
54 }
55 else
56 {
57 request.Headers.ConnectionClose = true;
58 }
59
60 request.Version = ProtocolVersion;
61
62 _sendRequestTask = async ?
63 client.SendAsync(request, _allowReadStreamBuffering ? HttpCompletionOption.ResponseContentRead : HttpCompletionOption.ResponseHeadersRead, _sendRequestCts!.Token) :
64 Task.FromResult(client.Send(request, _allowReadStreamBuffering ? HttpCompletionOption.ResponseContentRead : HttpCompletionOption.ResponseHeadersRead, _sendRequestCts!.Token));
65
66 HttpResponseMessage responseMessage = await _sendRequestTask.ConfigureAwait(false);
67
68 HttpWebResponse response = new HttpWebResponse(responseMessage, _requestUri, _cookieContainer);
69
70 int maxSuccessStatusCode = AllowAutoRedirect ? 299 : 399;
71 if ((int)response.StatusCode > maxSuccessStatusCode || (int)response.StatusCode < 200)
72 {
73 throw new WebException(
74 SR.Format(SR.net_servererror, (int)response.StatusCode, response.StatusDescription),
75 null,
76 WebExceptionStatus.ProtocolError,
77 response);
78 }
79
80 return response;
81 }
82 finally
83 {
84 if (disposeRequired)
85 {
86 client?.Dispose();
87 }
88 }
89 }

  在SendRequest(bool async)方法中调用了一个方法GetCachedOrCreateHttpClient看到此处我一阵感慨,最终还是调用了HttpClient。到此也能粗显的看出来,三者在.Net5下,本质已经没有了区别,只是对外的表现形式不同而已,使用了时候不必太纠结内部实现优先不同,只关注自己喜欢怎么样的写法就行了。

.Net5下WebRequest、WebClient、HttpClient是否还存在使用争议?的更多相关文章

  1. 第三节:总结.Net下后端的几种请求方式(WebClient、WebRequest、HttpClient)

    一. 前言 前端调用有Form表单提交,ajax提交,ajax一般是用Jquery的简化写法,在这里不再过多介绍: 后端调用大约有这些:WebCient.WebRequest.Httpclient.W ...

  2. WebClient, HttpClient, HttpWebRequest ,RestSharp之间的区别与抉择

    NETCore提供了三种不同类型用于生产的REST API: HttpWebRequest;WebClient;HttpClient,开源社区创建了另一个名为RestSharp的库.如此多的http库 ...

  3. .Net5 下Dictionary 为什么可以在foreach中Remove

    在一个讨论群里,看见有人说Dictionary可以在foreach中直接调用Remove了,带着疑问,写了简单代码进行尝试 class Program { static void Main(strin ...

  4. webrequest HttpWebRequest webclient/HttpClient

    webrequest(abstract类,不可直接用) <--- (继承)---- HttpWebRequest(更好的控制请求) <--- (继承)---- webclient (简单快 ...

  5. WebRequest/HttpWebRequest/HttpRequest/WebClient/HttpClient的区别

    1.WebRequest和HttpWebRequest WebRequest 的命名空间是: System.Net ,它是HttpWebRequest的抽象父类(还有其他子类如FileWebReque ...

  6. C# WebClient,HttpClient,WebRequest

    static void WebClientDemo() { string url = "https://www.cnblogs.com/Fred1987/p/11843418.html&qu ...

  7. 互联网的寒冬下各大一线互联网公司还在用SpringBoot这是为什么?

    引言 现在各大技术社区 Spring Boot 的文章越来越多,Spring Boot 相关的图文.视频教程越来越多,使用 Spring Boot 的互联网公司也越来越多: Java 程序员现在出去面 ...

  8. C#: Create a WebRequest with HTTPClient

    http://www.cnblogs.com/shanyou/archive/2012/03/21/2410739.html http://msdn.microsoft.com/zh-cn/libra ...

  9. ubuntu下30天自制操作系统还在继续学习中

    操作系统还在学习中,进度不是非常确定,近期学习到了第13天的中部,由于把ucgui移植上去花了一点时间. 同一时候为了方便代码的兴许管理和分享,也为了学习github的代码管理使用思想, 所以建立了一 ...

随机推荐

  1. 图片转tfrecords

    import numpy as np import tensorflow as tf import time import os import cv2 from sklearn.utils impor ...

  2. 快速下载 Visual Studio Code

    快速下载 Visual Studio Code https://visualstudio.microsoft.com/zh-hant/downloads/ 切换 cdn https://az76429 ...

  3. iPhone 12 导入通讯录排序 Bug

    iPhone 12 导入通讯录排序 Bug iOS iOS 通讯录排序问题 Huawei OK solution iOS 切换中英文,修复排序通讯录 bug Awesome iOS Contacts ...

  4. auto open Chrome DevTools in the command line

    auto open Chrome DevTools in the command line --auto-open-devtools-for-tabs # macOS $ /Applications/ ...

  5. css skeleton loading & skeleton components

    css skeleton loading css & :empty See the Pen Skeleton Screen with CSS by xgqfrms (@xgqfrms) on ...

  6. vue技术栈

    1 vue 说明:vue生命周期:技术点:1:常用的API:computed,methods,props,mounted,created,components 2vue-cli说明:vue绞手架,用于 ...

  7. 「NGK每日快讯」11.28日NGK公链第25期官方快讯!

  8. 如何将文件夹取消svn关联

    随便在什么目录新建一个文本文件,文件名随便,将文本文件打开,将下面的文字复制到文本文件中: Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHI ...

  9. 对Map进行复合操作(读写)且并发执行时,无法保证业务的行为是正确的,对读写操作进行同步则可以解决。

    ConcurrentHashMap通常只被看做并发效率更高的Map,用来替换其他线程安全的Map容器,比如 Hashtable和Collections.synchronizedMap.线程安全的容器, ...

  10. openwrt编译加载龙尚U9300模组上网

    硬件平台:MT7628A openwrt版本:MTK_SDK 1.添加模组信息 /build_dir/target-mipsel_24kc_musl/linux-ramips_mt76x8/linux ...