HttpClient in Xamarin.Forms throwing “An error occurred while sending the request.”

Issue

I use Xamarin.Forms to develop a multiplateform app on Windows(UWP) and Android. Also I use a WebService from an ERP running on the LAN of the Enterprise I work. This WebService is available in a normal request in C# with WebRequest and it works fine. But Xamarin prefers, with several plateforms, to use HttpClient with asynchronous methods. The WebRequest indeed doesn’t work with android, and it locks the UI in UWP.

So I created a RestService like its in MSDN and no way to make the request responding. Just if I put the request with WebRequest just before the request with HttpClient, it works and I receive the XML like I want.

If I put only the HttpClient Request it throws a simple error → HttpRequestException with just (“An error occurred while sending the request.”). The InnerException is → “The text associated with this error code cannot be found. The certification authority is not valid or correct.”

The goal is multiplatform so HttpClient is required I think, I’ve already tried to put certificates validations and searched on many forums without finding the answer!!

Hope Somebody can help me!

Request working with 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;
}

My request with 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("{0}{1}", 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;
}

Where I do my request in the MockDataStore to fill a list of objects

public async Task<IEnumerable<Operation>> GetItemsAsync(bool forceRefresh  false)
{
     GetOperations(); // call WebRequest Method

     await GetOperationsAsync(); // call HttpClient Method

     return await Task.FromResult(Operations);
}

Attempt to custom default headers of httpclient instance with GetStringAsync

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"));

Attempt to custom headers of the request using 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();

Solution

Problem solved by adding the header of the httpClient in a Handler instance like this :

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;
     }
}

Using this method, the authentification works and the response is good!

Answered By – Toinouchiwa

Leave a Comment