2

I am trying to develop a Xamarin.Forms or Xamarin.iOS/Xamarin.Droid native app which can make a Web API call to my server. I get the error saying HttpRequestException thrown. Once I searched for a solution, it says that it is because it can't reach the socket, but I am unable to install it to a PCL project. So I check the solution for this and they said to use a proxy to reach the service.

Here is my problem. I have tried making a Proxy in the PCL to connect to a service in the .Droid or .iOS projects so they can use the sockets, (although I don't think the service should be in the app project itself because duplicate code). But the proxy class is not able to reference the the service because it is not in the project.

This is my RestService class.

public class RestService : IRestService
{
    private const string BASE_URI = "http://xxx.xxx.xxx.xxx/";
    private HttpClient Client;
    private string Controller;

    /**
     * Controller is the middle route, for example user or account etc.
     */
    public RestService(string controller)
    {
        Controller = controller;
        Client = new HttpClient();
    }

    /**
     * uri in this case is "userId?id=1".
     */
    public async Task<string> GET(string uri)
    {
        try
        {
            Client.BaseAddress = new Uri(BASE_URI);
            Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            var fullUri = String.Format("api/{0}/{1}", Controller, uri);
            var response = Client.GetAsync(fullUri);
            string content = await response.Result.Content.ReadAsStringAsync();
            return content;
        }
        catch (Exception e)
        {
            return null;
        }
    }
}

I cannot find any good tutorials online on how to get this to work and any help in this regards would be much appreciated.

Nkosi
  • 235,767
  • 35
  • 427
  • 472
Tomaltach
  • 913
  • 1
  • 11
  • 30
  • Did you check this- https://stackoverflow.com/questions/15143107/httpclient-httprequestexception and this- https://stackoverflow.com/questions/31131658/xamarain-web-api – Souvik Ghosh Jun 06 '17 at 14:26
  • Just took a look at both of the links. Both solutions aren't the problem here as I am not using IIS and the url given works with postman. – Tomaltach Jun 06 '17 at 14:48
  • @Tomaltach avoid blocking calls on the whole. Moving it to the response makes no difference. it is still a blocking call – Nkosi Jun 06 '17 at 14:55
  • You can try refit, it's easy to use in PCL https://github.com/paulcbetts/refit – Jesse Jiang Jun 07 '17 at 02:05

1 Answers1

2

You are mixing async/await and blocking calls .Result

public async Task<string> GET(string uri) {
    //...other code removed for brevity

    var response = Client.GetAsync(fullUri).Result;

    //...other code removed for brevity
}

which is causing a deadlock resulting in you not being able to get to socket.

When using async/await you need to go async all the way and avoid blocking calls like .Result and .Wait().

public async Task<string> GET(string uri) {
    try {
        Client.BaseAddress = new Uri(BASE_URI);
        Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        var fullUri = String.Format("api/{0}/{1}", Controller, uri);
        var response = await Client.GetAsync(fullUri);
        var content = await response.Content.ReadAsStringAsync();
        return content;
    } catch (Exception e) {
        return null;
    }
}
Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • Sorry for the mix up with the lines of code. Had tried out a few ways before I posted the code here and it got mixed a little. I have fixed that now but that still fails because of the sockets. – Tomaltach Jun 06 '17 at 14:54
  • @Tomaltach, Because you are still using blocking call. Get rid of `.Result`. That is causing the block. – Nkosi Jun 06 '17 at 14:56