Condividi tramite


Connettersi ai servizi Web locali da emulatori Android e simulatori iOS

Sfogliare l'esempio. Esplorare l'esempio

Molte app per dispositivi mobili e desktop usano servizi Web. Durante la fase di sviluppo software, è comune distribuire un servizio Web in locale e usarlo da un'app in esecuzione nell'emulatore Android o nel simulatore iOS. Ciò evita di dover distribuire il servizio Web in un endpoint ospitato e consente un'esperienza di debug semplice perché sia l'app che il servizio Web sono in esecuzione in locale.

Le app .NET multipiattaforma dell'interfaccia utente (.NET MAUI) eseguite in Windows o MacCatalyst possono usare ASP.NET Servizi Web Core in esecuzione localmente su HTTP o HTTPS senza ulteriori operazioni, purché sia stato considerato attendibile il certificato di sviluppo. Tuttavia, è necessario un lavoro aggiuntivo quando l'app è in esecuzione nell'emulatore Android o nel simulatore iOS e il processo è diverso a seconda che il servizio Web sia in esecuzione su HTTP o HTTPS.

Indirizzo computer locale

L'emulatore Android e il simulatore iOS forniscono entrambi l'accesso ai servizi Web in esecuzione su HTTP o HTTPS nel computer locale. Tuttavia, l'indirizzo del computer locale è diverso per ognuno.

Android

Ogni istanza dell'emulatore di Android è isolata dalle interfacce di rete del computer di sviluppo e viene eseguita dietro un router virtuale. Pertanto, un dispositivo emulato non può visualizzare il computer di sviluppo o altre istanze dell'emulatore in rete.

Tuttavia, il router virtuale per ogni emulatore gestisce uno spazio di rete speciale che include gli indirizzi già allocati, con l'indirizzo 10.0.2.2 usato come alias per l'interfaccia di loopback host (127.0.0.1 nel computer di sviluppo). Pertanto, dato un servizio Web locale che espone un'operazione GET tramite l'URI /api/todoitems/ relativo, un'app in esecuzione nell'emulatore Android può utilizzare l'operazione inviando una richiesta GET a http://10.0.2.2:<port>/api/todoitems/ o https://10.0.2.2:<port>/api/todoitems/.

iOS

Il simulatore iOS usa la rete del computer host. Pertanto, le app in esecuzione nel simulatore possono connettersi ai servizi Web in esecuzione nel computer locale tramite l'indirizzo IP dei computer o tramite il localhost nome host. Ad esempio, dato un servizio Web locale che espone un'operazione GET tramite l'URI /api/todoitems/ relativo, un'app in esecuzione nel simulatore iOS può utilizzare l'operazione inviando una richiesta GET a http://localhost:<port>/api/todoitems/ o https://localhost:<port>/api/todoitems/.

Nota

Quando si esegue un'app .NET MAUI nel simulatore iOS da Windows, l'app viene visualizzata nel simulatore iOS remoto per Windows. Tuttavia, l'app è in esecuzione nel Mac associato. Di conseguenza, non esiste alcun accesso localhost a un servizio Web in esecuzione in Windows per un'app iOS in esecuzione in un Mac.

Servizi Web locali in esecuzione su HTTP

Un'app MAUI .NET in esecuzione nell'emulatore Android o nel simulatore iOS può usare un servizio Web ASP.NET Core in esecuzione localmente su HTTP. A tale scopo, è possibile configurare il progetto di app .NET MAUI e il progetto di servizio Web di ASP.NET Core per consentire il traffico HTTP non crittografato.

Nel codice che definisce l'URL del servizio Web locale nell'app MAUI .NET, assicurarsi che l'URL del servizio Web specifichi lo schema HTTP e il nome host corretto. La DeviceInfo classe può essere usata per rilevare la piattaforma in cui è in esecuzione l'app. Il nome host corretto può quindi essere impostato come segue:

public static string BaseAddress =
    DeviceInfo.Platform == DevicePlatform.Android ? "http://10.0.2.2:5000" : "http://localhost:5000";
public static string TodoItemsUrl = $"{BaseAddress}/api/todoitems/";

Per altre informazioni sulla DeviceInfo classe, vedere Informazioni sul dispositivo.

Inoltre, per eseguire l'app in Android, è necessario aggiungere la configurazione di rete necessaria e per eseguire l'app in iOS è necessario rifiutare esplicitamente Apple Transport Security (ATS). Per altre informazioni, vedere Configurazione di rete Android e configurazione di iOS ATS.

