用途
HybridWebView 用于在 .NET MAUI 应用内承载 HTML/JS/CSS 内容,并提供 C# 与 JavaScript 之间的双向通信。资料明确指出:它不是通用浏览器控件,而是为随应用一起分发的本地 Web 内容而设计。
主要能力
- 在 MAUI 应用中托管本地 Web 资源(位于 Resources/Raw/wwwroot)。
- 双向 C#↔JS 通信,包括类型化的调用接口(InvokeJavaScriptAsync / InvokeDotNet)与原始消息方式(SendRawMessage / RawMessageReceived)。
- 通过 JsonSerializerContext 进行序列化,以支持类型安全的数据交换。
使用方式与关键要点
桥接脚本
HTML 页面必须在任何应用脚本之前引入桥接脚本:
<!-- ✅ 正确顺序 -->
<script src="_hwv/HybridWebView.js"></script>
<script src="scripts/app.js"></script>
<!-- ❌ 错误 — app.js 先于桥接脚本加载,interop 调用会静默失败 -->
<script src="scripts/app.js"></script>
<script src="_hwv/HybridWebView.js"></script>
JSON 序列化:每个类型都必须注册
InvokeJavaScriptAsync 中用到的每个参数类型与返回类型都必须有 [JsonSerializable] 条目:
// ✅ 正确 — 所有 interop 类型均已注册
[JsonSerializable(typeof(int))]
[JsonSerializable(typeof(string))]
[JsonSerializable(typeof(Person))]
internal partial class MyJsonContext : JsonSerializerContext { }
资料指出,当向 interop 表面新增类型时,必须添加对应的 [JsonSerializable(typeof(T))] 特性;遗忘这一点是 interop 神秘失败的首要原因。
SetInvokeJavaScriptTarget 的调用时机
// ✅ 在网页加载、JS 调用 C# 之前设置目标
myHybridWebView.SetInvokeJavaScriptTarget(new MyJsBridge());
应在页面构造期间或 OnAppearing 中调用,而非延迟调用,否则 JS 的调用会丢失。
异常处理(.NET 9+)
InvokeJavaScriptAsync 期间抛出的 JS 异常会转发到 .NET,因此应包裹调用:
try
{
var result = await myHybridWebView.InvokeJavaScriptAsync<string>(
"riskyFunction", MyJsonContext.Default.String);
}
catch (Exception ex)
{
Debug.WriteLine($"JS error: {ex.Message}");
}
裁剪 / NativeAOT 注意点
MAUI 项目默认禁用裁剪。若启用裁剪,必须使用源生成的 JsonSerializerContext,并将 JsonSerializerIsReflectionEnabledByDefault 设为 false:
<PropertyGroup>
<PublishTrimmed>true</PublishTrimmed>
<JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault>
</PropertyGroup>
资料建议无论裁剪设置如何,都使用上述 JsonSerializerContext 方式。
选型框架:类型化 Interop 还是原始消息
| 需求 | 使用方式 |
|---|---|
| 带类型安全的结构化数据交换 | InvokeJavaScriptAsync / InvokeDotNet,配合 JsonSerializerContext |
| 简单字符串载荷、即发即忘 | SendRawMessage / RawMessageReceived |
| 从 JS 调用 C# 并获取返回值 | InvokeDotNet(必须先设置目标) |
| 需要调用多个 JS 函数 | 类型化 interop — 每个函数一个 InvokeJavaScriptAsync |
常见问题排查
| 问题 | 修复 |
|---|---|
| 空白白屏 | Web 资源未放入 Resources/Raw/wwwroot,或未设置 DefaultFile |
| JS interop 静默失败 | HTML 中缺少 <script src="_hwv/HybridWebView.js"></script> |
| InvokeJavaScriptAsync 返回 null | JsonSerializerContext 中返回类型缺少 [JsonSerializable] 特性 |
| JS → C# 调用无反应 | JS 调用 C# 方法前未调用 SetInvokeJavaScriptTarget |
| 裁剪导致序列化崩溃 | 未使用源生成的 JsonSerializerContext |
快速检查清单
- Web 内容位于 Resources/Raw/wwwroot。
- index.html 在应用脚本之前包含 <script src="_hwv/HybridWebView.js"></script>。
- 已设置 DefaultFile(或默认为 index.html)。
- 每个 interop 类型在 JsonSerializerContext 中都有 [JsonSerializable] 条目。
- 在 JS 调用 C# 方法之前已调用 SetInvokeJavaScriptTarget。
- InvokeJavaScriptAsync 调用已包裹在 try/catch 中(.NET 9+)。
- 若启用裁剪:已配置源生成的 JSON 序列化。