• .Net5下WebRequest、WebClient、HttpClient是否还存在使用争议?


      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下,本质已经没有了区别,只是对外的表现形式不同而已,使用了时候不必太纠结内部实现优先不同,只关注自己喜欢怎么样的写法就行了。

  • 相关阅读:
    02 re模块
    24 内置模块re 正则表达式
    pickle 模块
    json模块
    命名元组
    os模块
    24 内置函数 命名元组(namedtuple) ,os ,sys,序列化,pickle,json
    functools
    ccc 音乐播放
    ccc prefab
  • 原文地址:https://www.cnblogs.com/gsjlovenet/p/14554206.html
Copyright © 2020-2023  润新知