Search code examples
asp.netasp.net-web-apixamarin.formsandroid-emulatorlocalhost

How to access localhost from android emulator?


I am studying Xamarin from this tutorial - Signup user to ASP.NET Identity from Xamarin Forms. Everything is working if a send request with postman. But if I want to use android emulator it is not working. And I cannot use UWP, because developer mode has to be enabled and I don’t have admin rights on my company computer. I enabled developer mode on my private computer and it is working on UWP but it is not working on android emulator. In the tutorial is used UWP and the guy said that for the android emulator is needed some configuration, but he did not tell any details.

I read many articles and it seems that problem is in the connection between my backend (running on localhost) and android emulator. Is it correct that android emulator is a separate machine trying to call my localhost? I tried to change localhost to 127.0.0.1 or 10.0.2.2 and I tried all options from this article. But it is not working.

Am I right that localhost has to be changed? If so, where? Or is problem somewhere else?

Api services Register method:

    public async Task<bool> RegisterAsync(string email, string password, string confirmPassword)
    {

        try
        {
            System.Diagnostics.Debug.WriteLine("Email: " + email);
            var client = new HttpClient();

            var model = new RegisterBindingModel
            {
                Email = email,
                Password = password,
                ConfirmPassword = confirmPassword
            };
            var json = JsonConvert.SerializeObject(model);

            HttpContent content = new StringContent(json);
            content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            var response = await client.PostAsync("http://localhost:49205/api/Account/Register", content); 

            if (response.IsSuccessStatusCode)
            {
                return true;
            }

            return false;
        }
        catch(Exception e)
        {
            System.Diagnostics.Debug.WriteLine("Error: " + e);
            throw;
        }
   }

Exception if I use localhost:

{System.Net.Http.HttpRequestException: An error occurred while sending the request ---> System.Net.WebException: Error: ConnectFailure (Connection refused) ---> System.Net.Sockets.SocketException: Connection refused
at System.Net.Sockets.Socket.Connect (System.Net.EndPoint remoteEP) [0x000b6] in <bcdc1df2b3724ab69797f3819a126346>:0 
at System.Net.WebConnection.Connect (System.Net.HttpWebRequest request) [0x0016d] in <bcdc1df2b3724ab69797f3819a126346>:0 --- End of inner exception stack trace ---
at System.Net.HttpWebRequest.EndGetRequestStream (System.IAsyncResult asyncResult) [0x0003a] in <bcdc1df2b3724ab69797f3819a126346>:0 
at System.Threading.Tasks.TaskFactory`1[TResult].FromAsyncCoreLogic (System.IAsyncResult iar, System.Func`2[T,TResult] endFunction, System.Action`1[T] endAction, System.Threading.Tasks.Task`1[TResult] promise, System.Boolean requiresSynchronization) [0x0000f] in <fcbf47a04b2e4d90beafbae627e1fca4>:0 

Bad request if I use 10.0.2.2:

{StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, 

Headers: {Server: Microsoft-HTTPAPI/2.0 Date: Thu, 17 May 2018 09:08:41 GMT Connection: close Content-Type: text/html; charset=us-ascii Content-Length: 334 }}

Solution

  • localhost refers to your local machine. It's a common mistake that people think that the Android emulator (or iOS for that matter) is also part of localhost since it is running on the same machine. But this isn't the case.

    The emulators are running as a device in your device and mimic the working as if it was a physical device. It has it's own IP address and cannot reach your localhost loopback address. Your app runs as a application on another machine, namely te emulator. It gets a bit confusing when using UWP, since this does run as an application on your local machine.

    That is why you would have to use the network address of your machine where the server application is hosted. This address typically starts with 192.168.x.x or 10.x.x.x and can be found in the network settings of your machine.

    It seems that you already discovered this. When using the 10.0.2.2 address you receive a HTTP 400. Which means something in your request wasn't right, but you can conclude from this that the server application can actually be reached. But the content of the request causes a problem in your server app. Since you do not provide any code for the /Account/Register endpoint it is impossible to tell what is going on there. Put a breakpoint in your server code, retry the request and try to see why a HTTP 400 is triggered.