51

I am testing an endpoint that I am experiencing some issues with.

I am simply using HttpClient in a loop that performs a request each hour.

var httpClient = new HttpClient();
var message = httpClient.GetAsync(url).Result;
Console.WriteLine(message.StatusCode);

Once in a while I am getting this exception:

System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The remote name could not be resolved: 'xxx'

The experience is that right after the exception, the URL can be accessed. In a browser you simply refresh the page and all is good.

I still haven't got any reports from users experiencing it so I am wondering if it's just a local issue here but could use a little information to help diagnose.

Is there a way to check if The remote name could not be resolved is caused by an DNS issue or by a web server issue from the exceptions? Can I get more information out of HttpCLient or do I need more advanced diagnostic tools?

brett rogers
  • 6,501
  • 7
  • 33
  • 43
Poul K. Sørensen
  • 16,950
  • 21
  • 126
  • 283
  • If you want to you could share the actual URL here and we could have a look if it fails for everyone this way, but it seems to be a local fail of some service. – Kimmax Jul 29 '14 at 11:35
  • Have you tired to switch your DNS Server in the connection properties? (For example Google DNS on _8.8.8.8_) – Kimmax Jul 29 '14 at 11:36
  • nope. havent tried anything. It feels like its when the site has been idle for some time, then the first request wakes it up. seems odd – Poul K. Sørensen Jul 29 '14 at 11:45
  • [Fiddler] DNS Lookup for "url" failed. System.Net.Sockets.SocketException This is usually a temporary error during hostname resolution and means that the local server did not receive a response from an authoritative server – Poul K. Sørensen Jul 29 '14 at 21:57
  • Try `ipconfig /flushdns` and temporally change DNS server – Kimmax Jul 30 '14 at 11:52
  • I had sporadic sporadic successful http requests to the same hostname while it worked fine in a Chrome web browser. Then I noticed the DNS field in the network interface ipv6 configuration of that particular machine was blank. Default gateway was resolved using DHCP but somehow DNS was difficult. After adding the IP of the network providers DNS servers and also Google DNS 8.8.8.8 to the network interface ipv6 configuration it worked fine. – flodis Dec 31 '20 at 10:30

4 Answers4

50

It's probably caused by a local network connectivity issue (but also a DNS error is possible). Unfortunately HResult is generic, however you can determine the exact issue catching HttpRequestException and then inspecting InnerException: if it's a WebException then you can check the WebException.Status property, for example WebExceptionStatus.NameResolutionFailure should indicate a DNS resolution problem.


It may happen, there isn't much you can do.

What I'd suggest to always wrap that (network related) code in a loop with a try/catch block (as also suggested here for other fallible operations). Handle known exceptions, wait a little (say 1000 msec) and try again (for say 3 times). Only if failed all times then you can quit/report an error to your users. Very raw example like this:

private const int NumberOfRetries = 3;
private const int DelayOnRetry = 1000;

