maui-aspire について
.NET MAUI 開発者向けの .NET Aspire 連携ガイドです。モバイルアプリと Aspire バックエンド間のネットワーク、認証、デバッグの違いを説明し、到達可能なエンドポイントと Android エミュレーターの設定を扱います。
主な機能
- 01MAUI クライアントと Aspire のオーケストレーションを区別
- 02デバイスから到達できるエンドポイントを使用
- 03Android エミュレーターのネットワークアドレスを設定
- 04MSAL.NET のパブリッククライアント認証を使用
- 05MAUI とバックエンドの並行デバッグを調整
活用シーン
- 01Aspire で実行する API への接続
- 02Android エミュレーターからホストに接続できない問題の調査
- 03MAUI アプリの Entra 認証設定
- 04MAUI クライアントとバックエンドサービスのデバッグ
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ davidortinau/ maui-skills --skill maui-aspireインストール後、Claude Code で/maui-aspireを入力して読み込まれたか確認します。
同梱ファイルreferences/aspire-api.md
詳細
.NET MAUI と .NET Aspire
他の Aspire クライアントとの主な違い
MAUI アプリは AppHost によるオーケストレーションの対象ではありません。デバイスやシミュレーター上で実行され、ネットワーク経由で接続します。そのため、すべてが変わります。
- ❌ Aspire のサービス検出 URI(
https+http://apiservice)は使用できません - ❌ AppHost で
.WithReference()を使って追加できません - ❌
AddServiceDefaults()は使用できません(ASP.NET Core ホストではありません) - ✅ ネットワークから到達可能な実際のエンドポイントを使用する必要があります
- ✅ MSAL.NET(パブリッククライアント)を使用する必要があります。OIDC(コンフィデンシャルクライアント)ではありません
よくある注意点
1. ❌ MAUI を AppHost に追加しないでください
// ❌ MAUI doesn't implement IServiceMetadata — this will fail
builder.AddProject<Projects.MyMauiApp>("mauiapp");
// ✅ Only add backend services to the AppHost
var apiService = builder.AddProject<Projects.MyApp_ApiService>("apiservice");
2. ❌ MAUI で Aspire のサービス検出 URI を使用しないでください
// ❌ This only resolves inside the Aspire AppHost orchestration
client.BaseAddress = new Uri("https+http://apiservice");
// ✅ Use real endpoints
client.BaseAddress = new Uri("https://localhost:7001");
3. ⚠️ Android エミュレーターから localhost に接続できません
Android エミュレーターは独自のネットワークスタックを持っています。localhost はホストマシンではなく、エミュレーター自体を指します。
// ❌ Fails silently on Android emulator
client.BaseAddress = new Uri("https://localhost:7001");
// ✅ Use 10.0.2.2 for host loopback on Android emulator
#if ANDROID && DEBUG
client.BaseAddress = new Uri("https://10.0.2.2:7001");
#else
client.BaseAddress = new Uri("https://localhost:7001");
#endif
4. ⚠️ Android エミュレーターは .NET の開発用証明書を信頼しません
エミュレーターは HTTPS の開発用証明書を信頼しません。ローカル開発中は、次のようにします。
// ⚠️ Development only — never ship this
#if ANDROID && DEBUG
builder.Services.AddHttpClient<IWeatherApiClient, WeatherApiClient>(client =>
{
client.BaseAddress = new Uri("https://10.0.2.2:7001");
})
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (_, _, _, _) => true
});
#endif
5. ⚠️ 認証にはコンフィデンシャルクライアントではなく、パブリッククライアントを使用します
MAUI では PublicClientApplication(MSAL.NET)を使用します。Entra Aspire 認証スキル(entra-id-aspire-authentication)は、API/Blazor Server 側専用です。MAUI 側では maui-authentication スキルを使用してください。
6. ⚠️ Aspire には .NET 10 以降が必要です
Aspire のバックエンドに合わせて、MAUI プロジェクトも net10.0-* TFM をターゲットにしてください。
Blazor Hybrid に関する注意事項
Aspire サービスを呼び出す MAUI Blazor Hybrid アプリでは、認証は Blazor WebView ではなく、MAUI レイヤー(MSAL.NET)で行われます。MAUI アプリでは AddMicrosoftIdentityWebApp やサーバー側の OIDC パターンを使用しないでください。
Aspire のサービスの既定値は適用されません
MAUI プロジェクトでは AddServiceDefaults() を使用しないでください。理由は次のとおりです。
- MAUI アプリは ASP.NET Core ホストではありません
- モバイル向けの OpenTelemetry には異なる要件があります
- ヘルスチェックのエンドポイントはクライアントアプリには適用されません
テレメトリの相関関係を設定するには、System.Diagnostics API を使用して OpenTelemetry を別途構成してください。
開発ワークフローの選択
| シナリオ | 対応方法 |
|---|---|
| API の問題をデバッグする | https://localhost:17178 の Aspire ダッシュボードを使用します |
| MAUI と API をデバッグする | 1 つのターミナルで Aspire AppHost を実行し、もう 1 つのターミナルで MAUI を実行します |
| VS:同時デバッグ | VS のインスタンスを 2 つ開きます。プロジェクトごとに 1 つずつ使用します |
| VS Code | ターミナルを 2 つ使用するか、Aspire 拡張機能と MAUI 拡張機能を使用します |
プラットフォームのネットワーク設定クイックリファレンス
| プラットフォーム | localhost を使用できますか? | HTTPS の開発用証明書は信頼されますか? | 特別な設定が必要ですか? |
|---|---|---|---|
| iOS シミュレーター | ✅ はい | ✅ はい(macOS のキーチェーン) | HTTP 用の ATS 例外 |
| Android エミュレーター | ❌ 10.0.2.2 を使用 | ❌ いいえ | ネットワークセキュリティ構成 |
| Mac Catalyst | ✅ はい | ✅ はい | なし |
| Windows | ✅ はい | ✅ はい | なし |
チェックリスト
- MAUI プロジェクトを
AddProjectで AppHost に追加していない - API のベース URL に、
https+http://URI ではなく実際のエンドポイントを使用している - Android:
localhostの代わりに10.0.2.2を使用している - Android:ローカル開発時に限り、SSL のバイパスまたは HTTP の構成を使用している
- 認証に、コンフィデンシャルクライアントではなく MSAL.NET の
PublicClientApplicationを使用している - MAUI と Aspire の両方で
net10.0-*をターゲットにしている - MAUI プロジェクトで
AddServiceDefaults()を呼び出していない