Fix DynamicComponent serialization with interactive render modes by adding TypeJsonConverter #63817
+352
−0
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Analysis of DynamicComponent Serialization Issue
Understanding the problem: When
DynamicComponent
is used with interactive render modes in .NET 8, theType
parameter needs to be serialized to JSON, butSystem.Type
instances cannot be serialized by System.Text.Json by default.Plan
Implementation Complete ✅
Created TypeJsonConverter
A custom JsonConverter that:
{ "assembly": "AssemblyName", "type": "FullTypeName" }
ConcurrentDictionary<TypeKey, Type?>
to avoid repeated lookupsUnconditionalSuppressMessage
for trimming warningsIntegrated with JSRuntime
Hot Reload Support
Test Fix
Read_ThrowsJsonException_IfJsonIsNotStartObject
""""invalid""""
which producesinvalid
(not valid JSON)"invalid"
so the converter receives a valid JSON string token and can throw the expected error messageValidation
How This Fixes the Issue
Before:
DynamicComponent
with@rendermode
would fail with:After: The TypeJsonConverter automatically handles Type serialization/deserialization when JSRuntime needs to serialize component parameters, allowing DynamicComponent to work seamlessly with interactive render modes.
The solution is transparent to users - no code changes needed in their applications.
Original prompt
This section details on the original issue you should resolve
<issue_title>DynamicComponent Throws Run-Time Error on .NET 8</issue_title>
<issue_description>### Is there an existing issue for this?
Describe the bug
When using the standard DynamicComponent (introduced in .NET 6) and specifying an instance-based @rendermode attribute ie.
The component throws a run-time error related to serialization:
DynamicComponent expects a Type parameter which is of type System.RuntimeType - however in .NET 8 parameters must be serializable.
Expected Behavior
DynamicComponent is widely used in Blazor applications to construct razor components dynamically based on type information. I would expect DynamicComponent to render a component in exactly the same manner as it does in .NET 6 and .NET 7.
Steps To Reproduce
Please see repo: https://github.com/oqtane/OqtaneSSR which is based on the standard Blazor Web template in .NET 8 RC2. Set the appsettings.json Modules property to:
When you run the application, it will immediately throw a run-time error. This is caused by the line:
<DynamicComponent Type="@_type" @rendermode="RenderMode.InteractiveServer">
in OqtaneSSR\Components\Router\ModuleInstance2.razor
Exceptions (if any)
An unhandled exception occurred while processing the request.
NotSupportedException: Serialization and deserialization of 'System.RuntimeType' instances is not supported.
System.Text.Json.Serialization.Converters.UnsupportedTypeConverter.Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
.NET Version
8.0.0-rc.2.23480.2
Anything else?
A workaround to this problem is to create a custom component which accepts a TypeName (rather than a Type) and use RenderFragment to render it:
Note that this workaround does not support Parameters - which is another problem with DynamicComponent as it uses a Dictionary for parameters.</issue_description>
<agent_instructions>For this case, we should have a custom JsonConverter in JSInterop that uses
Assembly.GetType
, probably https://github.com/dotnet/aspnetcore/blob/main/src/JSInterop/Microsoft.JSInterop/src/JSRuntime.cs#L38-L45 doing something likeaspnetcore/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetDispatcher.cs
Lines 487 to 509 in 063ba34
We want to keep a cache of types on the converter to avoid multiple lookups (both for assemblies and types). Follow the pattern In DotNetDispatcher</agent_instructions>
Comments on the Issue (you are @copilot in this section)
@ Thanks for contacting us.We're moving this issue to the
.NET 9 Planning
milestone for future evaluation / consideration. We would like to keep this...💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.