当我在我的mvvm cross android应用程序中发出web请求(get)时,经常会出现NameResolutionFailure
错误。
我已经在论坛上尝试了很多关于这个问题的建议,因为这是一个常见的问题,但我无法解决这个问题。
我当前的尝试使用nuget包执行web请求。同样的错误发生了-无法将域解析为IP-但是错误消息与我使用ModernHttpClient
时发生的情况略有不同,所以我想这是一个轻微的改进?
java.net.unknownhostexception:无法解析主机“jsonplaceholder.typicode.com”:没有与主机名关联的地址
你能就为什么总是失败提供建议吗?也许是我的方法没有真正地利用HttpWebRequest
?
下面的代码是位于ModernHttpClient
pcl而不是android项目中的myIRestService
类的一部分。
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;
}
注:我也尝试过使用cheesebarons modernhtpclient mvvm cross插件,但这会在发布模式下导致编译错误,而且没有文档说明它有哪些方法和类-可能不再受支持了?
PPS:是的,我的清单具有Internet权限(我检查选项和实际清单文件以确认)
最佳答案
mvvmcross不再需要modernhttpclient插件,所以不要使用它。
所以既然你在androidmanifest中设置了internet权限,问题就出在别的地方了。我在一些android设备上经历过,第一次调用某个internet资源失败时出现的错误与您得到的相同。我通常处理这个问题的方式是重新打电话。
有多种方法可以做到这一点。
您可以创建自己的httpclienthandler,它包装来自modernhttpclient的httpclienthandler,并在其中创建自己的重试处理。
可以使用库(如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);
通常在第二次尝试时,异常就会消失。
我在Nexus5、Nexus7和三星GalaxySII上看到过这个问题,但在其他设备上没有。如果在调试之前切换设备上的WiFi,也可能会有所帮助。
在任何情况下,你的应用程序都应该有某种重试逻辑,因为互联网连接有时可能会出现不稳定。