Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make Https call using HttpClient

I have been using HttpClient for making WebApi calls using C#. Seems neat & fast way compared to WebClient. However I am stuck up while making Https calls.

How can I make 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 making http calls. But when I change the scheme to https it does not work. Here is the error obtained:

The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.

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

How do I supply certificate & public / private key along with C# request.

like image 225
Abhijeet Avatar asked Oct 11 '22 15:10

Abhijeet


People also ask

How do I use HttpClient Getasync?

Using SendAsync, we can write the code as: static async Task SendURI(Uri u, HttpContent c) { var response = string. Empty; using (var client = new HttpClient()) { HttpRequestMessage request = new HttpRequestMessage { Method = HttpMethod. Post, RequestUri = u, Content = c }; HttpResponseMessage result = await client.


Video Answer


2 Answers

If the server only supports higher TLS version like TLS 1.2 only, it will still fail unless your client PC is configured to use higher TLS version by default. To overcome this problem, add the following in your code:

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

Modifying your code example, it would 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);
like image 262
Ronald Ramos Avatar answered Oct 14 '22 05:10

Ronald Ramos


Simply specify HTTPS in the URI.

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

Foobar.com will need to have a trusted SSL cert or your calls will fail with untrusted error.

EDIT Answer: ClientCertificates with HttpClient

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

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

  1. Upgrade to .Net 4.6+ (Supports TLS 1.2 by default)
  2. Add registry changes to instruct 4.5 to connect over TLS1.2 ( See: salesforce writeup for compat and keys to change OR checkout IISCrypto see Ronald Ramos answer comments)
  3. Add application code to manually configure .NET to connect over TLS1.2 (see Ronald Ramos answer)
like image 133
felickz Avatar answered Oct 14 '22 05:10

felickz