Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A published blazor wasm app throws a serialization error "Unhandled exception rendering component: ConstructorContainsNullParameterNames" #52947

Open
1 task done
Stamo-Gochev opened this issue Nov 15, 2023 · 69 comments
Labels
area-blazor Includes: Blazor, Razor Components Docs This issue tracks updating documentation feature-trimming triaged

Comments

@Stamo-Gochev
Copy link

Stamo-Gochev commented Nov 15, 2023

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

An error is thrown when making a JS interop call in a published blazor wasm app that should serialize a KeyValuePair value.

This seems to be related to trimming as running this with things like dotnet run --configuration Release works as expected, but publishing the app starts the trimmer by default.

In addition, using an anonymous type instead of KeyValuePair works without any errors.

Note

I tried to disable the trimming, but the error is still present. Any suggestions on how to do that will be helpful - this might turn out to be another issue though.

blazor-issue-wasm-serialization

Expected Behavior

No error is thrown.

Steps To Reproduce

  1. Clone https://github.com/Stamo-Gochev/blazor-issue-wasm-serialization
  2. Change directory to https://github.com/Stamo-Gochev/blazor-issue-wasm-serialization/tree/master/BlazorissueWasmSerialization/BlazorissueWasmSerialization
  3. Run dotnet publish --configuration Release
  4. Go to BlazorissueWasmSerialization/BlazorissueWasmSerialization/bin/Release/net8.0/publish
  5. Run dotnet BlazorissueWasmSerialization.dll
  6. Click the "Show issue button"

Exceptions (if any)

Exception
blazor.web.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: 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.Metadata.DefaultJsonTypeInfoResolver.PopulateParameterInfoValues(JsonTypeInfo )
   at System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver.CreateTypeInfoCore(Type , JsonConverter , JsonSerializerOptions )
   at System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver.CreateJsonTypeInfo(Type , JsonSerializerOptions )
   at System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver.GetTypeInfo(Type , JsonSerializerOptions )
   at System.Text.Json.JsonSerializerOptions.GetTypeInfoNoCaching(Type )
   at System.Text.Json.JsonSerializerOptions.CachingContext.CreateCacheEntry(Type type, CachingContext context)