public static async Task<HttpResponseMessage> GetFromUrlAsync(string url) {
    using (var client = new HttpClient()) {
        for (int i=1; i <= NumberOfRetries; ++i) {
            try {
                return await client.GetAsync(url); 
            }
            catch (Exception e) when (i < NumberOfRetries) {
                await Task.Delay(DelayOnRetry);
            }
        }
    }
}
Adriano Repetti
  • 65,416
  • 20
  • 137
  • 208
  • See now that i --> 0 operator deserves an upvote :) THanks for the code. – Poul K. Sørensen Jul 29 '14 at 11:43
  • 1
    @Kimmax it is just short hand. `i--` means subtract one from i and then obviously `> 0` is greater than zero. NOTE though that the decrement happens AFTER checking for greater than zero. So, it means if `i` is greater than zero then decrement `i` by one and loop again, when `i` is no longer greater than zero the loop will exit. – Belogix Jul 29 '14 at 11:50
  • 3
    @pksorensen _decrement to zero_ (LOL) operator is unclear to too many people. IMO when you stop and think "eh?" then you'd better rewrite to something easier to understand. Going to zero is OK (but should change also test in catch block). – Adriano Repetti Jul 29 '14 at 11:56
  • 1
    ahh ye, forgot that one! but the rest was just a joke:D did not intend to break the code. – Poul K. Sørensen Jul 29 '14 at 11:59
  • 1
    @pksorensen yes, don't worry! I saw it many times in code, I just would like to keep answer as much readable as possible for future readers! – Adriano Repetti Jul 29 '14 at 12:06
  • 1
    my -1 vote: HttpClient is designed specifically to persist and be used for multiple requests. Creating a new HttpClient object for every request is not recommended even in demos. – Mahmoud Samy May 09 '16 at 14:53
  • @msa yes and no. Yes, it should be reused but in that case you need a much better error handling (is object consistent after an exception? Depends on the exception). For batch tasks yes, you should (but thing may get as complicate as for sql connections). What's worse in this example is that it lack to properly dispose it. – Adriano Repetti May 09 '16 at 15:00
  • This for loop, causes to consume sockets, and soon you will run out of it ; Windows it is 5000, and not released to pool up to 3 minutes. You should refactor this code to use singleton class for HttpClient – Sanjay10 Oct 30 '18 at 19:45
  • The second version has the `new` outside the loop, it should not _consume_ resources when looping. – Adriano Repetti Oct 30 '18 at 21:07
  • -1 This doesn't answer the question: "Is there a way to check if The remote name could not be resolved is caused by an DNS issue or by a web server issue from the exceptions?". It merely presents a (poor IMO) retry strategy. – Josh Noe Feb 07 '19 at 22:16
  • 1
    @JoshNoe re-reading this question after some years I admit...you're right, I didn't write a single line to answer the question "is a name resolution issue?". However for the retry strategy...I do not agree with you. You can make it much more complex but IMHO it's definitely NOT worthy and it will take a LONG time to tune it to cover all the real-world scenarios you will have. It's one of the cases where to keep it stupid is a sensible idea. – Adriano Repetti Feb 08 '19 at 10:06
  • @AdrianoRepetti Appreciate the edit. Upvoted :). For the retry part, the real crux of the problem is figuring out which exceptions to handle, which you've indicated in your edit, thanks! Also, a library like [Polly](https://github.com/App-vNext/Polly) is a nice way to get more power like exponential backoff without much effort. – Josh Noe Feb 08 '19 at 15:13
  • I'm not a fan of exponential delay if any UI is involved (even as simple as `i * DelayOnRetry`) because often it is not so effective and it makes the task to have a good UI much harder (if delays are long enough to be useful and then noticeable), anyway Polly is a great general purpose library! – Adriano Repetti Feb 08 '19 at 15:20
  • Would these suggestions in general be equally applicable to HttpWebRequests? – Eric Legault May 01 '19 at 23:51
  • @EricLegault yes and no, the same mechanism (try/wait/retry) can be of course applied for almost everything and nearly everywhere but code will be pretty different.`HttpWebRequest` has not `async` methods (it uses the older `IAsyncResult`) and there are many more object to create/dispose. It's also MUCH more complex to use than `HttpClient` but that's another story. Honestly I usually go with `HttpClient` or - few times - with `WebClient` if a feature I need isn't supported (see also https://stackoverflow.com/questions/20530152/deciding-between-httpclient-and-webclient/27737601#27737601) – Adriano Repetti May 02 '19 at 10:42
  • Thanks Adriano. I'd definitely like to verify whether it's possible that any of these web request methods are somehow at fault for DNS name resolution errors that logically should be the fault of the networking environment and out of the control of the developer. Not sure how you're supposed to code around that! Unless there's an EnableSupportForCrappyNetworks property I forgot to set to True... – Eric Legault May 03 '19 at 16:18
15

I had a similar issue when trying to access a service (old ASMX service). The call would work when accessing via an IP however when calling with an alias I would get the remote name could not be resolved.

Added the following to the config and it resolved the issue:

<system.net>
    <defaultProxy enabled="true">
    </defaultProxy>
</system.net>
user1620050
  • 181
  • 1
  • 3
3

Open the hosts file located at : **C:\windows\system32\drivers\etc**.

Hosts file is for what?

Add the following at end of this file :

YourServerIP YourDNS

Example:

198.168.1.1 maps.google.com

Mubsher Mughal
  • 442
  • 8
  • 19
0

this problem is pretty sure related to the HttpClient of c#. This client is designed to reuse it. Because the sockets are not directly closed after you dispose the HttpClient. Good explanation is provided by this blog post (https://www.nimaara.com/beware-of-the-net-httpclient/).

You have to handle the case that you DNS lookup table is outdated. In the blog post you also find information how to do this.

ServicePointManager.FindServicePoint(endpoint).ConnectionLeaseTimeout = (int)TimeSpan.FromMinutes(1).TotalMilliseconds;

ServicePointManager.DnsRefreshTimeout = (int)1.Minutes().TotalMilliseconds;

Changer
  • 85
  • 1
  • 7