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 · 53 comments
Labels
area-blazor Includes: Blazor, Razor Components Docs This issue tracks updating documentation feature-trimming
Milestone

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!

@mguinness
Copy link

mguinness commented Jan 4, 2024

Thanks for the suggestion, I changed the assembly name but it made no difference. I did look at that assembly in the wwwroot\_framework folder and noticed that the constructor was public KeyValuePair(TKey P_0, TValue P_1) instead of public KeyValuePair(TKey key, TValue value) so that might be causing the issue.

@vitek-karas
Copy link
Member

Can you try adding:

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

(This is just to validate the assumptions... real fix would be something more complicated I guess)

@mguinness
Copy link

mguinness commented Jan 5, 2024

Yes, added that to PropertyGroup section in NullParameterNames.Client.csproj of the repro and the exception disappeared.

Confusing as setting <PublishTrimmed>false</PublishTrimmed> didn't achieve the same result - might be worth mentioning in Trimming options documentation.

Also see issue Expose the Linker's KeepMetadata parameter.

@vitek-karas
Copy link
Member

I agree that we should fix dotnet/runtime#81979.

@javiercn
Copy link
Member

@vitek-karas what's the impact in terms of size that you expect from using something like <_ExtraTrimmerArgs>--keep-metadata parametername</_ExtraTrimmerArgs>.

@javiercn javiercn added Docs This issue tracks updating documentation and removed bug This issue describes a behavior which is not expected - a bug. labels Jan 11, 2024
@javiercn javiercn modified the milestones: 8.0.x, Backlog Jan 11, 2024
@ghost
Copy link

ghost commented Jan 11, 2024

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

@javiercn
Copy link
Member

Given where we are, I think the best course of action is to go with dotnet/runtime#81979. In addition to that, we'll update the documentation to recommend using types from your app with JS interop as those will be preserved.

@javiercn
Copy link
Member

@guardrex can you add a note to the docs here to "refrain from using complex framework types like KeyValuePair, etc, when performing JS interop as those types might be trimmed by default. Create your own custom types instead.

@Bellarmine-Head
Copy link

Bellarmine-Head commented Jan 12, 2024

@guardrex can you add a note to the docs here to "refrain from using complex framework types like KeyValuePair, etc, when performing JS interop as those types might be trimmed by default. Create your own custom types instead.

@javiercn @guardrex

when performing JS interop - also when server <--> client serialization (by the framework) of shared models is concerned.

I had a property in a model in the Shared project that was typed as KeyValuePair<string, string>[] that caused (after migration to .NET 8, and only on the published website) the "ConstructorContainsNullParameterNames" error.

Easily solved by replacing with my own:

    // Used instead of KeyValuePair<string, string> in published .NET 8 apps because of this issue:-
    // https://github.com/dotnet/aspnetcore/issues/52947
    //
    public sealed class StringKeyValuePair
    {
        [SetsRequiredMembers]
        public StringKeyValuePair(string key, string value)
        {
            Key = key;
            Value = value;
        }

        public required string Key { get; init; }
        public required string Value { get; init; }
    }

@guardrex
Copy link
Contributor

... or if VS is correct for a primary ctor version ...

[method: SetsRequiredMembers]
public sealed class StringKeyValuePair(string key, string value)
{
    public required string Key { get; init; } = key;
    public required string Value { get; init; } = value;
}

... but I've rejected showing an example because whatever we'd show would be quite arbitrary.

@javiercn javiercn removed this from 8.0.x in Servicing Jan 18, 2024
@zawarq
Copy link

zawarq commented Feb 6, 2024

I am facing a similar issue. I have the following code in a Blazor 8 app that works fine on local, but on Azure I get an error:

Code:

public async Task OnImageChanged(CellEditContext<WeblogImage> context, FileChangedEventArgs e)
{
    IFileEntry fileEntry = e.Files.FirstOrDefault();
    if (fileEntry != null)
    {
        using (var stream = new MemoryStream())
        {
            await fileEntry.WriteToStreamAsync(stream);
            stream.Seek(0, SeekOrigin.Begin);
            context.CellValue = stream.ToArray();
        }
    }
}

Error:

image

Note that I am using Blazorise DataGrid and FileEdit components

@Sean4572435243
Copy link

Sean4572435243 commented Feb 9, 2024

There's some whacky related behavior here that generates this KeyValuePair exception:
dotnet/runtime#98180 (comment)
so the following won't work for me because I'm not even trying to use KeyValuePair or serializing

@guardrex can you add a note to the docs here to "refrain from using complex framework types like KeyValuePair, etc, when performing JS interop as those types might be trimmed by default. Create your own custom types instead.

@Sean4572435243
Copy link

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

This didn't work for me

@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

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 (thumbs up/down for those that agree/disagree).

@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?

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
Projects
None yet
Development

No branches or pull requests