Make an Https Call Using HttpClient

I am using HttpClient to make WebApi calls using C #. Seems to be a neat and quick way compared to WebClient . However, I got stuck during Https calls.

How can I make the below code to make Https calls?

 HttpClient httpClient = new HttpClient(); httpClient.BaseAddress = new Uri("https://foobar.com/"); httpClient.DefaultRequestHeaders.Accept.Clear(); httpClient.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/xml")); var task = httpClient.PostAsXmlAsync<DeviceRequest>( "api/SaveData", request); 

EDIT 1: The code above works fine for http calls. But when I change the scheme to https, it does not work. Here is the error received:

The underlying connection was closed: Failed to establish trust for the SSL / TLS secure channel.

EDIT 2: Changing the scheme to https: step one.

How do I provide a certificate and public / private key with a C # request.

+137
c # asp.net-web-api
Mar 07 '14 at 13:40
source share
15 answers

If the server only supports a higher version of TLS, such as TLS 1.2, it will still work if your client PC is not configured to use a higher version of TLS by default. To resolve this issue, add the following to your code.

 System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; 

By changing the example code, it will be

 HttpClient httpClient = new HttpClient(); //specify to use TLS 1.2 as default connection System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; httpClient.BaseAddress = new Uri("https://foobar.com/"); httpClient.DefaultRequestHeaders.Accept.Clear(); httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml")); var task = httpClient.PostAsXmlAsync<DeviceRequest>("api/SaveData", request); 
+174
Oct 12 '15 at 23:39
source

Just specify HTTPS in the URI.

 new Uri("https://foobar.com/"); 

Foobar.com will need to have a trusted SSL certificate, or your calls will not be completed with an unreliable error.

EDIT Response: ClientCertificates with HttpClient

 WebRequestHandler handler = new WebRequestHandler(); X509Certificate2 certificate = GetMyX509Certificate(); handler.ClientCertificates.Add(certificate); HttpClient client = new HttpClient(handler); 

EDIT Answer2: If the server connected has disabled SSL, TLS 1.0 and 1.1, and you are still using the .NET framework 4.5 (or lower), you need to make a choice

+122
Mar 07 '14 at 1:47
source

Your code should be modified as follows:

 httpClient.BaseAddress = new Uri("https://foobar.com/"); 

You must use the https: URI scheme. There is a useful page here on MSDN about secure HTTP connections. Really:

Use the https: URI scheme

The HTTP protocol defines two URI schemes:

http: used for unencrypted connections.

https: Used for secure connections that must be encrypted. This option also uses digital certificates and certification authorities to verify that the server is who it claims to be.

Also, keep in mind that HTTPS connections use an SSL certificate. Make sure your secure connection has this certificate, otherwise the requests will fail.

EDIT:

The code works fine for creating http calls. But when I change the https scheme does not work, let me post an error message.

What does it mean doesn't work? Queries fail? Is an exception thrown? Specify your question.

If the requests fail, then the problem should be an SSL certificate.

To fix the problem, you can use the HttpWebRequest class and then its ClientCertificate property. You can also find here a useful example of how to make an HTTPS request using a certificate.

An example is as follows (as shown on the MSDN page previously linked):

 //You must change the path to point to your .cer file location. X509Certificate Cert = X509Certificate.CreateFromCertFile("C:\\mycert.cer"); // Handle any certificate errors on the certificate from the server. ServicePointManager.CertificatePolicy = new CertPolicy(); // You must change the URL to point to your Web server. HttpWebRequest Request = (HttpWebRequest)WebRequest.Create("https://YourServer/sample.asp"); Request.ClientCertificates.Add(Cert); Request.UserAgent = "Client Cert Sample"; Request.Method = "GET"; HttpWebResponse Response = (HttpWebResponse)Request.GetResponse(); 
+13
Mar 07 '14 at 13:48
source

I had the same issue when connecting to GitHub which requires a user agent. Thus, it is sufficient to provide this and not generate a certificate

 var client = new HttpClient(); client.BaseAddress = new Uri("https://api.github.com"); client.DefaultRequestHeaders.Add( "Authorization", "token 123456789307d8c1d138ddb0848ede028ed30567"); client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/json")); client.DefaultRequestHeaders.Add( "User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"); 
+6
Feb 27 '15 at 19:31
source

When connecting to https I also got this error, I add this line before HttpClient httpClient = new HttpClient(); and connect successfully:

 ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; 

I know this from this answer and another similar answer, and the comment mentions:

This is a useful hacking process in development, so if you put the #if DEBUG #endif operator around it, this is at least what you need to do to make it safer and stop it ultimately in production.

