Connect to Local Web Services from iOS Simulators and Android Emulators

Download Sample Download the sample

Many mobile applications consume web services. During the development phase, it's common to deploy a web service locally and consume it from a mobile application running in the iOS simulator or Android emulator. This avoids having to deploy the web service to a hosted endpoint, and enables a straightforward debugging experience because both the mobile application and web service are running locally.

Mobile applications running in the iOS simulator or Android emulator can consume ASP.NET Core web services that are running locally, and exposed over HTTP, as follows:

  • Applications running in the iOS simulator can connect to local HTTP web services via your machines IP address, or via the localhost hostname. For example, given a local HTTP web service that exposes a GET operation via the /api/todoitems/ relative URI, an application running in the iOS simulator can consume the operation by sending a GET request to http://localhost:<port>/api/todoitems/.
  • Applications running in the Android emulator can connect to local HTTP web services via the 10.0.2.2 address, which is an alias to your host loopback interface (127.0.0.1 on your development machine). For example, given a local HTTP web service that exposes a GET operation via the /api/todoitems/ relative URI, an application running in the Android emulator can consume the operation by sending a GET request to http://10.0.2.2:<port>/api/todoitems/.

However, additional work is necessary for an application running in the iOS simulator or Android emulator to consume a local web service that is exposed over HTTPS. For this scenario, the process is as follows:

  1. Create a self-signed development certificate on your machine. For more information, see Create a development certificate.
  2. Configure your project to use the appropriate HttpClient network stack for your debug build. For more information, see Configure your project.
  3. Specify the address of your local machine. For more information, see Specify the local machine address.
  4. Bypass the local development certificate security check. For more information, see Bypass the certificate security check.

Each item will be discussed in turn.

Create a development certificate

Installing the .NET Core SDK installs the ASP.NET Core HTTPS development certificate to the local user certificate store. However, while the certificate has been installed, it's not trusted. To trust the certificate, perform the following one-time step to run the dotnet dev-certs tool:

dotnet dev-certs https --trust

The following command provides help on the dev-certs tool:

dotnet dev-certs https --help

Alternatively, when you run an ASP.NET Core 2.1 project (or above), that uses HTTPS, Visual Studio will detect if the development certificate is missing and will offer to install it and trust it.

Note

The ASP.NET Core HTTPS development certificate is self-signed.

For more information about enabling local HTTPS on your machine, see Enable local HTTPS.

Configure your project

Xamarin applications running on iOS and Android can specify which networking stack is used by the HttpClient class, with the choices being a managed network stack, or native network stacks. The managed stack provides a high level of compatibility with existing .NET code, but is limited to TLS 1.0 and can be slower and result in a larger executable size. The native stacks can be faster and provide better security, but may not provide all the functionality of the HttpClient class.

iOS

Xamarin applications running on iOS can use the managed network stack, or the native CFNetwork or NSUrlSession network stacks. By default, new iOS platform projects use the NSUrlSession network stack, to support TLS 1.2, and use native APIs for better performance and smaller executable size.

However, when an application needs to connect to a secure web service running locally, for developer testing, it's easier to use the managed network stack. Therefore, it's recommended to set debug simulator build profiles to use the managed network stack, and release build profiles to use the NSUrlSession network stack. Each network stack can be set programmatically or via a selector in the project options. For more information, see HttpClient and SSL/TLS implementation selector for iOS/macOS.

Android

Xamarin applications running on Android can use the managed HttpClient network stack, or the native AndroidClientHandler network stack. By default, new Android platform projects use the AndroidClientHandler network stack, to support TLS 1.2, and use native APIs for better performance and smaller executable size. For more information about Android network stacks, see HttpClient Stack and SSL/TLS Implementation selector for Android.

Specify the local machine address

The iOS simulator and Android emulator both provide access to secure web services running on your local machine. However, the local machine address is different for each.

iOS

The iOS simulator uses the host machine network. Therefore, applications running in the simulator can connect to web services running on your local machine via the machines IP address or via the localhost hostname. For example, given a local secure web service that exposes a GET operation via the /api/todoitems/ relative URI, an application running on the iOS simulator can consume the operation by sending a GET request to https://localhost:<port>/api/todoitems/.

Note

When running a mobile application in the iOS simulator from Windows, the application is displayed in the remoted iOS simulator for Windows. However, the application is running on the paired Mac. Therefore, there's no localhost access to a web service running in Windows for an iOS application running on a Mac.

Android

Each instance of the Android emulator is isolated from your development machine network interfaces, and runs behind a virtual router. Therefore, an emulated device can't see your development machine or other emulator instances on the network.

However, the virtual router for each emulator manages a special network space that includes pre-allocated addresses, with the 10.0.2.2 address being an alias to your host loopback interface (127.0.0.1 on your development machine). Therefore, given a local secure web service that exposes a GET operation via the /api/todoitems/ relative URI, an application running on the Android emulator can consume the operation by sending a GET request to https://10.0.2.2:<port>/api/todoitems/.

Xamarin.Forms example

In a Xamarin.Forms application, the Device class can be used to detect the platform the application is running on. The appropriate hostname, that enables access to local secure web services, can then be set as follows:

public static string BaseAddress =
    Device.RuntimePlatform == Device.Android ? "https://10.0.2.2:5001" : "https://localhost:5001";
public static string TodoItemsUrl = $"{BaseAddress}/api/todoitems/";

Bypass the certificate security check

Attempting to invoke a local secure web service from an application running in the iOS simulator or Android emulator will result in a HttpRequestException being thrown, even when using the managed network stack on each platform. This is because the local HTTPS development certificate is self-signed, and self-signed certificates aren't trusted by iOS or Android.

Therefore, it's necessary to ignore SSL errors when an application consumes a local secure web service. The mechanism for accomplishing this is currently different on iOS and Android.

iOS

SSL errors can be ignored on iOS for local secure web services, when using the managed network stack, by setting the ServicePointManager.ServerCertificateValidationCallback property to a callback that ignores the result of the certificate security check for the local HTTPS development certificate:

#if DEBUG
    System.Net.ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) =>
    {
        if (certificate.Issuer.Equals("CN=localhost"))
            return true;
        return sslPolicyErrors == System.Net.Security.SslPolicyErrors.None;
    };
#endif

In this code example, the server certificate validation result is returned when the certificate that underwent validation is not the localhost certificate. For this certificate, the validation result is ignored and true is returned, indicating that the certificate is valid. This code should be added to the AppDelegate.FinishedLaunching method on iOS, prior to the LoadApplication(new App()) method call.

Note

The native network stacks on iOS don't hook into the ServerCertificateValidationCallback.

Android

SSL errors can be ignored on Android for local secure web services, when using both the managed and native AndroidClientHandler network stacks, by setting the ServerCertificateCustomValidationCallback property on a HttpClientHandler object to a callback that ignores the result of the certificate security check for the local HTTPS development certificate:

public HttpClientHandler GetInsecureHandler()
{
    var handler = new HttpClientHandler();
    handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
    {
        if (cert.Issuer.Equals("CN=localhost"))
            return true;
        return errors == System.Net.Security.SslPolicyErrors.None;
    };
    return handler;
}

In this code example, the server certificate validation result is returned when the certificate that underwent validation is not the localhost certificate. For this certificate, the validation result is ignored and true is returned, indicating that the certificate is valid. The resulting HttpClientHandler object should be passed as an argument to the HttpClient constructor.