È anche necessario assicurarsi che il servizio Web ASP.NET Core sia configurato per consentire il traffico HTTP. A tale scopo, è possibile aggiungere un profilo HTTP alla profiles sezione di launchSettings.json nel progetto di servizio Web ASP.NET Core:

{
  ...
  "profiles": {
    "http": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "launchUrl": "api/todoitems",
      "applicationUrl": "http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    ...
  }
}

Un'app MAUI .NET in esecuzione nell'emulatore Android o nel simulatore iOS può quindi usare un servizio Web ASP.NET Core in esecuzione in locale su HTTP, a condizione che il servizio Web venga avviato con il http profilo.

Configurazione di rete Android

Esistono due approcci principali per abilitare il traffico locale di testo non crittografato in Android:

Abilitare il traffico di rete non crittografato per tutti i domini

Il traffico di rete non crittografato per tutti i domini può essere abilitato impostando la UsesCleartextTraffic proprietà dell'attributo Application su true. Questa operazione deve essere eseguita nel file Platforms > Android > MainApplication.cs nel progetto di app MAUI .NET e deve essere sottoposto a wrapping in per #if DEBUG assicurarsi che non sia abilitato accidentalmente in un'app di produzione:

#if DEBUG
[Application(UsesCleartextTraffic = true)]
#else
[Application]
#endif
public class MainApplication : MauiApplication
{
    public MainApplication(IntPtr handle, JniHandleOwnership ownership)
        : base(handle, ownership)
    {
    }

    protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
}

Nota

La UsesCleartextTraffic proprietà viene ignorata in Android 7.0 (API 24) e versioni successive se è presente un file di configurazione della sicurezza di rete.

Abilitare il traffico di rete non crittografato per il dominio localhost

Il traffico di rete non crittografato per il localhost dominio può essere abilitato creando un file di configurazione della sicurezza di rete. A tale scopo, è possibile aggiungere un nuovo file XML denominato network_security_config.xml alla cartella Platforms\Android\Resources\xml nel progetto di app MAUI .NET. Il file XML deve specificare la configurazione seguente:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
  <domain-config cleartextTrafficPermitted="true">
    <domain includeSubdomains="true">10.0.2.2</domain>
  </domain-config>
</network-security-config>

Nota

Assicurarsi che l'azione di compilazione del file network_security_config.xml sia impostata su AndroidResource.

Configurare quindi la proprietà networkSecurityConfig nel nodo applicazione nel file Platforms\Android\AndroidManifest.xml nel progetto di app MAUI .NET:

<?xml version="1.0" encoding="utf-8"?>
<manifest>
    <application android:networkSecurityConfig="@xml/network_security_config" ...>
        ...
    </application>
</manifest>

Per altre informazioni sui file di configurazione della sicurezza di rete, vedere Configurazione della sicurezza di rete in developer.android.com.

Configurazione di iOS ATS

Per abilitare il traffico locale non crittografato in iOS, è necessario rifiutare esplicitamente Apple Transport Security (ATS) nell'app .NET MAUI. A tale scopo, aggiungere la configurazione seguente al file Platforms\iOS\Info.plist nel progetto di app MAUI .NET:

<key>NSAppTransportSecurity</key>    
<dict>
    <key>NSAllowsLocalNetworking</key>
    <true/>
</dict>

Per altre informazioni su ATS, vedere Prevenzione delle connessioni di rete non sicure in developer.apple.com.

Servizi Web locali in esecuzione su HTTPS

Un'app MAUI .NET in esecuzione nell'emulatore Android o nel simulatore iOS può usare un servizio Web ASP.NET Core in esecuzione in locale su HTTPS. Il processo per abilitare questa operazione è il seguente:

  1. Considerare attendibile il certificato di sviluppo autofirmato nel computer. Per altre informazioni, vedere Considerare attendibile il certificato di sviluppo.
  2. Specificare l'indirizzo del computer locale. Per altre informazioni, vedere Specificare l'indirizzo del computer locale.
  3. Evitare il controllo di sicurezza del certificato di sviluppo locale. Per altre informazioni, vedere Evitare il controllo di sicurezza del certificato.

Ogni elemento verrà presentato singolarmente.

Considerare attendibile il certificato di sviluppo

L'installazione di .NET Core SDK installa il certificato di sviluppo HTTPS di ASP.NET Core nell'archivio certificati utente locale. Tuttavia, anche se il certificato viene installato, non è attendibile. Per rendere attendibile il certificato, seguire questa procedura una sola volta per eseguire lo strumento dev-certs dotnet:

dotnet dev-certs https --trust

Il comando seguente consente di visualizzare informazioni della Guida sullo strumento dev-certs:

