如何修复Blazor WASM中System.Text.Json的SerializationNotSupportedParentType相关异常?
解决Blazor WASM PWA部署Azure时System.Text.Json 8.0.5与TelerikDatePicker的序列化异常问题
问题背景
基于.NET7开发Blazor WASM PWA时,为修复NU1903漏洞升级System.Text.Json到兼容.NET7的8.0.5版本,部署到Azure后出现运行时异常,堆栈信息显示SerializationNotSupportedParentType和ThrowNotSupportedException_ConstructorContainsNullParameterNames,本地开发无此问题。经排查:
- TelerikDatePicker通过反射序列化
KeyValuePair进行JS互操作 - .NET8+的WASM链接器默认会修剪仅通过反射引用的程序集(如
KeyValuePair所在程序集) - Azure使用了更高版本的.NET运行时(如v9.0),导致
System.Text.Json 8.0.5触发该运行时的回归问题 - 暂不想升级Telerik到修复该问题的v5.0.1版本(重大升级)
解决方案
1. 配置链接器强制保留KeyValuePair类型
在Blazor WASM项目根目录创建或修改BlazorWebAssemblyLinker.xml文件,添加规则避免KeyValuePair被链接器修剪:
<linker> <assembly fullname="System.Private.CoreLib"> <type fullname="System.Collections.Generic.KeyValuePair`2" preserve="all" /> </assembly> </linker>
若项目未自动识别该文件,手动在项目文件(.csproj)中添加引用:
<ItemGroup> <None Include="BlazorWebAssemblyLinker.xml" /> </ItemGroup>
2. 强制Azure使用.NET7运行时
通过Azure配置指定运行时版本,避免触发高版本运行时的回归问题:
- Azure门户操作:进入你的App Service → 配置 → 应用程序设置 → 添加新设置,键为
DOTNET_VERSION,值为7.0 - Azure CLI命令:
az webapp config appsettings set --name <你的应用名称> --resource-group <资源组名称> --settings DOTNET_VERSION=7.0
3. 自定义System.Text.Json转换器处理KeyValuePair序列化
编写自定义转换器替代默认的KeyValuePair序列化逻辑,绕开反射依赖问题:
using System.Text.Json; using System.Text.Json.Serialization; public class KeyValuePairConverter<TKey, TValue> : JsonConverter<KeyValuePair<TKey, TValue>> { public override KeyValuePair<TKey, TValue> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { using var doc = JsonDocument.ParseValue(ref reader); var root = doc.RootElement; var key = root.GetProperty("Key").Deserialize<TKey>(options); var value = root.GetProperty("Value").Deserialize<TValue>(options); return new KeyValuePair<TKey, TValue>(key, value); } public override void Write(Utf8JsonWriter writer, KeyValuePair<TKey, TValue> value, JsonSerializerOptions options) { writer.WriteStartObject(); writer.WritePropertyName("Key"); JsonSerializer.Serialize(writer, value.Key, options); writer.WritePropertyName("Value"); JsonSerializer.Serialize(writer, value.Value, options); writer.WriteEndObject(); } }
在Program.cs中注册转换器(根据Telerik实际使用的泛型类型添加对应转换器):
builder.Services.AddControllersWithViews() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new KeyValuePairConverter<object, object>()); // 若Telerik使用特定类型的KeyValuePair,比如<string, DateTime>,可添加对应转换器: // options.JsonSerializerOptions.Converters.Add(new KeyValuePairConverter<string, DateTime>()); });
内容的提问来源于stack exchange,提问作者Jesper Risager
相关产品推荐
相关产品推荐

