從 Android 模擬器和 iOS 模擬器 連線 至本機 Web 服務

Browse sample. 流覽範例

許多行動裝置和傳統型應用程式都會取用 Web 服務。 在軟體開發階段,通常會在本機部署 Web 服務,並從在 Android 模擬器或 iOS 模擬器中執行的應用程式取用 Web 服務。 這可避免將 Web 服務部署至託管端點,並啟用簡單的偵錯體驗,因為應用程式和 Web 服務都在本機執行。

在 Windows 或 MacCatalyst 上執行的 .NET 多平台應用程式 UI (.NET MAUI) 應用程式,只要您已 信任開發憑證,即可取用透過 HTTP 或 HTTPS 在本機執行的 ASP.NET Core Web 服務,而不需要任何額外的工作。 不過,當應用程式在 Android 模擬器或 iOS 模擬器中執行時,需要額外的工作,而且程式會根據 Web 服務是透過 HTTP 或 HTTPS 執行而有所不同。

本機計算機位址

Android 模擬器和 iOS 模擬器都可讓您存取在本機電腦上透過 HTTP 或 HTTPS 執行的 Web 服務。 但是每部電腦的本機電腦位址都不一樣。

Android

Android 模擬器的每個執行個體都會與您的開發電腦網路介面隔離,並在虛擬路由器背後執行。 因此,模擬的裝置看不到您的開發電腦,或網路上的其他模擬器執行個體。

但是,每個模擬器的虛擬路由器都會管理一個特殊的網路空間,其中包括預先配置的位址,而 10.0.2.2 位址為您主機回送介面的別名 (在您的開發電腦上為 127.0.0.1)。 因此,假設本機 Web 服務透過 /api/todoitems/ 相對 URI 公開 GET 作業,Android 模擬器上執行的應用程式可以藉由將 GET 要求傳送至 http://10.0.2.2:<port>/api/todoitems/https://10.0.2.2:<port>/api/todoitems/來取用作業。

iOS

iOS 模擬器會使用主機電腦網路。 因此,在模擬器中執行的應用程式可以透過電腦IP位址或 localhost 主機名連線到本機電腦上執行的Web服務。 例如,假設本機 Web 服務透過 /api/todoitems/ 相對 URI 公開 GET 作業,在 iOS 模擬器上執行的應用程式可以藉由將 GET 要求傳送至 http://localhost:<port>/api/todoitems/https://localhost:<port>/api/todoitems/來取用作業。

注意

從 Windows 在 iOS 模擬器中執行 .NET MAUI 應用程式時,應用程式會顯示在 Windows 的遠端 iOS 模擬器中。 不過,應用程式正在配對的 Mac 上執行。 因此,對於在 Mac 上執行的 iOS 應用程式,在 Windows 中執行的 Web 服務沒有 localhost 存取權。

透過 HTTP 執行的本機 Web 服務

在 Android 模擬器或 iOS 模擬器中執行的 .NET MAUI 應用程式,可以使用透過 HTTP 在本機執行的 ASP.NET Core Web 服務。 您可以藉由設定 .NET MAUI 應用程式專案和 ASP.NET Core Web 服務專案,以允許純文本 HTTP 流量來達成此目的。

在 .NET MAUI 應用程式中定義本機 Web 服務的 URL 的程式代碼中,請確定 Web 服務 URL 會指定 HTTP 配置,以及正確的主機名。 類別 DeviceInfo 可用來偵測應用程式執行的平臺。 接著可以設定正確的主機名,如下所示:

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

如需 類別 DeviceInfo 的詳細資訊,請參閱 裝置資訊

此外,若要在 Android 上執行您的應用程式,您必須新增必要的網路安全性設定,並在 iOS 上執行您的應用程式,您必須退出宣告 Apple Transport Security (ATS)。 如需詳細資訊,請參閱 Android 網路安全性設定iOS ATS 設定

您也必須確定您的 ASP.NET Core Web 服務已設定為允許 HTTP 流量。 這可以透過將 HTTP 配置檔新增至 profiles launch 的 區段來達成 設定.json 在您的 ASP.NET Core Web 服務專案中:

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

在 Android 模擬器或 iOS 模擬器中執行的 .NET MAUI 應用程式,接著可以使用透過 HTTP 在本機執行的 ASP.NET Core Web 服務,前提是 Web 服務是以配置檔啟動 http

Android 網路安全性設定

若要在 Android 上啟用純文字本機流量,您必須建立網路安全組態檔。 將名為 network_security_config.xml 的新 XML 檔案新增至 .NET MAUI 應用程式專案中的 Platform\Android\Resources\xml 資料夾,即可達成此目的。 XML 檔案應該指定下列組態:

<?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>

注意

確定network_security_config.xml檔案的 建置 動作已設定為 AndroidResource

然後,在 .NET MAUI 應用程式專案中 Platform\Android\AndroidManifest.xml 檔案的應用程式節點上設定 networkSecurityConfig 屬性:

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

