C# HttpClient.SendAsync 在测试某些 URL 时抛出“发送请求时发生错误”异常

Posted

技术标签:

【中文标题】C# HttpClient.SendAsync 在测试某些 URL 时抛出“发送请求时发生错误”异常【英文标题】:C# HttpClient.SendAsync throw "An error occurred while sending the request" exception when testing some URLs 【发布时间】:2015-10-04 09:39:49 【问题描述】:

我正在开发一个 C# 控制台应用程序,用于测试 URL 是否有效或有效。它适用于大多数 URL,并且可以从目标网站获得 HTTP 状态代码的响应。但是在测试其他一些 URL 时,应用程序在运行 HttpClient.SendAsync 方法时抛出“发送请求时发生错误”异常。因此,即使此 URL 在浏览器中实际运行,我也无法获得任何响应或 HTTP 状态代码。我很想知道如何处理这个案子。如果 URL 不起作用或服务器拒绝我的请求,它至少应该给我相应的 HTTP 状态代码。

这是我的测试应用程序的简化代码:

using System;
using System.Net.Http;
using System.Threading.Tasks;

namespace TestUrl

    class Program
    
        static void Main(string[] args)
        
           // var urlTester = new UrlTester("http://www.sitename.com/wordpress"); // works well and get 404
           // var urlTester = new UrlTester("http://www.fc.edu/"); // Throw exception and the URL doesn't work
           var urlTester = new UrlTester("http://www.ntu.edu.tw/english/"); // Throw exception and the URL works actually

            Console.WriteLine("Test is started");

            Task.WhenAll(urlTester.RunTestAsync());

            Console.WriteLine("Test is stoped");
            Console.ReadKey();
        


        public class UrlTester
        
            private HttpClient _httpClient;
            private string _url;

            public UrlTester(string url)
            
                _httpClient = new HttpClient();
                _url = url;
            

            public async Task RunTestAsync()
            
                var httpRequestMsg = new HttpRequestMessage(HttpMethod.Head, _url);

                try
                
                    using (var response = await _httpClient.SendAsync(httpRequestMsg, HttpCompletionOption.ResponseHeadersRead))
                    
                        Console.WriteLine("Response: 0", response.StatusCode);
                    
                
                catch (Exception e) 
                 
                
            
        

    
 

【问题讨论】:

【参考方案1】:

如果您查看InnerException,您会看到:

“无法解析远程名称:'www.fc.edu'”

这个网址在我的浏览器上也不起作用。

为了获得 HTTP 响应,您需要客户端能够与服务器通信(即使是为了获得 error 404),在您的情况下,错误发生在 at the DNS level。

某些浏览器会自动完成这种情况,如果找不到特定的 URL,浏览器会使用不同的后缀/前缀重试,例如:

try "x"
if didn't work, try "www." + x
if this didn't work try "www." + x + ".com"
if this didn't work try "www." + x + ".net"
if this didn't work try "www." + x + "." + currentRegionSuffix.

但请注意,您可以从以下位置更改代码:

catch (Exception e)



收件人:

catch (HttpRequestException e)

    Console.WriteLine(e.InnerException.Message);

您将能够看到导致错误的原因。

另外,除非投掷者抛出了泛型 Exception,否则你永远不应该抓住泛型 Exception,甚至永远不要抓到并且什么都不做除了例外,至少记录一下。

请注意,因为您只等待您可以使用的一项任务:

urlTester.RunTestAsync().Wait();

代替:

Task.WhenAll(urlTester.RunTestAsync());

Task.WhenAll 在给定的Tasks 完成后创建一个新的Task。在您的情况下,您需要 Task.WaitAllTask.WhenAll(...).Wait()

【讨论】:

一般情况下,Task.WhenAll 会返回一个需要等待的 awaitable。如果他想要阻塞版本,Task.WaitAll 是他应该使用的。 感谢@TamirVered 和 Yuval Itzchakov 帮助我找出异常的细节并改进我的代码。现在问题变成了当这个 DNS 级别问题发生时,我如何知道这个 URL 是否有效。因为在很多情况下,URL 确实有效。查看测试过的 URL 部分,我刚刚添加了这个案例。 您可以再次阅读InnerException 以查看错误原因,并查看InternalStatus 以查看之后的连接状态。 "这个 URL 在我的浏览器上也不起作用。" - 这个对我有帮助,我错误地设置了内部 DNS 操作 ;)【参考方案2】:

我解决了这个问题:

System.Net.ServicePointManager.SecurityProtocol =
            SecurityProtocolType.Tls12 |
            SecurityProtocolType.Tls11 |
            SecurityProtocolType.Tls;

【讨论】:

以上是关于C# HttpClient.SendAsync 在测试某些 URL 时抛出“发送请求时发生错误”异常的主要内容,如果未能解决你的问题,请参考以下文章

在 HttpClient.SendAsync() 之后无法访问已释放的对象

HttpClient.SendAsync() 未将 JSON 作为字符串发送

HttpClient.SendAsync 不发送请求正文

HttpClient.SendAsync:500 - Windows 服务应用程序中的内部服务器错误

HttpClient.SendAsync 方法退出而不抛出异常

HttpClient.SendAsync 在 Xamarin.Forms Android 上引发 ObjectDisposedException,但在 UWP 上却没有