Also, I have not tried the method in another answer that uses new X509Certificate() or new X509Certificate2() to create a certificate, I'm not sure if just creating using new() will work or not.

EDIT: Some links:

Create a self-signed server certificate in IIS 7

Import and export SSL certificates in IIS 7

Convert .pfx to .cer

Best Practices for Using ServerCertificateValidationCallback

I believe the Thumbprint value is x509certificate.GetCertHashString() :

Get certificate fingerprint

+5
Nov 14 '17 at 3:53 on
source

Just specifying HTTPS in the URI should do the trick.

 httpClient.BaseAddress = new Uri("https://foobar.com/"); 

If the request works with HTTP, but not with HTTPS, then this is certainly a certificate issue . Verify that the caller trusts the issuer of the certificate and that the certificate has not expired. A quick and easy way to verify that you need to make a request in a browser.

You can also check on the server (if it is yours and / or if you can) that it is configured to correctly execute HTTPS requests.

+3
Mar 07
source

I also got the error:

The underlying connection was closed: Failed to establish trust for the SSL / TLS secure channel.

... with the Xamarin Forms Android -targeting app trying to request resources from an API provider that requires TLS 1.3.

The solution was to update the project configuration to replace the “managed” (.NET) Xamarin http client (which does not support TLS 1.3 with Xamarin Forms v2.5) and use the native android client instead.

This is a simple switching project in a visual studio. See the screenshot below.

  • Project properties
  • Android settings
  • advanced
  • List item
  • Change "Implement HttpClient" to "Android"
  • Change the SSL / TLS implementation to "Native TLS 1. 2+"

enter image description here

+2
May 2 '18 at 18:15
source

At the HttpClientHandler level:

 var handler = new HttpClientHandler() { SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls }; var client = new HttpClient(handler); 

Thus, one includes the latest versions of TLS.

Note that the default value of SslProtocols.Default is actually SslProtocols.Ssl3 | SslProtocols.Tls SslProtocols.Ssl3 | SslProtocols.Tls SslProtocols.Ssl3 | SslProtocols.Tls SslProtocols.Ssl3 | SslProtocols.Tls (tested on .Net Core 2.1 and .Net Framework 4.6.1).

+1
Jul 12 '19 at 7:55
source

You can try using the Nuget ModernHttpClient package: after downloading the package, you can implement it as follows:

  var handler = new ModernHttpClient.NativeMessageHandler() { UseProxy = true, }; handler.ClientCertificateOptions = ClientCertificateOption.Automatic; handler.PreAuthenticate = true; HttpClient client = new HttpClient(handler); 
0
Aug 03 '16 at 4:17
source

Add the following declarations to your class:

 public const SslProtocols _Tls12 = (SslProtocols)0x00000C00; public const SecurityProtocolType Tls12 = (SecurityProtocolType)_Tls12; 

After:

 var client = new HttpClient(); 

As well as:

 ServicePointManager.SecurityProtocol = Tls12; System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 /*| SecurityProtocolType.Tls */| Tls12; 

Happy? :)

0
Jun 27 '18 at 11:26
source

I agree with Felickz, but I also want to add an example to clarify usage in C #. I am using SSL in a windows service as follows.

  var certificatePath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "bin"); gateway = new GatewayService(); gateway.PreAuthenticate = true; X509Certificate2 cert = new X509Certificate2(certificatePath + @"\Attached\my_certificate.pfx","certificate_password"); gateway.ClientCertificates.Add(cert); ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; gateway.UserAgent = Guid.NewGuid().ToString(); gateway.Timeout = int.MaxValue; 

If I am going to use it in a web application, I just change the implementation on the proxy side as follows:

 public partial class GatewayService : System.Web.Services.Protocols.SoapHttpClientProtocol // to => Microsoft.Web.Services2.WebServicesClientProtocol 
0
Jul 16 '19 at 8:46
source

I even read everything I tried here but nothing worked. Everything is working

enter image description here

-one
Jan 19 '19 at 10:24
source

I even read everything I tried here but nothing worked. Everything is working

Code image

-one
Jan 19 '19 at 10:32
source

I had this problem and in my case the solution was stupidly simple: open Visual Studio with administrator privileges. I tried all of the above solutions and it did not work until I did this. Hope this saves someone valuable time.

-one
Mar 28 '19 at 10:58
source

For the error:

The underlying connection was closed: Failed to establish trust for the SSL / TLS secure channel.

I think you need to unconditionally accept a certificate with the following code

 ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true; 

As Opposition wrote in his answer to a .NET question, the client connects to the ssl Web API .

-four
Jan 19 '18 at 15:07
source



All Articles