共用方式為


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

流覽範例。 流覽範例

許多行動裝置和傳統型應用程式都會取用 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 ASP.NET Core Web 服務項目中 launchSettings.json段來達成此目的:

{
  ...
  "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 上啟用純文字本機流量有兩個主要方法:

  • 啟用純文本網路流量,以便與所有網域通訊。 如需詳細資訊,請參閱 為所有網域啟用純文本網路流量。
  • 啟用純文本網路流量,以便與 localhost 網域通訊。 如需詳細資訊,請參閱 啟用localhost網域的純文本網路流量。

為所有網域啟用純文本網路流量

您可以將 屬性的 屬性設定為 true,以啟用UsesCleartextTraffic所有網域的Application純文字網路流量。 這應該在 .NET MAUI 應用程式專案中的平臺 > Android > MainApplication.cs 檔案中執行,而且應該包裝在 中 #if DEBUG ,以確保它不會意外在生產應用程式中啟用:

#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();
}

注意

UsesCleartextTraffic如果存在網路安全性配置檔,則會在 Android 7.0 (API 24) 和更新版本上忽略 屬性。

啟用localhost網域的純文本網路流量

您可以建立網路安全組態檔來啟用網域的 localhost 純文本網路流量。 將名為 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)
    {
        return url.StartsWith("https://localhost");
    }
#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 服務。