Tekno
Tekno

Reputation: 193

Async with HTTPClient

I'm calling a WEB API with HTTPClient in an App for WP8. When I click a button I look for an user credentials and if it's ok go to the main page. This is my code:

Calling Method

private async void BtnLogin_OnClick(object sender, RoutedEventArgs e)
{
    var user = new User();

    if (user.IsAuthenticated(tbUserName.Text, tbPassword.Text))
    {
        NavigationService.Navigate(new Uri("/MainPage.xaml"));
    }
}

User Class

public class User
{
    private bool? _isAuthenticated;
    public bool IsAuthenticated(string _userName, string _password)
    {
        return (bool)  (_isAuthenticated ?? (_isAuthenticated = AuthenticateAsync(_userName, _password).Result));
    }

    private static async Task<bool> AuthenticateAsync(string userName, string password)
    {
        var baseUrl = string.Format(Constant.AuthenticateAPIUrl, userName, password);
        try
        {
            var client = new HttpClient { BaseAddress = new Uri(baseUrl) };
            var result = await client.PostAsync(baseUrl, new StringContent("")).ConfigureAwait(false);                
            result.EnsureSuccessStatusCode();
        }
        catch (HttpRequestException ex)
        {
            return false;
        }
        return true;
    }
}

The problem is when await is executed, it blocks the App and never returns.

I try a lot of distinct codes but I think I'm lost now!!.

Upvotes: 0

Views: 352

Answers (1)

Stephen Cleary
Stephen Cleary

Reputation: 456417

Calling Task<T>.Result or Task.Wait on the UI thread can cause a deadlock that I explain in full on my blog.

To fix it, replace every use of Result or Wait with await

public async Task<bool> IsAuthenticatedAsync(string _userName, string _password)
{
    return (bool) (_isAuthenticated ?? (_isAuthenticated = await AuthenticateAsync(_userName, _password)));
}

private async void BtnLogin_OnClick(object sender, RoutedEventArgs e)
{
    var user = new User();

    if (await user.IsAuthenticatedAsync(tbUserName.Text, tbPassword.Text))
    {
        NavigationService.Navigate(new Uri("/MainPage.xaml"));
    }
}

Other notes:

  • Don't ignore compiler warnings. Your original code was informing you that your async void BtnLogin_OnClick method didn't have an await.
  • Follow the Task-based Asynchronous Pattern.

Upvotes: 3

Related Questions