如需網路安全組態檔的詳細資訊,請參閱 developer.android.com 上的網路安全性 設定。

iOS ATS 設定

若要在 iOS 上啟用純文字本機流量,您應該退出宣告 .NET MAUI 應用程式中的 Apple Transport Security (ATS)。 將下列組態新增至 .NET MAUI 應用程式專案中的 Platform\iOS\Info.plist 檔案,即可達成此目的:

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

如需 ATS 的詳細資訊,請參閱防止 developer.apple.com 上的不安全網路 連線。

透過 HTTPS 執行的本機 Web 服務

在 Android 模擬器或 iOS 模擬器中執行的 .NET MAUI 應用程式,可以使用透過 HTTPS 在本機執行的 ASP.NET Core Web 服務。 開啟此作業的程式如下所示:

  1. 信任您電腦上的自我簽署開發憑證。 如需詳細資訊,請參閱 信任您的開發憑證
  2. 指定本機電腦的位址。 如需詳細資訊,請參閱指定本機電腦位址
  3. 繞過本機開發憑證安全性檢查。 如需詳細資訊,請參閱繞過憑證安全性檢查

我們會輪流討論每個項目。

信任您的開發憑證

安裝 .NET Core SDK 會將 ASP.NET Core HTTPS 開發憑證安裝到本機使用者證書存儲。 但是,雖然已安裝憑證,但憑證不受信任。 若要信任憑證,請執行下面的一次性步驟,以執行 dotnet dev-certs 工具:

dotnet dev-certs https --trust

下列命令會提供 dev-certs 工具的說明:

dotnet dev-certs https --help

或者,當您使用 HTTPS 執行 ASP.NET Core 2.1 專案 (或更新版本) 時,Visual Studio 會偵測開發憑證是否遺失,且將提供安裝並信任該憑證。

注意

ASP.NET Core HTTPS 開發憑證是自我簽署的。

如需在電腦上啟用本機 HTTPS 的詳細資訊,請參閱啟用本機 HTTPS

指定本機電腦位址

在 .NET MAUI 應用程式中定義本機 Web 服務的 URL 的程式代碼中,請確定 Web 服務 URL 指定 HTTPS 配置,以及正確的主機名。 類別 DeviceInfo 可用來偵測應用程式執行的平臺。 接著可以設定正確的主機名,如下所示:

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

如需 類別 DeviceInfo 的詳細資訊,請參閱 裝置資訊

繞過憑證安全性檢查

嘗試從在 Android 模擬器中執行的 .NET MAUI 應用程式叫用本機安全 Web 服務會導致 java.security.cert.CertPathValidatorException 擲回,並出現訊息,指出找不到認證路徑的信任錨點。 同樣地,嘗試從 iOS 模擬器中執行的 .NET MAUI 應用程式叫用本機安全 Web 服務,將會產生 NSURLErrorDomain 錯誤,指出伺服器的憑證無效。 發生這些錯誤的原因是本機 HTTPS 開發憑證是自我簽署,而 Android 或 iOS 不會信任自我簽署憑證。 因此,當應用程式取用本機安全 Web 服務時,必須忽略 SSL 錯誤。

這可以藉由將已設定的原生 HttpMessageHandler 類別版本傳遞至 HttpClient 建構函式來完成,以指示 HttpClient 類別信任透過 HTTPS 的 localhost 通訊。 類別 HttpMessageHandler 是抽象類,其 Android 上的實作是由 AndroidMessageHandler 類別提供,而 iOS 上的 NSUrlSessionHandler 實作是由 類別提供。

下列範例顯示類別,其 AndroidMessageHandler 會在 Android 上設定 類別,以及 NSUrlSessionHandler iOS 上的 類別,以信任透過 HTTPS 的 localhost 通訊:

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)
    {
        if (url.StartsWith("https://localhost"))
            return true;
        return false;
    }
#endif
}

在Android上 GetPlatformMessageHandler ,方法會傳 AndroidMessageHandler 回物件。 方法會將 GetPlatformMessageHandlerServerCertificateCustomValidationCallback 物件上的 AndroidMessageHandler 屬性設定為回呼,這個回呼會忽略本機 HTTPS 開發憑證的憑證安全性檢查結果。

在 iOS 上 GetPlatformMessageHandler ,方法會 NSUrlSessionHandler 傳回 物件,該物件會將其 TrustOverrideForUrl 屬性設定為與 IsHttpsLocalHost 委派簽章相符的 NSUrlSessionHandler.NSUrlSessionHandlerTrustOverrideForUrlCallback 委派。 當 URL 以 開頭https://localhost時,委派IsHttpsLocalHosttrue傳回 。

然後,產生的 HttpClientHandler 物件可以當做自變數傳遞至偵錯組建的 HttpClient 建構函式:

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

在 Android 模擬器或 iOS 模擬器中執行的 .NET MAUI 應用程式,接著可以使用透過 HTTPS 在本機執行的 ASP.NET Core Web 服務。