C# HttpClient's PostAsync fails when HttpRuntime's TargetFramework is set to 4.8

571 views Asked by At

I am facing an issue with the C# HttpClient's PostAsync method. I am calling an API which is on HTTPS SSL and things are working fine until I deployed my code on to a server which has the following in the web.config

var response = await Client.PostAsync(path, requestObject);
response.EnsureSuccessStatusCode();
string strResponse = response.Content.ReadAsStringAsync().Result;

The API being called is on HTTPS and the certificate is trusted on my machine.

<httpRuntime maxRequestLength="40960" **targetFramework="4.8" **enableVersionHeader="false" />

My local environment doesn't have the targetFramework in the web.config. The API call only works if I remove the TargetFramework attribute. After adding the attribute back, there seems to be no errors or response, the execution hangs for 5 minutes. There is no exception or error, nothing in the event viewer.

I have tried a lot of things like setting the TLS

Security.Transport.SslProtocols = SslProtocols.Tls11 | SslProtocols.Tls12;  

and

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

But nothing seems to work. We need the targetframework attribute and need this api call to work. What is the TargetFramework attribute adding in terms of configuration which is leading to api call failing/hanging ?

1

There are 1 answers

0
Stephen Cleary On BEST ANSWER

targetFramework controls the server-side "quirks mode". One of those "quirks" is which SynchronizationContext to use. Without the targetFramework setting, ASP.NET uses the LegacyAspNetSynchronizationContext, which doesn't work correctly with async and await. With the targetFramework setting, ASP.NET uses AspNetSynchronizationContext, which does work with async and await.

If your code is blocking on asynchronous code, then it's possible that the old/legacy SynchronizationContext will not cause a deadlock when it actually should. Note that removing the targetFramework is not the correct solution, since the old/legacy SynchronizationContext shouldn't be used with async/await at all. The proper solution is to remove the blocking so that no deadlock can occur with the new SynchronizationContext.