Xamarin.Forms 中的 HttpClient 抛出“发送请求时发生错误。”

Posted

技术标签:

【中文标题】Xamarin.Forms 中的 HttpClient 抛出“发送请求时发生错误。”【英文标题】:HttpClient in Xamarin.Forms throwing "An error occurred while sending the request." 【发布时间】:2021-06-29 13:47:37 【问题描述】:

我使用 Xamarin.Forms 在 Windows(UWP) 和 android 上开发多平台应用程序。此外,我使用在我工作的企业的 LAN 上运行的 ERP 中的 WebService。此 WebService 在 C# 中使用 WebRequest 的正常请求中可用,并且工作正常。但是 Xamarin 更喜欢使用带有异步方法的 HttpClient,有几个平台。 WebRequest 确实不适用于 android,它会将 UI 锁定在 UWP 中。

所以我在 MSDN 中创建了一个像它一样的 RestService 并且无法使请求响应。只要我将 WebRequest 请求放在 HttpClient 请求之前,它就可以正常工作,并且我会收到我想要的 XML。

如果我只放置 HttpClient 请求,它会抛出一个简单的错误 → HttpRequestException,只是(“发送请求时发生错误。”)。 InnerException 是 →“找不到与此错误代码关联的文本。证书颁发机构无效或不正确。”

目标是多平台,所以我认为需要 HttpClient,我已经尝试放置证书验证并在许多论坛上搜索但没有找到答案!!

希望有人可以帮助我!

使用 WebRequest 的请求

public string Request(string uri)

     string responseFromServer = "";
     ServicePointManager.ServerCertificateValidationCallback = delegate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)  return true; ;

     WebRequest request = WebRequest.Create(uri);
     request.Credentials = new NetworkCredential(user, pswd);
     request.Method = "GET";

     HttpWebResponse response = (HttpWebResponse)request.GetResponse();

     if (((HttpWebResponse)response).StatusDescription == "OK")
     
          Stream dataStream;
          using (dataStream = response.GetResponseStream())
          
               StreamReader reader = new StreamReader(dataStream);
               responseFromServer = reader.ReadToEnd();
          
     
     response.Close();

     return responseFromServer;

我对 HttpClient 的请求

//Constructor 
public RestService()

     //Authentification for the request header
     user = "**";
     pswd = "*****";
     society= "*****";
     user = "%CP1252%" + Base64Encode(user + "@@" + society+ "@@00000");
     pswd = Base64Encode(pswd );
     var authData = string.Format("01", user, mdp);

     client = new HttpClient();
     client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authData);

     //Security protocol
     ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
     ServicePointManager.ServerCertificateValidationCallback = delegate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)  return true; ;


//Request method
public async Task<string> GetDatas(string url)

     Uri uri = new Uri(string.Format(url, string.Empty));
     string content = "";

     try
     
          HttpResponseMessage response = await client.GetAsync(uri);
          response.EnsureSuccessStatusCode();
          content = await response.Content.ReadAsStringAsync();
     
     catch (HttpRequestException e)
     
          Console.WriteLine(e.Message);
     
     return content;

我在 MockDataStore 中请求填写对象列表的位置

public async Task<IEnumerable<Operation>> GetItemsAsync(bool forceRefresh = false)

     GetOperations(); // call WebRequest Method

     await GetOperationsAsync(); // call HttpClient Method

     return await Task.FromResult(Operations);

尝试使用 GetStringAsync 自定义 httpclient 实例的默认标头

client = new HttpClient();

client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authData);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("Mozilla", "5.0"));
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("AppleWebKit", "537.36"));
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("Chrome", "91.0.4472.114"));
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("Safari", "537.36"));
client.DefaultRequestHeaders.Host = "srverp:****";
client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("deflate"));
client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("br"));
client.DefaultRequestHeaders.AcceptLanguage.Add(new StringWithQualityHeaderValue("fr-FR"));
client.DefaultRequestHeaders.Connection.Add("keep-alive");
client.DefaultRequestHeaders.Pragma.Add(new NameValueHeaderValue("no-cache"));

尝试使用 sendAsync 自定义请求标头

var request = new HttpRequestMessage()

     RequestUri = uri,
     Method = HttpMethod.Get,
     Headers = 
           HttpRequestHeader.Authorization.ToString(), "Basic " + authData,
           HttpRequestHeader.Accept.ToString(), "application/xml" 
     ,
;

var task = client.SendAsync(request).ContinueWith((taskwithmsg) =>

     var response = taskwithmsg.Result;
     var tmp = response.Content.ReadAsStringAsync();
     content = tmp.Result;
);
task.Wait();

【问题讨论】:

正如您所提到的,我尝试使用 GetStringAsync 方法和相同的错误来自定义 httpclient 实例的标头!还可以尝试通过 HttpRequestMessage 为每个请求自定义标头,如您在上面的代码中所见。使用第二种方法,我使用 SendAsync 和相同的异常! 用户代理可能是错误的,它指定了作为客户端的浏览器。即使您使用的是 httpclient,某些服务器也可能需要它。请参阅:developer.mozilla.org/en-US/docs/Web/HTTP/Headers/… 听起来像是 Android 上的内核问题。不知道怎么找。请参阅:android.googlesource.com/kernel/common/+log 在我的第一个方法中的 DefaultRequestHeaders 中添加了几乎所有我在请求标头和用户代理中找到的内容,但错误仍然存​​在!我一直在寻找解决方案。 我已经测试了很多东西,所以这似乎是由于我对企业局域网上的 ERP 的请求中的 xamarin,该请求在普通 C# 项目中与 HttpClient 一起使用,并且 HttpClient 请求有效很好地在 xamarin 中从其他网站获取资源,所以我仍然阻止了 【参考方案1】:

通过在 Handler 实例中添加 httpClient 的标头来解决问题,如下所示:

public HttpClient HttpclientAccount

     get
     
          client = client ?? new HttpClient
          (
               new HttpClientHandler()
               
                    ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) =>
                    
                         //bypass
                         return true;
                    ,
               
               , false
          );

          // authentification headers
          client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", 
Convert.ToBase64String(Encoding.UTF8.GetBytes($"user:mdp")));
          return client;
     

使用此方法,认证成功,反响良好!

【讨论】:

以上是关于Xamarin.Forms 中的 HttpClient 抛出“发送请求时发生错误。”的主要内容,如果未能解决你的问题,请参考以下文章

ScrollView 问题中的 Xamarin.Forms 捏手势

Xamarin.Forms 中的 EmguCV 实现

Xamarin.Forms 中的死锁

xamarin.forms 中的推送通知

Xamarin.Forms 中的全局异常处理

ReactiveUI 中的 Xamarin.Forms 控件是不是需要自定义绑定?