Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android, Xamarin Forms PCL, PortableRest PCL and Async Web Api Call

I am trying to use PortableRest to make an Async call to a Web API 2.2 Rest service from Xamarin Forms.

I think I have some kind of deadlock / synchronisationcontext issue but I cannot work it out (newbie to async etc).

Can anyone please help?

My controller test method (removed any call to database) -

public IEnumerable<ContentModel> GetTestRest()
{
    return new List<ContentModel> {
        new ContentModel() {Categoryid = 1, Title = "Title"}};
}

My Unit Test Passes -

[TestMethod]
public async Task TestRest()
{
    MyNewsApiClient MyNewsApiClient = new MyNewsApiClient();

    var models = await MyNewsApiClient.TestRest();
    int count = models.Count;
    Assert.AreEqual(1, count);
}

My PortableRest Proxy (PCL) Method -

public async Task<List<ContentModel>> TestRest()
{
    var request = new RestRequest();
    request.Resource = "Content/GetTestRest";

    return await ExecuteAsync<List<ContentModel>>(request);
}

Xamarin Forms ContentPage (PCL) -

public partial class NewsType1CP : ContentPage
{
    public NewsType1CP ()
    {
        InitializeComponent ();
    }

    protected override void OnAppearing ()
    {
        LoadData ();  // this is a sync call of an async method, not sure how else to  approach, make OnAppearing async?
    }

    public async Task LoadData ()
    {
        Debug.WriteLine ("LoadData");

        HeaderLabel.Text = "Load Data!";

        MyNewsApiClient api = new MyNewsApiClient ();

        var cm = await api.TestRest ();
        // this will work on its own, control returns to this method - await api.GetDelay ();

        HeaderLabel.Text = "After! - ";

        NewsListView.ItemsSource = cm;
    }
}

The await to api.TestRest() never results in HeaderLabel.After or ListView being set.

If I just add a test Proxy Method GetDelay() which does not call PortableRest via return await ExecuteAsync>(request);

public async Task<bool> GetDelay ()
{
    await Task.Delay (1000);
    return true;
}

Then all "works".

Thanks for your help, I will download the source code for PortableRest if required (using Nuget dll at present), just was not sure if missing something basic at this top level.

like image 315
WickedW Avatar asked Feb 13 '23 11:02

WickedW


1 Answers

Right, this eventually has nothing to do with Async (or any Issue with PortableRest), but thought I would share in case it can help others.

I eventually put a try block (obvious next step now!) and caught this exception -

Method not found: 'System.Net.Http.HttpClientHandler.set_AutomaticDecompression'.

So, looking at this -

http://davidburela.wordpress.com/2013/07/12/error-when-using-http-portable-class-library-compression/

PortableRest was already in my Forms PCL, but I needed to add Microsoft Http Client Libraries Nuget to my Android Application.

I then got -

Error: ConnectFailure (The requested address is not valid in this context)

I thought it may be something to do with Android Permissions, but it was not in this case (although I now realise I need to add Internet permission anyway for future calls).

Because I am running my App in a VM (from GenyMotion / Virtual Box) then the Android App cannot access LocalHost (where my Web Api resides)

So, from this -

http://bbowden.tumblr.com/post/58650831283/accessing-a-localhost-server-from-the-genymotion

I can confirm that using the address shown in VirtualBox > File > Preferences > Network > VirtualBox Host-Only Network Adapter > Modify does the job beautifully.

Thanks for your help.

like image 174
WickedW Avatar answered Feb 15 '23 11:02

WickedW