Search code examples
c#xamarinhttpclientsystem.net.httpwebrequest

Xamarin Forms, HttpClient class - GetStringAsync and GetAsync return null value and exit from function quickly


when I run my code, in my function that call GetStringAsync or GetAsync, this 2 calls returns null value and immediately exit from my function (all code after is unreached )

I make a web api that is is reachable from web browser (url reached on browser) , also in the emulator browser ( Browser on the Android Emulator ) then i try to make a xamarin forms that manages to communicate with it

class MainPageViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;



    public MainPageViewModel()
    {
        GetEmployees();
    }



    private async void GetEmployees()
    {
        using (var httpClient = new HttpClient())
        {
            var uri = "http://192.168.1.135:8092/api/Masters/GetEmployees/";

            var result = await httpClient.GetStringAsync(uri);


            var EmployeeList = JsonConvert.DeserializeObject<List<Employee>>(result);

            Employees = new ObservableCollection<Employee>(EmployeeList);
        }

    }

    ObservableCollection<Employee> _employees;

    public ObservableCollection<Employee> Employees
    {

        get
        {
            return _employees;
        }

        set
        {
            _employees = value;
            OnPropertyChanged(nameof(Employee));

        }

    }

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

or

class MainPageViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private const string ApiBaseAddress = "http://192.168.1.135:8092/api/Masters/GetEmployees/";

    public MainPageViewModel()
    {
        GetEmployees();
    }

    private HttpClient CreateClient()
    {
        var httpClient = new HttpClient
        {
            BaseAddress = new Uri(ApiBaseAddress)
        };

        httpClient.DefaultRequestHeaders.Accept.Clear();
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        return httpClient;
    }

    private async void GetEmployees()
    {

        using (var httpClient = CreateClient())
        {
            var response = await httpClient.GetAsync(ApiBaseAddress).ConfigureAwait(false);

            var test = response;

            if (response.IsSuccessStatusCode)
            {
                var json = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

                if (!string.IsNullOrWhiteSpace(json))
                {
                    var EmployeeList = JsonConvert.DeserializeObject<List<Employee>>(json);

                    Employees = new ObservableCollection<Employee>(EmployeeList);

                }

            }

            response.Dispose();
        }
    }

    ObservableCollection<Employee> _employees;

    public ObservableCollection<Employee> Employees
    {

        get
        {
            return _employees;
        }

        set
        {
            _employees = value;
            OnPropertyChanged(nameof(Employee));

        }

    }

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

I expect that var result = await httpClient.GetStringAsync(uri);

or

 var response = await httpClient.GetAsync(ApiBaseAddress).ConfigureAwait(false);

returns something but the actual output is null and the code after is unreached because this 2 calls exit immediatly from the function


Solution

  • Avoid mixing async/await and blocking calls like .Wait() or .Result

    Refactor your code to be async all the way through.

    public MainPageViewModel()
    {
       var EmployeeList =  GetEmployees();
       Employees = new ObservableCollection<Employee>(EmployeeList.Result);
    }
    
    
    
    private async Task<List<Employee>> GetEmployees()
    {
       using (var httpClient = CreateClient())
       {
         var response = await httpClient.GetAsync(ApiBaseAddress).ConfigureAwait(false);
    
         var test = response;
    
         if (response.IsSuccessStatusCode)
         {
           var json = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
    
           if (!string.IsNullOrWhiteSpace(json))
           {
              var EmployeeList = JsonConvert.DeserializeObject<List<Employee>>(json);
    
              return EmployeeList;
    
           }                    
    
         }
    
         return null;
        }
    
    }