JeffreySu/WeiXinMPSDK · error · NotSupportedException
Native AOT 不支持未注册的 H5 场景类型:
Error message
Native AOT 不支持未注册的 H5 场景类型:{value.GetType().FullName}。请使用 H5_Info_IOS、H5_Info_Android 或 H5_Info_WAP。 What it means
SerializeCustomH5Info can only serialize the pre-registered H5 scene types (H5_Info_IOS, H5_Info_Android, H5_Info_WAP) via source-generated metadata. When reflection is disabled (Native AOT: JsonSerializer.IsReflectionEnabledByDefault == false) and a different IH5_Info implementation is passed, a NotSupportedException is thrown because the custom type has no generated JSON metadata.
Solutions
- Switch to the built-in H5_Info_IOS, H5_Info_Android, or H5_Info_WAP types that match your scenario.
- If a custom type is truly needed, add it to the JsonSerializerContext ([JsonSerializable]) and extend serialization accordingly.
- Test under AOT publish settings before deploying; reflection-only paths fail only there.
Example fix
// before
IH5_Info h5 = new MyCustomH5Info(); // custom class
// after
IH5_Info h5 = new H5_Info_WAP { Type = "WAP", WapUrl = "https://example.com", WapName = "Example" }; Defensive patterns
Strategy: type-guard
Validate before calling
// C# bool isAotSafeH5(IH5_Info h5) => h5 is H5_Info_IOS or H5_Info_Android or H5_Info_WAP;
Type guard
bool IsBuiltInH5Info(IH5_Info v) => v is H5_Info_IOS or H5_Info_Android or H5_Info_WAP;
Try / catch
try { json = TenPayJsonSerializer.SerializeCustomH5Info(h5Info); }
catch (NotSupportedException ex) when (ex.Message.Contains("Native AOT")) { log.LogError("Replace {Type} with a built-in H5_Info_* type", h5Info.GetType().FullName); } Prevention
- Only use H5_Info_IOS / H5_Info_Android / H5_Info_WAP
- Run AOT publish builds in CI for payment flows
- Avoid subclassing IH5_Info unless you also register it in a JsonSerializerContext
When it happens
Trigger: Publishing with Native AOT (PublishAot=true) and calling the payment/H5 request path with a custom class implementing IH5_Info instead of one of the three supported built-in scene types.
Common situations: Developers write their own IH5_Info implementation to add a custom wap_url/app_id scene; it works in normal (reflection-enabled) builds but crashes after switching to AOT/trimmed deployment.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- 未生成类型 的 JSON 元数据。
- 不能为空。
- out_trade_no、transaction_id、sub_order_no 和 sub_order_id…
- out_trade_no 和 transaction_id 至少填写一个。
- data
AI-assisted analysis of JeffreySu/WeiXinMPSDK@be573f6f94 (2026-09-12).
Data as JSON: /api/errors/54c23a8685f8e17e.
Report an issue: GitHub.
Appendix: source
Thrown at src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPay/V3/Universal/Entities/Request/TenPayJsonSerializer.cs:73
internal static class TenPayJsonSerializer
{
internal static string Serialize<T>(T value)
{
var jsonTypeInfo = TenPayJsonSerializerContext.Default.GetTypeInfo(typeof(T));
if (jsonTypeInfo == null)
{
throw new NotSupportedException($"未生成类型 {typeof(T).FullName} 的 JSON 元数据。");
}
return JsonSerializer.Serialize(value, jsonTypeInfo);
}
internal static string SerializeCustomH5Info(IH5_Info value)
{
if (!JsonSerializer.IsReflectionEnabledByDefault)
{
throw new NotSupportedException(
$"Native AOT 不支持未注册的 H5 场景类型:{value.GetType().FullName}。" +
"请使用 H5_Info_IOS、H5_Info_Android 或 H5_Info_WAP。");
}
#pragma warning disable IL2026
#pragma warning disable IL3050
return JsonSerializer.Serialize(
new Dictionary<string, object> { ["h5_info"] = value },
new JsonSerializerOptions
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
});
#pragma warning restore IL3050
#pragma warning restore IL2026
}
}
internal sealed class StoreInfoJsonView on GitHub (pinned to be573f6f94)