NameResolutionFailure 噩梦:甚至 ModernHttpClient 也失败了

NameResolutionFailure Nightmare: Even ModernHttpClient is failing

当我在我的 MVVM Cross Android 应用程序中发出 Web 请求 (GET) 时,我不断收到 NameResolutionFailure 错误。

我已经尝试了论坛中提供的关于这个问题的很多建议,因为这是一个常见问题,但我无法解决这个问题。

我目前的尝试是使用 NuGet 包 ModernHttpClient 来执行网络请求。出现相同的错误 - 无法将域解析为 IP - 但是错误消息与我使用 HttpWebRequest 时发生的情况略有不同所以我想这是一个轻微的改进?

java.net.UnknownHostException: Unable to resolve host "jsonplaceholder.typicode.com": No address associated with hostname

您能否就为什么总是失败提供建议?也许是我的方法没有真正利用 ModernHttpClient?

以下代码是我的 IRestService class 的一部分,位于 Core PCL 而不是 Android 项目中。

public async Task MakeRequest(WebHeaderCollection headers = null)
{

    var handler = new NativeMessageHandler();
    string requestUrl = "http://jsonplaceholder.typicode.com/posts/1";

    try
    {
        using (var client = new HttpClient(handler))
        {
            //client.BaseAddress = new Uri(baseAddress);
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            var response = await client.GetAsync(requestUrl);

            if (response.IsSuccessStatusCode)
            {
                var stream = await response.Content.ReadAsStreamAsync();
                var reader = new StreamReader(stream);
                Mvx.Trace("Stream: {0}", reader.ReadToEnd());
            }
        }
    }
    catch (WebException ex)
    {
        Mvx.Trace("MakeRequest Error: '{0}'", ex.Message);
    }

    return;
}

PS: 我也尝试过使用 Cheesebarons ModernHttpClient MVVM Cross 插件,但这会导致发布模式下出现编译错误,并且没有关于方法和方法的文档class是的 - 也许它不再受支持了?

PPS: 是的,我的清单具有互联网权限(我检查选项和实际清单文件以确认)

不再需要 MvvmCross 的 ModernHttpClient 插件,所以不要使用它。

因此,由于您在 AndroidManifest 中设置了 Internet 权限,所以问题出在其他地方。我在某些 Android 设备上遇到过,第一次调用某些 Internet 资源失败并出现与您遇到的相同的错误。我通常解决这个问题的方法是重试呼叫。

有多种方法可以做到这一点。

  1. 您可以创建自己的 HttpClientHandler,它包装来自 ModernHttpClient 的 HttpClientHandler,并在其中创建您自己的重试处理。
  2. 您可以使用 Polly 等库重试

我倾向于后者。因此,如果您添加 Polly NuGet,您可以很快地测试它是否能为您解决问题:

var policy = Policy.WaitAndRetryAsync(
    5, 
    retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
    (ex, span) => {
        Mvx.Trace("Retried because of {0}", ex);
    }
);

然后像这样重试您的任务:

await policy.ExecuteAsync(() => MakeRequest(someHeaders)).ConfigureAwait(false);

通常在第二次尝试时异常消失。

我在 Nexus 5、Nexus 7 和 Samsung Galaxy SII 上看到过这个问题,但在其他设备上没有。如果您在调试之前切换设备上的 WiFi,它也可能会有所帮助。

无论如何,您的应用程序应该具有某种重试逻辑,因为 Internet 连接有时可能不稳定。