我有以下代码使用Xamarin和Android设备向REST API发出请求:
public class ApiBase
{
HttpClient m_HttpClient;
public ApiBase(string baseAddress, string username, string password)
{
if (!baseAddress.EndsWith("/"))
{
baseAddress += "/";
}
var handler = new HttpClientHandler();
if (handler.SupportsAutomaticDecompression)
{
handler.AutomaticDecompression = DecompressionMethods.GZip;
}
m_HttpClient = new HttpClient(handler);
m_HttpClient.BaseAddress = new Uri(baseAddress);
var credentialsString = Convert.ToBase64String(Encoding.UTF8.GetBytes(username + ":" + password));
m_HttpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", credentialsString);
m_HttpClient.Timeout = new TimeSpan(0, 0, 30);
}
protected async Task<XElement> HttpGetAsync(string method)
{
try
{
HttpResponseMessage response = await m_HttpClient.GetAsync(method);
if (response.IsSuccessStatusCode)
{
// the request was successful, parse the returned string as xml and return the XElement
var xml = await response.Content.ReadAsAsync<XElement>();
return xml;
}
// the request was not successful -> return null
else
{
return null;
}
}
// some exception occured -> return null
catch (Exception)
{
return null;
}
}
}
如果我有这样的话,对HttpGetAsync的第一次和第二次调用都能很好地工作,但是从GetAsync
档位的第3次调用,最终因超时而抛出异常。我连续发送这些呼叫,其中没有两个同时运行,因为需要先前呼叫的结果来决定下一个呼叫。
我尝试使用应用程序数据包捕获来查看请求和响应,以查明我是否发送了错误的请求。但看起来最终失败的请求似乎从未被发送过。
通过实验,我发现如果不设置AutomaticDecompression
,一切正常。
如果我将HttpGetAsync
方法改为:
protected async Task<XElement> HttpGetAsync(string method)
{
try
{
// send the request
var response = await m_HttpClient.GetStringAsync(method);
if (string.IsNullOrEmpty(response))
{
return null;
}
var xml = XElement.Parse(response);
return xml;
}
// some exception occured -> return null
catch (Exception)
{
return null;
}
}
所以基本上使用i&#39; m m_HttpClient.GetStringAsync
代替m_HttpClient.GetAsync
,然后改变它周围的绒毛以使用不同的返回类型。如果我这样做,一切都没有任何问题。
有没有人知道为什么GetAsync
无法正常工作(似乎没有发送第3个请求)AutomaticDecompression
,GetStringAsync
无瑕疵地工作?
答案 0 :(得分:1)
有关此确切问题的错误报告:
https://bugzilla.xamarin.com/show_bug.cgi?id=21477
该错误标记为已解决已修复,推荐的操作是更新为最新的稳定版本。但还有其他(较新的)bug报告表明同样的事情仍然是开放的,例如: https://bugzilla.xamarin.com/show_bug.cgi?id=34747
通过实现我自己的HttpHandler,我做了一个解决方法:
public class DecompressionHttpClientHandler : HttpClientHandler { protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { request.Headers.AcceptEncoding.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("gzip")); var msg = await base.SendAsync(request, cancellationToken); if (msg.Content.Headers.ContentEncoding.Contains("gzip")) { var compressedStream = await msg.Content.ReadAsStreamAsync(); var uncompresedStream = new System.IO.Compression.GZipStream(compressedStream, System.IO.Compression.CompressionMode.Decompress); msg.Content = new StreamContent(uncompresedStream); } return msg; } }
请注意,上面的代码只是一个示例,而不是最终解决方案。例如,请求不会被压缩,所有标题都将从结果中条带化。但是你明白了。