En_Tech_Siast
En_Tech_Siast

Reputation: 83

Xamarin HttpClient how to fetch json and use it

First I'd like to say that I've been reading over and over hthe https://developer.xamarin.com/guides/xamarin-forms/cloud-services/consuming/rest/ guide, but it doesn't help.

I have a phpwebservice that returns json when asked:

    <?php

include("../include/class.pdogsb.inc.php");


$pdo = PdoGsb::getPdoGsb();


$tabCabinets = $pdo->getLesCabinets();



    header('Content-type: application/json');
    echo json_encode(array('cabinets'=>$tabCabinets));

?>

it gives a response of this type

cabinets": [

    {
        "0": "1",
        "1": "2,2891506",
        "2": "48,8618687",
        "3": "75016",
        "4": "Paris",
        "5": "1 Avenue Gustave V de Suède",
        "id": "1",
        "longitudeGPS": "2,2891506",
        "latitudeGPS": "48,8618687",
        "cp": "75016",
        "ville": "Paris",
        "rue": "1 Avenue Gustave V de Suède"
    },

In my xamarin PCL project I have created a method that I use when I load my view to fetch that json data.

    using Newtonsoft.Json;
    using suivAAndroid.Models;
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Net.Http;
    using System.Text;
    using System.Threading.Tasks;

    namespace suivAAndroid.ViewModel
    {
        public partial class CreerVisiteViewModel : INotifyPropertyChanged
        {
            #region propriétés
            private Cabinet unCabinet;
            private Medecin unMedecin;

            public event PropertyChangedEventHandler PropertyChanged;

            #endregion

            #region methods
            public CreerVisiteViewModel()
            {
                loadcabinets();
            }
            private async Task loadcabinets()
            {
                List<Cabinet> listeCabinets = null;
                HttpClient clientCabinets = new HttpClient();
                string url = "http://10.0.0.5/ppe3JoJuAd/gsbAppliFraisV2/webservices/w_cabinet.php";
//does not read the code after this line
                var response = await clientCabinets.GetAsync(new Uri(url));
                string jsonString = await response.Content.ReadAsStringAsync();
                listeCabinets = JsonConvert.DeserializeObject<List<Cabinet>>(jsonString);
            }

            #endregion
        }
    }

My problem is, while executing and debugging the app, the compiler does not go after the string url = "10.0.0.5/ppe3JoJuAd/gsbAppliFraisV2/webservices/w_cabinet.php"; line. Instead it returns to loadcabinets(); which means that the client never fetch the json data.

what can I do ?

Edit: Updated code with recent answers

i created a BaseViewModel where I Implemented the Icommand interface

public class RelayCommandAsync : ICommand
    {
        private Func<object, Task> _action;
        private Task _task;

        public RelayCommandAsync(Func<object, Task> action)
        {
            _action = action;
        }

        public bool CanExecute(object parameter)
        {
            return _task == null || _task.IsCompleted;
        }

        public event EventHandler CanExecuteChanged;

        public async void Execute(object parameter)
        {
            _task = _action(parameter);
            OnCanExecuteChanged();
            //await _task;
            //OnCanExecuteChanged();
        }

        private void OnCanExecuteChanged()
        {
            var handler = this.CanExecuteChanged;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }
    }

Here is the result in my previous ViewModel

#region methods
        public CreerVisiteViewModel()
        {


        }
        #endregion
        #region Methods
        public async Task<List<Cabinet>> loadcabinetsAsync()
        {
            List<Cabinet> listeCabinets = null;
            HttpClient clientCabinets = new HttpClient();
            try
            {
                string url = "http://10.0.0.5/ppe3JoJuAd/gsbAppliFraisV2/webservices/w_cabinet.php";
                var uri = new Uri(string.Format(url, string.Empty));
                var response = await clientCabinets.GetAsync(uri);
                string jsonString = await response.Content.ReadAsStringAsync();
                listeCabinets = JsonConvert.DeserializeObject<List<Cabinet>>(jsonString);

            }
            catch (Exception e)
            {

            }
            return listeCabinets;
        }
        #endregion


        #region ICommand
        public ICommand ExecuteLoadCabinetAsync { get { return new RelayCommandAsync(x => loadcabinetsAsync()); } }
        #endregion

It still does not resolve my problem with the compiler not reading all the method's code, what can I do more ?

Upvotes: 0

Views: 549

Answers (1)

Cheesebaron
Cheesebaron

Reputation: 24460

There are several issues here:

  1. You are calling a async method without awaiting it.
  2. You are calling a async method in a constructor
  3. You are calling several async methods right after another, without using ConfigureAwait(false), meaning you are switching context back and forth
  4. Your URL does not have a valid scheme, so you are probably getting an exception there

If you want to use the MVVM pattern, you would wrap your code in ICommand, and execute that command, to populate a ObservableCollection. The execution of that command would happen in a Lifecycle event of your ViewController/Activity/Page depending on what platform you are on.

Upvotes: 1

Related Questions