I am doing Async
and Await
with C# ASP.Net MVC, with Target .Net Framework 4.8 using Visual Studio 2022. So no matter what, I always get an exception when I call httpClient.PostAsync(...)
. I can call httpClient.PostAsync(...).ConfigureAwait(false)
which doesn't give me an immediate exception and my code after proceeds normally, but I still get an exception by the last closing bracket of my method.
So first, I am making httpClient
a private static
variable in my class, and I think this is the recommended practice:
private static readonly HttpClient httpClient = new HttpClient();
Here is the code where I call httpClient.PostAsync(...)
but I don't call ConfigureAwait(false)
and this gives me an immediate exception in the Visual Studio 2022 debugger and I never make it to the end curly bracket of my method (I simplified the code a little):
private async Task MyMethod(string json, Dictionary<string, string> headerDictionary)
{
string accessToken = GetAccessToken();
string webhookID = WebConfigurationManager.AppSettings["PayPalWebhookID"];
var paypalVerifyRequestJsonString = ... ...;
string payPalServHref = WebConfigurationManager.AppSettings["PayPalV2ServHref"];
httpClient.DefaultRequestHeaders.Clear();
httpClient.DefaultRequestHeaders.Add("authorization", "Bearer " + accessToken);
var content = new StringContent(paypalVerifyRequestJsonString, Encoding.UTF8, "application/json");
// if I return here, there is no exception
//return;
var resultResponse = await httpClient.PostAsync(payPalServHref + "/v1/notifications/verify-webhook-signature", content);
// the end curly bracket of this method (the } below) is never reached
}
An exception is immediately thrown when I call httpClient.PostAsync(...)
:
Now I just change httpClient.PostAsync(...)
to httpClient.PostAsync(...).ConfigureAwait(false)
and my code proceeds normally when I debug it, but an exception is always thrown by the end curly bracket of my method (again, I simplified the code a little):
private async Task MyMethod(string json, Dictionary<string, string> headerDictionary)
{
string accessToken = GetAccessToken();
string webhookID = WebConfigurationManager.AppSettings["PayPalWebhookID"];
var paypalVerifyRequestJsonString = ... ...;
string payPalServHref = WebConfigurationManager.AppSettings["PayPalV2ServHref"];
httpClient.DefaultRequestHeaders.Clear();
httpClient.DefaultRequestHeaders.Add("authorization", "Bearer " + accessToken);
var content = new StringContent(paypalVerifyRequestJsonString, Encoding.UTF8, "application/json");
// if I return here, there is no exception
//return;
var resultResponse = await httpClient.PostAsync(payPalServHref + "/v1/notifications/verify-webhook-signature", content).ConfigureAwait(false);
// lines after httpClient.PostAsync(...).ConfigureAwait(false); are reached and I can debug it, but there will always be an exception
// thrown by the end curly bracket below (the } below)
// if I undo this comment for return, the return statement is called but an exception is still thrown by the end curly bracket below (the } below)
// return;
}
And as I said, ConfigureAwait(false)
allows my code to proceed normally, but an exception is always thrown by the end curly bracket of my method:
I am calling MyMethod(...)
as follows (actually, PayPal Sandbox is calling my C# ASP.Net Webhook method and inside my Webhook method, the call is made to await MyMethod(...)
:
await MyMethod(json, headerDictionary);
The interesting thing is, if I remove all instances of Async and Await, and I forcefully call httpClient.PostAsync(...)
synchronously, that is I call
httpClient.PostAsync(...).Result
, everything works and I don't get any exceptions at all:
var resultResponse = httpClient.PostAsync(payPalServHref + "/v1/notifications/verify-webhook-signature", content).Result;
Does anybody know why I keep getting exceptions when using Async
and Await
when calling httpClient.PostAsync(...)
or calling httpClient.PostAsync(...).ConfigureAwait(false)
?
Edit: Some people requested the function that is calling MyMethod(...). So here is the function that is calling MyMethod(...). It's just a Webhook method that PayPal Sandbox calls:
public async Task<ActionResult> WebhookTester()
{
try
{
// get the JSON from PayPal
Stream req = Request.InputStream;
req.Seek(0, System.IO.SeekOrigin.Begin);
string json = new StreamReader(req).ReadToEnd();
// Get the header from PayPal and store it in a dictionary
var headers = HttpContext.Request.Headers;
Dictionary<string, string> headerDictionary = new Dictionary<string, string>();
var nvc = headers.AllKeys.SelectMany(headers.GetValues, (k, v) => new { key = k, value = v });
foreach (var header in nvc)
{
headerDictionary.Add(header.key, header.value);
}
// Verify the JSON and header. If PayPal returns SUCCESS then process the order. If it's FAILURE, don't process the order.
await MyMethod(json, headerDictionary);
}
catch (Exception ex)
{
}
return new HttpStatusCodeResult(200);
}