mcpField
M
maui-hybridwebview

maui-hybridwebview

github.com/davidortinau開発17644 回インストール16 週間前に更新
リポジトリ

maui-hybridwebview について

.NET MAUI の HybridWebView でローカルの Web コンテンツを表示し、JavaScript と C# を連携させるための実用ガイドです。相互運用の設定、シリアル化、例外処理、よくある問題を扱います。

主な機能

  1. 01C# と JavaScript の型付き相互運用
  2. 02生メッセージの送受信
  3. 03ソース生成 JSON シリアル化の指針
  4. 04トリミングと NativeAOT の注意点
  5. 05設定と実行時の問題の対処

活用シーン

  1. 01JavaScript から C# への呼び出し失敗の調査
  2. 02型付き相互運用と生メッセージの選択
  3. 03トリミング対応の相互運用コードの準備

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/davidortinau/maui-skills --skill maui-hybridwebview

インストール後、Claude Code で/maui-hybridwebviewを入力して読み込まれたか確認します。

同梱ファイルreferences/hybridwebview-api.md

詳細

.NET MAUI の HybridWebView

HybridWebView は、.NET MAUI アプリ内で HTML/JS/CSS コンテンツをホストし、C#↔JS 間の双方向通信を可能にします。汎用ブラウザーコントロールではありません。アプリに同梱するローカルの Web コンテンツ向けに設計されています。

よくある注意点

問題対処方法
画面が白紙になるWeb アセットが Resources/Raw/wwwroot にないか、DefaultFile が設定されていません
JS 相互運用がエラーなく失敗するHTML に <script src="_hwv/HybridWebView.js"></script> がありません
InvokeJavaScriptAsync が null を返す戻り値の型に、JsonSerializerContext 内の [JsonSerializable] 属性がありません
JS → C# の呼び出しが機能しないJS から C# メソッドを呼び出す前に SetInvokeJavaScriptTarget が呼び出されていません
トリミングによりシリアル化でクラッシュするソース生成された JsonSerializerContext を使用していません

⚠️ ブリッジスクリプトは必須です

HTML ページには、アプリのスクリプトより前にブリッジスクリプトを含める必要があります。


<script src="_hwv/HybridWebView.js"></script>
<script src="scripts/app.js"></script>


<script src="scripts/app.js"></script>
<script src="_hwv/HybridWebView.js"></script>

JSON シリアル化 — すべての型を登録する必要があります

InvokeJavaScriptAsync で使用するすべての引数の型および戻り値の型に、[JsonSerializable] エントリが必要です。

// ✅ Correct — all interop types registered
[JsonSerializable(typeof(int))]
[JsonSerializable(typeof(string))]
[JsonSerializable(typeof(Person))]
internal partial class MyJsonContext : JsonSerializerContext { }

// ❌ Wrong — adding a new type to interop without registering it
// This causes silent null returns or runtime exceptions

ルール:相互運用の対象に新しい型を追加するときは、コンテキストに [JsonSerializable(typeof(T))] 属性を必ず追加してください。これを忘れることが、原因の分かりにくい相互運用の失敗の最大の原因です。

SetInvokeJavaScriptTarget — 呼び出すタイミングが重要です

// ✅ Set target BEFORE the web page loads and JS calls C#
myHybridWebView.SetInvokeJavaScriptTarget(new MyJsBridge());

// ❌ Setting it after JS already tried to call — calls are lost

⚠️ SetInvokeJavaScriptTarget は遅延して呼び出すのではなく、ページの構築時または OnAppearing で呼び出してください。

例外処理(.NET 9 以降)

InvokeJavaScriptAsync の実行中にスローされた JS 例外は .NET に転送されます。相互運用の呼び出しは必ずラップしてください。

// ✅ Catches JS errors
try
{
    var result = await myHybridWebView.InvokeJavaScriptAsync<string>(
        "riskyFunction", MyJsonContext.Default.String);
}
catch (Exception ex)
{
    Debug.WriteLine($"JS error: {ex.Message}");
}

// ❌ Unhandled JS exception crashes the interop pipeline
var result = await myHybridWebView.InvokeJavaScriptAsync<string>(
    "riskyFunction", MyJsonContext.Default.String);

トリミング/NativeAOT の注意点

MAUI プロジェクトでは、トリミングはデフォルトで無効です。有効にする場合:

  • ⚠️ ソース生成された JsonSerializerContext を必ず使用してください(リフレクションベースのシリアル化は使用しないでください)
  • ⚠️ JsonSerializerIsReflectionEnabledByDefault を false に設定してください
  • トリミング設定にかかわらず、上記のように JsonSerializerContext を使用することを推奨します
<PropertyGroup>
  <PublishTrimmed>true</PublishTrimmed>
  <JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault>
</PropertyGroup>

選択の目安 — 型付き相互運用と生メッセージ

要件使用するもの
型安全性のある構造化データのやり取りJsonSerializerContext を使用した InvokeJavaScriptAsync / InvokeDotNet
単純な文字列ペイロード、応答不要の送信SendRawMessage / RawMessageReceived
戻り値を取得しながら JS から C# を呼び出すInvokeDotNet(事前にターゲットを設定する必要があります)
呼び出す JS 関数が複数ある型付き相互運用 — 関数ごとに InvokeJavaScriptAsync を呼び出す

簡易チェックリスト

  • Web コンテンツが Resources/Raw/wwwroot にある
  • index.html に <script src="_hwv/HybridWebView.js"></script> がアプリのスクリプトより前に含まれている
  • DefaultFile が設定されている(またはデフォルトの index.html が使用されている)
  • すべての相互運用の型に、JsonSerializerContext 内の [JsonSerializable] エントリがある
  • JS から C# メソッドを呼び出す前に SetInvokeJavaScriptTarget が呼び出されている
  • InvokeJavaScriptAsync の呼び出しが try/catch でラップされている(.NET 9 以降)
  • トリミングが有効な場合:ソース生成による JSON シリアル化が設定されている

コメント