Many mobile and desktop apps consume web services. During the software development phase, it's common to deploy a web service locally and consume it from an app running in the Android emulator or iOS simulator. This avoids having to deploy the web service to a hosted endpoint, and enables a straightforward debugging experience because both the app and web service are running locally.
.NET Multi-platform App UI (.NET MAUI) apps that run on Windows or MacCatalyst can consume ASP.NET Core web services that are running locally over HTTP or HTTPS without any additional work, provided that you've trusted your development certificate. However, additional work is required when the app is running in the Android emulator or iOS simulator, and the process is different depending on whether the web service is running over HTTP or HTTPS.
Local machine address
The Android emulator and iOS simulator both provide access to web services running over HTTP or HTTPS on your local machine. However, the local machine address is different for each.
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 web service that exposes a GET operation via the /api/todoitems/ relative URI, an app running on the Android emulator can consume the operation by sending a GET request to http://10.0.2.2:<port>/api/todoitems/ or https://10.0.2.2:<port>/api/todoitems/.
iOS
The iOS simulator uses the host machine network. Therefore, apps 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 web service that exposes a GET operation via the /api/todoitems/ relative URI, an app running on the iOS simulator can consume the operation by sending a GET request to http://localhost:<port>/api/todoitems/ or https://localhost:<port>/api/todoitems/.
Note
When running a .NET MAUI app in the iOS simulator from Windows, the app is displayed in the remote iOS simulator for Windows. However, the app is running on the paired Mac. Therefore, there's no localhost access to a web service running in Windows for an iOS app running on a Mac.
Local web services running over HTTP
A .NET MAUI app running in the Android emulator or iOS simulator can consume an ASP.NET Core web service that's running locally over HTTP. This can be achieved by configuring your .NET MAUI app project and your ASP.NET Core web service project to allow clear-text HTTP traffic.
In the code that defines the URL of your local web service in your .NET MAUI app, ensure that the web service URL specifies the HTTP scheme, and the correct hostname. The DeviceInfo class can be used to detect the platform the app is running on. The correct hostname can then be set as follows:
public static string BaseAddress =
DeviceInfo.Platform == DevicePlatform.Android ? "http://10.0.2.2:5000" : "http://localhost:5000";
public static string TodoItemsUrl = $"{BaseAddress}/api/todoitems/";
In addition, to run your app on Android you must add the required network configuration, and to run your app on iOS you must opt-out of Apple Transport Security (ATS). For more information, see Android network configuration and iOS ATS configuration.
You must also ensure that your ASP.NET Core web service is configured to allow HTTP traffic. This can be achieved by adding a HTTP profile to the profiles section of launchSettings.json in your ASP.NET Core web service project:
A .NET MAUI app running in the Android emulator or iOS simulator can then consume an ASP.NET Core web service that's running locally over HTTP, provided that web service is launched with the http profile.
Android network configuration
There are two main approaches to enabling clear-text local traffic on Android:
Clear-text network traffic for all domains can be enabled by setting the UsesCleartextTraffic property of the Application attribute to true. This should be performed in the Platforms > Android > MainApplication.cs file in your .NET MAUI app project, and should be wrapped in an #if DEBUG to ensure that it isn't accidentally enabled in a production app:
The UsesCleartextTraffic property is ignored on Android 7.0 (API 24) and higher if a network security config file is present.
Enable clear-text network traffic for the localhost domain
Clear-text network traffic for the localhost domain can be enabled by creating a network security configuration file. This can be achieved by adding a new XML file named network_security_config.xml to the Platforms\Android\Resources\xml folder in your .NET MAUI app project. The XML file should specify the following configuration:
Ensure that the build action of the network_security_config.xml file is set to AndroidResource.
Then, configure the networkSecurityConfig property on the application node in the Platforms\Android\AndroidManifest.xml file in your .NET MAUI app project:
For more information about network security configuration files, see Network security configuration on developer.android.com.
iOS ATS configuration
To enable clear-text local traffic on iOS you should opt-out of Apple Transport Security (ATS) in your .NET MAUI app. This can be achieved by adding the following configuration to the Platforms\iOS\Info.plist file in your .NET MAUI app project:
A .NET MAUI app running in the Android emulator or iOS simulator can consume an ASP.NET Core web service that's running locally over HTTPS. The process to enable this is as follows:
Installing the .NET Core SDK installs the ASP.NET Core HTTPS development certificate to your 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.
Specify the local machine address
In the code that defines the URL of your local web service in your .NET MAUI app, ensure that the web service URL specifies the HTTPS scheme, and the correct hostname. The DeviceInfo class can be used to detect the platform the app is running on. The correct hostname can then be set as follows:
public static string BaseAddress =
DeviceInfo.Platform == DevicePlatform.Android ? "https://10.0.2.2:5001" : "https://localhost:5001";
public static string TodoItemsUrl = $"{BaseAddress}/api/todoitems/";
Attempting to invoke a local secure web service from a .NET MAUI app running in an Android emulator will result in a java.security.cert.CertPathValidatorException being thrown, with a message indicating that the trust anchor for the certification path hasn't been found. Similarly, attempting to invoke a local secure web service from a .NET MAUI app running in an iOS simulator will result in an NSURLErrorDomain error with a message indicating that the certificate for the server is invalid. These errors occur because the local HTTPS development certificate is self-signed, and self-signed certificates aren't trusted by Android or iOS. Therefore, it's necessary to ignore SSL errors when an app consumes a local secure web service.
This can be accomplished by configuring an instance of HttpClientHandler with a custom ServerCertificateCustomValidationCallback, which instructs the HttpClient class to trust localhost communication over HTTPS. The following example shows how to create an instance of HttpClientHandler that will ignore localhost certificate validation errors:
var handler = new HttpClientHandler();
#if DEBUG
handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
{
if (cert != null && cert.Issuer.Equals("CN=localhost"))
return true;
return errors == System.Net.Security.SslPolicyErrors.None;
};
#endif
var client = new HttpClient(handler);
Important
The code above ignores localhost certificate validation errors, but only in debug builds. This approach avoids security incidents in production builds.
A .NET MAUI app running in the Android emulator or iOS simulator can then consume an ASP.NET Core web service that's running locally over HTTPS.
Collaborate with us on GitHub
The source for this content can be found on GitHub, where you can also create and review issues and pull requests. For more information, see our contributor guide.
.NET MAUI feedback
.NET MAUI is an open source project. Select a link to provide feedback:
Build a .NET Multi-platform App UI (MAUI) application that consumes a REST web service by using HttpClient and performs basic CRUD operations. In the app, you detect when your device is connected to the internet to provide a good user experience and take advantage of the native networking stacks to get top performance.
Build end-to-end solutions in Microsoft Azure to create Azure Functions, implement and manage web apps, develop solutions utilizing Azure storage, and more.
.NET MAUI provides cross-platform APIs to access platform functionality that includes access to sensors, storing data, and checking network connectivity.
Learn how to use the .NET MAUI IConnectivity interface in the Microsoft.Maui.Networking namespace. With this interface, you can determine if you can communicate with the internet and which network devices are connected
Learn about the Android app manifest, AndroidManifest.xml, that describes essential information about your app to build tools, the Android OS, and Google Play.
.NET MAUI supports database-driven applications using the SQLite database engine, which makes it possible to load and save objects in shared code. This article describes how .NET MAUI applications can read and write data to a local SQLite database using SQLite-net