I have a generic PostAsync
method and then I have my AddCart
method to insert my CrCart
entity on my api. The thing is, I want to return the result but it will stop and not return anything even though it is inserting on the api correctly.
Here is my PostAsync
method
// Generic Post Method
public async Task<T> HttpPostAsync<T>(string url, string token, T data)
{
T result = default(T); // résultat de type générique
try
{
string json = JsonConvert.SerializeObject(data);
StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var response = await httpClient.PostAsync(new Uri(url), content);
if (response.IsSuccessStatusCode)
{
var jsonResponse = await response.Content.ReadAsStringAsync();
result = JsonConvert.DeserializeObject<T>(jsonResponse);
}
else
{
throw new Exception(((int)response.StatusCode).ToString() " - " response.ReasonPhrase);
}
return result;
}
catch (Exception ex)
{
one rror(ex.ToString());
return result;
}
}
And here is my AddCart
method
public async Task<CrCart> AddCart(string url, string token, CrCart data)
{
var cart = await _apiService.HttpPostAsync(url, token, data);
return cart;
}
This is where I call AddCart
. It is called the same.
private async void AddCart()
{
if (CurrentPropertiesService.GetCart() == "" )
{
_oCart = new CrCart()
{
IdCustomer = Convert.ToInt32(CurrentPropertiesService.GetCustomer()),
IdUser = Convert.ToInt32(CurrentPropertiesService.GetUserId()),
Date = DateTime.UtcNow,
Status = "Saved"
};
var cart = await _apiService.AddCart(Constants.UrlCart, CurrentPropertiesService.GetToken(), _oCart);
CurrentPropertiesService.SaveCart(cart);
}
else
{
_oCart.Id = Convert.ToInt32(CurrentPropertiesService.GetCart());
}
}
Then I call that method on my constructor. And that is all the call stack.
public ProductDetailPage(CrProduct oProduct, int category)
{
InitializeComponent();
_oProduct = oProduct;
ProductImage.Source = _oProduct.Image;
txtName.Text = _oProduct.Name;
txtDescription.Text = _oProduct.Description;
txtDetails.Text = _oProduct.Stock.ToString();
txtPrice.Text = string.Format("{0:N2}€", _oProduct.Price.ToString());
AddCart();
}
When I try to debug it stops as I said in this line, inserts correctly and doesn't give any errors but doesn't return response.
var response = await httpClient.PostAsync(new Uri(url), content);
I tried calling it on the OnAppearing() method instead of the constructor and making it async to see if that made any difference but doesn't work either.
Please help because I don't know what is the issue here. Thanks.
CodePudding user response:
As suggested in first comment, this is probably a deadlock.
This simple fix might do what you need:
public ProductDetailPage(CrProduct oProduct, int category)
{
...
// Create an "async" context on MainThread. Code inside runs AFTER constructor returns.
// Can also use the equivalent Xamarin.Essentials.MainThread.BeginInvokeOnMainThread.
Xamarin.Forms.Device.BeginInvokeOnMainThread(async () =>
{
await AddCart();
}
}
NOTE: I am deliberately NOT using the newer MainThread.InvokeOnMainThreadAsync
, because constructor is not an async
method.
IMPLICATION: Because this code runs slightly later, the page might first appear without any cart contents. If so, then avoiding that requires changing code elsewhere - where the constructor is called. But first, see if the above works.
CodePudding user response:
According to your description, the await method var response = await httpClient.PostAsync(new Uri(url), content);
post the entity correctly but the response
is null.
So the cause may be the method is an asynchronous method, and the program go to the next line if (response.IsSuccessStatusCode)
without waiting the result of the await httpClient.PostAsync(new Uri(url), content);
.
You can try to use the following code to make the program wait the PostAsync:
var response = httpClient.PostAsync(new Uri(url), content).Wait
or
var response = httpClient.PostAsync(new Uri(url), content).Result