dotnet dev-certs https --help

In alternativa, quando si esegue un progetto ASP.NET Core 2.1 (o versione successiva), che usa HTTPS, Visual Studio rileva se il certificato di sviluppo è mancante e offre di installarlo e impostarlo come attendibile.

Nota

Il certificato di sviluppo HTTPS ASP.NET Core è autofirmato.

Per altre informazioni sull'abilitazione di HTTPS locale nel computer, vedere Abilitare HTTPS locale.

Specificare l'indirizzo del computer locale

Nel codice che definisce l'URL del servizio Web locale nell'app MAUI .NET, assicurarsi che l'URL del servizio Web specifichi lo schema HTTPS e il nome host corretto. La DeviceInfo classe può essere usata per rilevare la piattaforma in cui è in esecuzione l'app. Il nome host corretto può quindi essere impostato come segue:

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

Per altre informazioni sulla DeviceInfo classe, vedere Informazioni sul dispositivo.

Evitare il controllo di sicurezza del certificato

Se si tenta di richiamare un servizio Web protetto locale da un'app MAUI .NET in esecuzione in un emulatore Android, verrà generato un java.security.cert.CertPathValidatorException messaggio che indica che l'ancoraggio di attendibilità per il percorso di certificazione non è stato trovato. Analogamente, il tentativo di richiamare un servizio Web protetto locale da un'app MAUI .NET in esecuzione in un simulatore iOS genererà un NSURLErrorDomain errore con un messaggio che indica che il certificato per il server non è valido. Questi errori si verificano perché il certificato di sviluppo HTTPS locale è autofirmato e i certificati autofirmati non sono considerati attendibili da Android o iOS. Pertanto, è necessario ignorare gli errori SSL quando un'app utilizza un servizio Web protetto locale.

A tale scopo, è possibile passare versioni configurate delle classi native HttpMessageHandler al HttpClient costruttore, che indica alla classe di considerare attendibile la HttpClient comunicazione localhost tramite HTTPS. La HttpMessageHandler classe è una classe astratta, la cui implementazione in Android viene fornita dalla classe e la AndroidMessageHandlerNSUrlSessionHandler cui implementazione in iOS viene fornita dalla classe .

L'esempio seguente illustra una classe che configura la classe in Android e la classe in iOS per considerare attendibile la AndroidMessageHandlerNSUrlSessionHandler comunicazione localhost tramite HTTPS:

public class HttpsClientHandlerService
{
    public HttpMessageHandler GetPlatformMessageHandler()
    {
#if ANDROID
        var handler = new Xamarin.Android.Net.AndroidMessageHandler();
        handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
        {
            if (cert != null && cert.Issuer.Equals("CN=localhost"))
                return true;
            return errors == System.Net.Security.SslPolicyErrors.None;
        };
        return handler;
#elif IOS
        var handler = new NSUrlSessionHandler
        {
            TrustOverrideForUrl = IsHttpsLocalhost
        };
        return handler;
#else
     throw new PlatformNotSupportedException("Only Android and iOS supported.");
#endif
    }

#if IOS
    public bool IsHttpsLocalhost(NSUrlSessionHandler sender, string url, Security.SecTrust trust)
    {
        return url.StartsWith("https://localhost");
    }
#endif
}

In Android il GetPlatformMessageHandler metodo restituisce un AndroidMessageHandler oggetto . Il GetPlatformMessageHandler metodo imposta la ServerCertificateCustomValidationCallback proprietà sull'oggetto AndroidMessageHandler su un callback che ignora il risultato del controllo di sicurezza del certificato per il certificato di sviluppo HTTPS locale.

In iOS il GetPlatformMessageHandler metodo restituisce un NSUrlSessionHandler oggetto che imposta la relativa TrustOverrideForUrl proprietà su un delegato denominato IsHttpsLocalHost che corrisponde alla firma del NSUrlSessionHandler.NSUrlSessionHandlerTrustOverrideForUrlCallback delegato. Il IsHttpsLocalHost delegato restituisce true quando l'URL inizia con https://localhost.

L'oggetto risultante HttpClientHandler può quindi essere passato come argomento al HttpClient costruttore per le compilazioni di debug:

#if DEBUG
            HttpsClientHandlerService handler = new HttpsClientHandlerService();
            HttpClient client = new HttpClient(handler.GetPlatformMessageHandler());
#else
            client = new HttpClient();
#endif

Un'app MAUI .NET in esecuzione nell'emulatore Android o nel simulatore iOS può quindi usare un servizio Web ASP.NET Core in esecuzione in locale tramite HTTPS.