Reputation: 373
I have an ASP.NET WebApi hosted in Azure. There is no HTTP Header based or Azure API authentication on it and fiddler sessions prove that the API is fully functional and spits out data as requested and expected.
In my Xamarin forms (PCL, iOS & Android only) PCL project, I have the following code in a service class:
public async Task<IEnumerable<Link>> GetCategories()
{
IEnumerable<Link> categoryLinks = null;
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//Using https to satisfy iOS ATS requirements
var response = await client.GetAsync(new Uri("https://myproject.azurewebsites.net/api/contents"));
//response.EnsureSuccessStatusCode(); //I was playing around with this to see if it makes any difference
if (response.IsSuccessStatusCode)
{
var content = response.Content.ReadAsStringAsync().Result;
categoryLinks = JsonConvert.DeserializeObject<IEnumerable<Link>>(content);
}
}
return categoryLinks;
}
I have debugged the code and noticed that the control does not go past:
var response = await client.GetAsync(new Uri("https://myproject.azurewebsites.net/api/contents"));
and as a result categoryLinks remains null.
Has anyone come across this before?
A few things to note:
Although I doubt if there is any issue here but I have a MainViewModel class that looks as follows:
public class MainViewModel
{
private readonly INavigation navigation;
private readonly IContentService contentService;
public IEnumerable<CategoryItem> Categories { get; set; }
public MainViewModel(IContentService contentservice, INavigation nav)
{
this.navigation = nav;
this.contentService = contentservice;
SetCategoriesAsync();
}
private async Task SetCategoriesAsync()
{
var response = await this.contentService.GetCategories();
this.Categories = (from c in response
select new CategoryItem()
{
//code removed but you get the idea
}).AsEnumerable();
}
}
My MainPage.xaml.cs has the following lines in the constructor. I don't think there is any issue here either.
this.MainViewModel = new MainViewModel(contentService, navService);
this.CategoriesList.ItemsSource = this.MainViewModel.Categories;
As per this link, I have already added references via nuget to the following libraries in the order of appearance: Microsoft.BCL, Microsoft.BCL.Build, Microsoft.Net.Http
I'm not using ModernHttpClient as yet. I plan to do so once I have HttpClient working as I believe it improves performance.
Any assistance on this will be greatly appreciated.
Upvotes: 1
Views: 5040
Reputation: 4032
I have had this exact problem, and it is being caused by a deadlock, How are you calling this method? usually I go:
Device.BeginInvokeInMainThread(async () =>
{
var categoriesList = await GetCategories();
});
Or if it is inside your View Model, you can use Task.Run();
Avoid using .Result, and timers within your UI even events handlers may cause deadlocks like this one.
Hope this helps.
Upvotes: 1