Search code examples
c#azuregithubblazorblazor-webassembly

How do I fix SerializationNotSupportedParentType and ThrowNotSupportedException_ConstructorContainsNullParameterNames exception in System.Text.Json?


I ran into the following problem, which solution might help others, since I couldn't find any answer on Stack overflow.

I currently work on a C# Blazor Webassembly PWA. We publish and host it on windows Azure.

We started getting errors like these on our Github CI environment:

error NU1903: Warning As Error: Package 'System.Text.Json' 7.0.0 has a known high severity vulnerability, https://github.com/advisories/GHSA-hh2w-p6rv-4g7w

We where running on .Net 7 and where not quite ready yet to upgrade to .net 8, so I looked into it and found out that I could just upgrade System.Text.Json to v8.0.5 which was the lowest version where the security problem was fixed and the last version that could run on .Net 7 before requiring .Net 8.

We then ran into this runtime problem. (I only included the important parts of the stack trace):

Microsoft.AspNetCore.Components.Web.ErrorBoundary[0]
System.AggregateException: AggregateException_ctor_DefaultMessage (ConstructorContainsNullParameterNames, System.Collections.Generic.KeyValuePair`2[System.String,System.String] SerializationNotSupportedParentType, System.Object Path: $.)
---> System.NotSupportedException: ConstructorContainsNullParameterNames, System.Collections.Generic.KeyValuePair`2[System.String,System.String] SerializationNotSupportedParentType, System.Object Path: $.
---> System.NotSupportedException: ConstructorContainsNullParameterNames, System.Collections.Generic.KeyValuePair`2[System.String,System.String]
 at System.Text.Json.ThrowHelper.ThrowNotSupportedException_ConstructorContainsNullParameterNames(Type )
...
at System.Text.Json.Serialization.JsonConverter`1[[System.Object[], System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].WriteCore(Utf8JsonWriter , Object[]& , JsonSerializerOptions , WriteStack& )         
...
at Telerik.Blazor.Components.Common.DateInputs.DateInput`1.<OnAfterRenderAsync>d__186[[System.Nullable`1[[System.DateTime, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()

It turns out that the reason this happens is because the TelerikDatePicker we use is serializing KeyValuePairs with interop, so it works with the javascript part of the control.

We were using Telerik.UI.for.Blazor v4.4.0 and it seems like Telerik have fixed this issue in v5.0.1. This is however a major upgrade of the Telerik components with lots of breaking changes and since this whole thing started with security warnings when we wanted to create a release candidate, we didn't really want to upgrade to v5.0.1 yet, since that would delay everything.

It turns out that this problem isn't caused by Telerik at all, the problem can be reproduced without Telerik's components. They use reflection to find the values and types they serialize and that is the real problem.

Another strange thing we found was that we could not reproduce the error on our developer machines. It ONLY happened when we published the WASM App to Windows Azure.

To cut a long story short it turns out that the root cause of this error is a regression in .Net 8. They have made a breaking change in the linker, such that when trimming of assemblies is turned on, which it is by default when publishing WASM Aps to windows azure, assemblies that are only used by reflection, like the assembly that contains the KeyValuePair type are trimmed away, so the type can no longer be found on runtime.

Why is this a thing, when we run on .Net 7? The newest .Net run times are installed on Windows Azure .Net v9.0 in our case. Even though System.Text.Json v8.0.5 runs fine on .Net 7, it will use .Net 8 and .Net 9 runtime (where this regression is still present) if it is installed on the machine, since after .Net 3.5 versions of .Net replaces each other.

You can read more here: https://github.com/dotnet/aspnetcore/issues/52947


Solution

  • A workaround to fix this without changing anything else is to insert the following in your WebClient project file:

    <PropertyGroup>
        <_ExtraTrimmerArgs>--keep-metadata parametername</_ExtraTrimmerArgs>
    </PropertyGroup>
    

    The real issue should be fixed in https://github.com/dotnet/runtime/issues/81979