--- End of stack trace from previous location ---
   at System.Text.Json.JsonSerializerOptions.CachingContext.CacheEntry.GetResult()
   at System.Text.Json.JsonSerializerOptions.CachingContext.GetOrAddTypeInfo(Type , Boolean )
   at System.Text.Json.JsonSerializerOptions.GetTypeInfoInternal(Type , Boolean , Nullable`1 , Boolean , Boolean )
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo.Configure()
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo.<EnsureConfigured>g__ConfigureSynchronized|172_0()
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo.EnsureConfigured()
   at System.Text.Json.JsonSerializerOptions.GetTypeInfoInternal(Type , Boolean , Nullable`1 , Boolean , Boolean )
   at System.Text.Json.WriteStackFrame.InitializePolymorphicReEntry(Type , JsonSerializerOptions )
   at System.Text.Json.Serialization.JsonConverter.ResolvePolymorphicConverter(Object , JsonTypeInfo , JsonSerializerOptions , WriteStack& )
   at System.Text.Json.Serialization.JsonConverter`1[[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].TryWrite(Utf8JsonWriter , Object& , JsonSerializerOptions , WriteStack& )
   at System.Text.Json.Serialization.Converters.DictionaryOfTKeyTValueConverter`3[[System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].OnWriteResume(Utf8JsonWriter , Dictionary`2 , JsonSerializerOptions , WriteStack& )
   at System.Text.Json.Serialization.JsonDictionaryConverter`3[[System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].OnTryWrite(Utf8JsonWriter , Dictionary`2 , JsonSerializerOptions , WriteStack& )
   at System.Text.Json.Serialization.JsonConverter`1[[System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].TryWrite(Utf8JsonWriter , Dictionary`2& , JsonSerializerOptions , WriteStack& )
   at System.Text.Json.Serialization.JsonConverter`1[[System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].TryWriteAsObject(Utf8JsonWriter , Object , JsonSerializerOptions , WriteStack& )
   at System.Text.Json.Serialization.JsonConverter`1[[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].TryWrite(Utf8JsonWriter , Object& , JsonSerializerOptions , WriteStack& )
   at System.Text.Json.Serialization.Converters.ArrayConverter`2[[System.Object[], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].OnWriteResume(Utf8JsonWriter , Object[] , JsonSerializerOptions , WriteStack& )
   at System.Text.Json.Serialization.JsonCollectionConverter`2[[System.Object[], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].OnTryWrite(Utf8JsonWriter , Object[] , JsonSerializerOptions , WriteStack& )
   at System.Text.Json.Serialization.JsonConverter`1[[System.Object[], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].TryWrite(Utf8JsonWriter , Object[]& , JsonSerializerOptions , WriteStack& )
   at System.Text.Json.Serialization.JsonConverter`1[[System.Object[], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].WriteCore(Utf8JsonWriter , Object[]& , JsonSerializerOptions , WriteStack& )
   Exception_EndOfInnerExceptionStack
   at System.Text.Json.ThrowHelper.ThrowNotSupportedException(WriteStack& , NotSupportedException )
   at System.Text.Json.Serialization.JsonConverter`1[[System.Object[], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].WriteCore(Utf8JsonWriter , Object[]& , JsonSerializerOptions , WriteStack& )
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1[[System.Object[], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Serialize(Utf8JsonWriter , Object[]& , Object )
   at System.Text.Json.JsonSerializer.WriteString[Object[]](Object[]& , JsonTypeInfo`1 )
   at System.Text.Json.JsonSerializer.Serialize[Object[]](Object[] , JsonSerializerOptions )
   at Microsoft.JSInterop.JSRuntime.InvokeAsync[IJSVoidResult](Int64 , String , CancellationToken , Object[] )
   at Microsoft.JSInterop.JSRuntime.<InvokeAsync>d__16`1[[Microsoft.JSInterop.Infrastructure.IJSVoidResult, Microsoft.JSInterop, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].MoveNext()
   at Microsoft.JSInterop.JSRuntimeExtensions.InvokeVoidAsync(IJSRuntime , String , Object[] )
   at BlazorissueWasmSerialization.Client.Pages.Home.OnButtonShowIssueClick()
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task , ComponentState )

.NET Version

8.0.100

Anything else?

No response

@Stamo-Gochev Stamo-Gochev changed the title A published blazor wasm app throws a serialization error A published blazor wasm app throws a serialization error "Unhandled exception rendering component: ConstructorContainsNullParameterNames" Nov 15, 2023
@MackinnonBuck MackinnonBuck added this to the 8.0.x milestone Nov 15, 2023
@hexpoint
Copy link

I'm getting the identical exception, also in a published WASM app serializing a KeyValue pair. Error does not happen locally. In my case this is the Telerik blazor grid serializing or deserializing a KeyValue pair under the hood that is related to a default date filter in the grid. As a result this error appears on any grid that has a filterable date column.

@mkArtakMSFT mkArtakMSFT added bug This issue describes a behavior which is not expected - a bug. and removed investigate labels Nov 20, 2023
@javiercn
Copy link
Member

@Stamo-Gochev has this ever worked in a previous version of Blazor?

What I suspect is happening is that the KeyValuePair is being linked out. That's because the constructor and other elements are not being preserved. It works with an anonymous type because that type is created within the app assembly and Blazor doesn't serialize that.

If the members are used elsewhere in the app, the issue will go away, but seems that they are only being used during serialization. You can use https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trimming-options?pivots=dotnet-8-0#root-descriptors and https://github.com/dotnet/runtime/blob/main/docs/tools/illink/data-formats.md#descriptor-format to teach the linker not to strip away members from the type.

If you are still running into issues after taking those steps, let us know, it might be a different linker issue.

@taylorchasewhite
Copy link

@javiercn I have an application that began exhibiting this problem upon upgrading to .NET 8. I didn’t do too much research as I figured you all would hash this bug out, but if you’re under the impression this is not a new issue/not planning to be addressed soon I can also do more digging.

@javiercn javiercn removed this from the 8.0.x milestone Nov 23, 2023
@ghost
Copy link

ghost commented Nov 23, 2023

Hi @Stamo-Gochev. We have added the "Needs: Author Feedback" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

@javiercn
Copy link
Member

@taylorchasewhite If the issue happens at the linking stage, there are two possibilities:

  • The type is not being preserved; this requires an individual case analysis to determine whether it's by design or whether there is an issue with any of our annotations.
  • The type is being correctly told to be preserved, but despite that, there are some issues. In that case, it can be a bug in the linker, but with the info collected we can point that out to the linker folks and they can further investigate.

In most situations, the member is simply not being preserved, and that matters most when you are using types from the framework, since gestures that you might expect will result in them being preserved (like being passed to a JS interop call) won't actually do so.

In those situations, the descriptor file is the way to go.

@SaifAqqad
Copy link

has this ever worked in a previous version of Blazor?

Yes it has, I tested it on the same exact project just with different targets, on .NET 7 it works fine, but on .NET 8 an exception occurs ☹️

out.mp4

here's the project repo: https://github.com/SaifAqqad/blazor-bug-test

Imo even if this is the intended behavior of the trimmer, there should be a built-in exclusion of certain types (serialization, etc) for wasm projects

@ghost
Copy link

ghost commented Nov 27, 2023

This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment. If it is closed, feel free to comment when you are able to provide the additional information and we will re-investigate.

See our Issue Management Policies for more information.

@Stamo-Gochev
Copy link
Author

Stamo-Gochev commented Nov 28, 2023

@javiercn

@Stamo-Gochev has this ever worked in a previous version of Blazor?

What I suspect is happening is that the KeyValuePair is being linked out. That's because the constructor and other elements are not being preserved. It works with an anonymous type because that type is created within the app assembly and Blazor doesn't serialize that.

If the members are used elsewhere in the app, the issue will go away, but seems that they are only being used during serialization. You can use https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trimming-options?pivots=dotnet-8-0#root-descriptors and https://github.com/dotnet/runtime/blob/main/docs/tools/illink/data-formats.md#descriptor-format to teach the linker not to strip away members from the type.

If you are still running into issues after taking those steps, let us know, it might be a different linker issue.

Yes, it works with previous versions - .NET 6.0 and .NET 7.0.

The Home.razor page and the JS file can be pasted in a standalone .NET 6.0 and .NET 7.0 projects for comparison.

Regarding the suggestions:

If the members are used elsewhere in the app, the issue will go away, but seems that they are only being used during serialization. You can use https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trimming-options?pivots=dotnet-8-0#root-descriptors and https://github.com/dotnet/runtime/blob/main/docs/tools/illink/data-formats.md#descriptor-format to teach the linker not to strip away members from the type.

this is possible, but the change in the behavior looks more or less like a regression to me - it is not clear why KeyValuePair was serializeable before and not now.

As .NET 8.0 is a major release, I can accept a public issue that states that KeyValuePair is no longer serializable when linking is enabled, but I couldn't find such an issue, which is why it seems like a regression to me.

@javiercn
Copy link
Member

This seems to be a regression in the linker in fact.

@ghost ghost added the untriaged label Nov 29, 2023
@javiercn javiercn transferred this issue from dotnet/aspnetcore Nov 29, 2023
@ghost
Copy link

ghost commented Nov 29, 2023

Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis
See info in area-owners.md if you want to be subscribed.

Issue Details

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

An error is thrown when making a JS interop call in a published blazor wasm app that should serialize a KeyValuePair value.

This seems to be related to trimming as running this with things like dotnet run --configuration Release works as expected, but publishing the app starts the trimmer by default.

In addition, using an anonymous type instead of KeyValuePair works without any errors.

[!NOTE]
I tried to disable the trimming, but the error is still present. Any suggestions on how to do that will be helpful - this might turn out to be another issue though.

blazor-issue-wasm-serialization

Expected Behavior

No error is thrown.

Steps To Reproduce

  1. Clone https://github.com/Stamo-Gochev/blazor-issue-wasm-serialization
  2. Change directory to https://github.com/Stamo-Gochev/blazor-issue-wasm-serialization/tree/master/BlazorissueWasmSerialization/BlazorissueWasmSerialization
  3. Run dotnet publish --configuration Release
  4. Go to BlazorissueWasmSerialization/BlazorissueWasmSerialization/bin/Release/net8.0/publish
  5. Run dotnet BlazorissueWasmSerialization.dll
  6. Click the "Show issue button"

Exceptions (if any)

Exception
blazor.web.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: 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.Metadata.DefaultJsonTypeInfoResolver.PopulateParameterInfoValues(JsonTypeInfo )
   at System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver.CreateTypeInfoCore(Type , JsonConverter , JsonSerializerOptions )
   at System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver.CreateJsonTypeInfo(Type , JsonSerializerOptions )
   at System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver.GetTypeInfo(Type , JsonSerializerOptions )
   at System.Text.Json.JsonSerializerOptions.GetTypeInfoNoCaching(Type )
   at System.Text.Json.JsonSerializerOptions.CachingContext.CreateCacheEntry(Type type, CachingContext context)
--- End of stack trace from previous location ---
   at System.Text.Json.JsonSerializerOptions.CachingContext.CacheEntry.GetResult()
   at System.Text.Json.JsonSerializerOptions.CachingContext.GetOrAddTypeInfo(Type , Boolean )
   at System.Text.Json.JsonSerializerOptions.GetTypeInfoInternal(Type , Boolean , Nullable`1 , Boolean , Boolean )
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo.Configure()
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo.<EnsureConfigured>g__ConfigureSynchronized|172_0()
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo.EnsureConfigured()
   at System.Text.Json.JsonSerializerOptions.GetTypeInfoInternal(Type , Boolean , Nullable`1 , Boolean , Boolean )
   at System.Text.Json.WriteStackFrame.InitializePolymorphicReEntry(Type , JsonSerializerOptions )
   at System.Text.Json.Serialization.JsonConverter.ResolvePolymorphicConverter(Object , JsonTypeInfo , JsonSerializerOptions , WriteStack& )
   at System.Text.Json.Serialization.JsonConverter`1[[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].TryWrite(Utf8JsonWriter , Object& , JsonSerializerOptions , WriteStack& )
   at System.Text.Json.Serialization.Converters.DictionaryOfTKeyTValueConverter`3[[System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].OnWriteResume(Utf8JsonWriter , Dictionary`2 , JsonSerializerOptions , WriteStack& )
   at System.Text.Json.Serialization.JsonDictionaryConverter`3[[System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].OnTryWrite(Utf8JsonWriter , Dictionary`2 , JsonSerializerOptions , WriteStack& )
   at System.Text.Json.Serialization.JsonConverter`1[[System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].TryWrite(Utf8JsonWriter , Dictionary`2& , JsonSerializerOptions , WriteStack& )
   at System.Text.Json.Serialization.JsonConverter`1[[System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].TryWriteAsObject(Utf8JsonWriter , Object , JsonSerializerOptions , WriteStack& )
   at System.Text.Json.Serialization.JsonConverter`1[[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].TryWrite(Utf8JsonWriter , Object& , JsonSerializerOptions , WriteStack& )
   at System.Text.Json.Serialization.Converters.ArrayConverter`2[[System.Object[], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].OnWriteResume(Utf8JsonWriter , Object[] , JsonSerializerOptions , WriteStack& )
   at System.Text.Json.Serialization.JsonCollectionConverter`2[[System.Object[], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].OnTryWrite(Utf8JsonWriter , Object[] , JsonSerializerOptions , WriteStack& )
   at System.Text.Json.Serialization.JsonConverter`1[[System.Object[], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].TryWrite(Utf8JsonWriter , Object[]& , JsonSerializerOptions , WriteStack& )
   at System.Text.Json.Serialization.JsonConverter`1[[System.Object[], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].WriteCore(Utf8JsonWriter , Object[]& , JsonSerializerOptions , WriteStack& )
   Exception_EndOfInnerExceptionStack
   at System.Text.Json.ThrowHelper.ThrowNotSupportedException(WriteStack& , NotSupportedException )
   at System.Text.Json.Serialization.JsonConverter`1[[System.Object[], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].WriteCore(Utf8JsonWriter , Object[]& , JsonSerializerOptions , WriteStack& )
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1[[System.Object[], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Serialize(Utf8JsonWriter , Object[]& , Object )
   at System.Text.Json.JsonSerializer.WriteString[Object[]](Object[]& , JsonTypeInfo`1 )
   at System.Text.Json.JsonSerializer.Serialize[Object[]](Object[] , JsonSerializerOptions )
   at Microsoft.JSInterop.JSRuntime.InvokeAsync[IJSVoidResult](Int64 , String , CancellationToken , Object[] )
   at Microsoft.JSInterop.JSRuntime.<InvokeAsync>d__16`1[[Microsoft.JSInterop.Infrastructure.IJSVoidResult, Microsoft.JSInterop, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].MoveNext()
   at Microsoft.JSInterop.JSRuntimeExtensions.InvokeVoidAsync(IJSRuntime , String , Object[] )
   at BlazorissueWasmSerialization.Client.Pages.Home.OnButtonShowIssueClick()
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task , ComponentState )

.NET Version

8.0.100

Anything else?

No response

Author: Stamo-Gochev
Assignees: javiercn
Labels:

bug, area-System.Text.Json

Milestone: -

@eiriktsarpalis
Copy link
Member

Duplicate of dotnet/runtime#74141, dotnet/runtime#94806 and dotnet/runtime#81709.

The reason this error shows up on serialization traces as well as deserialization is because of this breaking change. I would recommend either switching to the source generator or applying a DynamicDependency attribute on the affected types (see passwordless-lib/fido2-net-lib@1fbfb25 for an example).

@ghost ghost removed the untriaged label Nov 29, 2023
@SaifAqqad
Copy link

The reason this error shows up on serialization traces as well as deserialization is because of this breaking change.

Does this mean that system.text.json doesn't support de/serializing KeyValuePair? Since this is what this issue is about.

I still think this should be looked into more, especially for built-in types like KeyValuePair.

I would recommend either switching to the source generator or applying a DynamicDependency attribute on the affected types

How is it acceptable that serializing such simple types would need this special handling, it sounds like a nightmare tbh.

Throwing attributes around as a fix for such things is not acceptable imo.

@eiriktsarpalis
Copy link
Member

The reason this error shows up on serialization traces as well as deserialization is because of this breaking change.

Does this mean that system.text.json doesn't support de/serializing KeyValuePair? Since this is what this issue is about.

No. It means that using reflection-based serialization in trimmed applications is not reliable and can result in multiple failures like the one reported here. This is a problem inherent to using dynamic member access via reflection in trimmed applications and there's not much that can be done about it other than adding manual annotations to work around the issues that pop up. Our recommendation is to switch to the source generator if you must use a trimmed app, see this article for more details.

@hoangdovan
Copy link

@eiriktsarpalis I have same problem after upgrade to .Net 8. As you explained, we need to handle this problem by changing our code, and .Net will not support anymore like previous .Net 7 version?

@hoangdovan
Copy link

@SaifAqqad @Stamo-Gochev any work around for this matter? I have same problem! Thanks!

@eiriktsarpalis
Copy link
Member

@hoangdovan The fundamental issue is that trimming and reflection are fundamentally incompatible. There's nothing that we can do about this in the System.Text.Json layer other than recommend switching to the source generator which is trimming-safe.

@Stamo-Gochev
Copy link
Author

hoangdovan

@SaifAqqad @Stamo-Gochev any work around for this matter? I have same problem! Thanks!

It still requires changing your code though and whether you need to serialize a KeyValuePair in several places or if you can replace it with another type.

One option is to create a custom serializer, another one is to map it to something like:

someKeyValuePair.Select(x => new { key = x.Key, value = x.Value })...

which follows the structure of a JSON-serialized KeyValuePair.

@hoangdovan
Copy link

@Stamo-Gochev Thank you. In my case, I create a custom class replace for .Net KeyPairValue to fix this error!

@Sean4572435243
Copy link

here's another example of strange AOT behavior eliciting this exception, once again by LINQ and 'not' directly using serialization or KeyValuePair
dotnet/runtime#98180 (comment)

@Sean4572435243
Copy link

No relief from 8.0.3

@Panzerfury
Copy link

Panzerfury commented Mar 27, 2024

Having something similar i think.
image

Working fine locally. But as soon as it's published through azure, to an IIS server it breaks.

@Sean4572435243
Copy link

No relief from VS 17.9.5

@Sean4572435243
Copy link

No relief from 8.0.4 or VS 17.9.6

@davidlsharp1
Copy link

Is there any indication they are looking at this yet?

@Sean4572435243
Copy link

No relief from 17.9.7 or 8.0.5

Is there any indication they are looking at this yet?

Still open. They usually get around to open items, particularly with so many different people reporting the issue.

@mguinness
Copy link

mguinness commented May 15, 2024

Is there any indication they are looking at this yet?

The proposed solution will be tracked in dotnet/runtime#81979 and that is now high priority in dotnet/projects/135.

No relief from 17.9.7 or 8.0.5

I don't think it's useful to create a new post for each version, but updating a single post would be. I think most people subscribing to this issue want to get alerts when something tangible occurred.

@Sean4572435243
Copy link

I don't think it's useful to create a new post for each version, but updating a single post would be. I think most people subscribing to this issue want to get alerts when something tangible occurred (thumbs up/down for those that agree/disagree).

Given the infrequency of these updates, and the fact that there may be some latency for MS to update this issue, I felt that people interested in this problem would want to know whether a release corrects this problem or not, so they can avoid updating each time a new release is available in pursuit of hopefully this issue being fixed. Far better to get an occasional email than to spend hours updating to a version that doesn't help, no?

@mguinness
Copy link

mguinness commented May 16, 2024

I felt that people interested in this problem would want to know whether a release corrects this problem or not

Then create a new post when that actually occurs?

@eiriktsarpalis
Copy link
Member

Once a solution has been implemented, there will be an update posted to this issue as well.

@Sean4572435243
Copy link

Once a solution has been implemented, there will be an update posted to this issue as well.

Ok, thanks for the assurance Eirik. I'll just wait for the update then. Apologies to everyone for the noise (it was well-intended)

@Bananas-Are-Yellow
Copy link

I have the same problem, only my project is a Bolero project written in F#. As far as I know, the source generator approach is not available to F# projects, only C# projects, so that doesn't help me.

I'm not using KeyValuePair but in my case the problem occurs using the F# tuple, which can be created in JS as: { Item1: value1, Item2: value2, ... }. This is a natural way to return a few values from JS back to F#. This works fine until I publish the project and then trimming causes the problem.

The workaround is to return a JS object with fields that match an F# anonymous type. So in JS, you can return { Name: name, Age: age, Height: height } and then deserialize this as (result: {| Name: string; Age: int; Height: int |}) and then access result.Name, result.Age, and result.Height. This works fine.

@Sean4572435243
Copy link

From what I can see in this related issue dotnet/runtime#81979 (comment), it looks like they've solved the problem, but not sure which coming release will contain the fix.

@mguinness
Copy link

mguinness commented Jun 2, 2024

I assume it will be part of 9.0-preview5 but I don't know what the criteria is for backporting fixes to 8.0

@Sean4572435243
Copy link

It's fixed! I updated to 8.0.6 aspnetcore and no more issues. Thank you Microsoft!

@Sean4572435243
Copy link

If you've been paring down the deployed wasm files, be sure to include the _framework/system.io.compression.wasm library, or you'll still get this KeyPair error.

@mguinness
Copy link

It's fixed! I updated to 8.0.6 aspnetcore and no more issues.

I don't see how PR dotnet/runtime#102850 committed on May 30 was included in 8.0.6 which was released on May 28?

@Sean4572435243
Copy link

My KeyValuePair issue was related to LINQ, so possibly they fixed this related issue in a prior commit. Try 8.0.6, report back.

@desmondinho
Copy link

We're facing the same issue but with System.Tuple. I've never touched source generator before and maybe I am doing something wrong, but do I understand correctly that there is no way to implement it [source generation] if A<T> is the base class that sits somewhere within our architecture and tons of classes derive from it in different projects which means that we can't just annotate A<T> with concrete classes as we don't know them?

public abstract class A<T> where T : class
{
   public class B
   {
      [JsonInclude]
      private Tuple<T1, T2> _fieldName; 

      // Uses T inside
   }
}

@ghostinside
Copy link

8.0.6 still there

ConstructorContainsNullParameterNames, System.Collections.Generic.KeyValuePair2[System.String,System.Collections.Generic.IEnumerable1[System.String]]

@ghostinside
Copy link

source of exception:

Console.WriteLine(JsonSerializer.Serialize(response.Content.Headers));

@rblanca
Copy link

rblanca commented Jul 6, 2024

Yeap confirmed tuple is getting the same error only on WASM

@mguinness
Copy link

Current workaround is to set keep-metadata parametername on the linker, see #52947 (comment).

@thirstyape
Copy link

Why wait for a fix that might not make it into .NET 8 at all? Here's a laughably simple workaround if you turn off trimming.

Just replace KeyValuePair with KeyValuePairSerializer in your deserialization calls and then call .ToKeyValuePair or if you're in a list .Select(x => x.ToKeyValuePair).ToList(). Same idea can be done for the various Tuple<T> iterations.

using System.Text.Json.Serialization;

public class KeyValuePairSerializer<TKey, TValue>
{
	public KeyValuePairSerializer() { }

	public KeyValuePairSerializer(TKey key, TValue value)
	{
		Key = key;
		Value = value;
	}

	public TKey Key { get; set; }

	public TValue Value { get; set; }

	[JsonIgnore]
	public KeyValuePair<TKey, TValue> ToKeyValuePair => new(Key, Value);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-blazor Includes: Blazor, Razor Components Docs This issue tracks updating documentation feature-trimming triaged
Projects
None yet
Development

No branches or pull requests