Skip to content

Conversation

@tomerqodo
Copy link

Benchmark PR dotnet#64643

Type: Corrupted (contains bugs)

Original PR Title: Add test coverage for prerendering closed generic components
Original PR Description: # Add test coverage for prerendering closed generic components

  • You've read the Contributor Guide and Code of Conduct.
  • You've included unit or integration tests for your change, where applicable.
  • You've included inline docs for your change, where applicable.
  • There's an open issue for the PR that you are making. If you'd like to propose a new feature or change, please open an issue to discuss the change or find an existing issue.

Add tests verifying closed generic components can be prerendered

Description

The issue reported that generic components couldn't be rendered as root components due to type serialization limitations. Investigation shows the feature already works correctly:

  • Type.FullName produces valid assembly-qualified names for closed generics (e.g., GenericComponent1[[System.Int32, System.Private.CoreLib, ...]]`)
  • Assembly.GetType() correctly resolves these names during deserialization

This PR adds comprehensive test coverage:

EndpointHtmlRendererTest (4 tests)

  • Static rendering of GenericComponent<int>
  • Interactive Server mode (prerendered and non-prerendered)
  • Interactive WebAssembly mode (prerendered)

ServerComponentDeserializerTest (4 tests)

  • Serialization/deserialization round-trip for closed generic types
  • Different type parameters (int, string)
  • Parameter handling with generic components
@* Example: GenericComponent.razor *@
@typeparam TValue

<p>Generic value: @(Value?.ToString() ?? "(null)")</p>
@code {
    [Parameter] public TValue Value { get; set; }
}

Usage in tests:

var result = await renderer.PrerenderComponentAsync(
    httpContext, 
    typeof(GenericComponent<int>), 
    RenderMode.InteractiveServer, 
    ParameterView.FromDictionary(new Dictionary<string, object> { { "Value", 123 } }));
Original prompt

This section details on the original issue you should resolve

<issue_title>Support prerendering closed generic components</issue_title>
<issue_description>

Summary

We don't support rendering generic components as root components due to limitations in the way we serialize the type definition for the component (a similar thing happens for component parameters). We should consider lifting this limitation to support some more advanced scenarios.

Motivation and goals

Turns out that rendering generic components is useful if you want to write a "functional" component to wrap around another component, an example of this is when you are rendering multiple components at different points on a page and you want to, for example, require authentication for those components.

At that point, application developers are forced to write an individual wrapper for each of those components they want to wrap.

In scope

Support rendering closed generic components from Blazor applications.

Out of scope

TBD

Risks / unknowns

None so far

Examples

<CascadingAuthenticationState>
    <AuthorizeView>
        <Authorized>
            <TComponent @attributes="Params" />
        </Authorized>
    </AuthorizeView>
</CascadingAuthenticationState>

@code{
    [Parameter(CaptureUnmatchedValues = true)] public IDictionary<string,object> Params { get; set; }
}

Having a language syntax for writing these types of components is also desirable, otherwise it's cumbersome and likely error prone to author them:

    public class ProtectedWidget<T> : IComponent where T : IComponent
    {
        private RenderHandle _handle;
        private ParameterView _parameters;
        static RenderFragment _authorizeFragment;

        public ProtectedWidget()
        {
            _authorizeFragment = new RenderFragment(AuthorizedFragment);
        }

        public void Attach(RenderHandle renderHandle)
        {
            _handle = renderHandle;
        }

        public Task SetParametersAsync(ParameterView parameters)
        {
            _parameters = parameters;
            _handle.Render(BuildRenderTree);

            return Task.CompletedTask;
        }

        private void BuildRenderTree(RenderTreeBuilder builder)
        {

            builder.OpenComponent<CascadingAuthenticationState>(0);
            builder.OpenComponent<AuthorizeView>(1);
            builder.AddAttribute(1, "Authorized", _authorizeFragment);
            builder.CloseComponent();
            builder.CloseComponent();

        }
        void AuthorizedFragment(RenderTreeBuilder child)
        {
            child.OpenComponent<T>(0);
            child.AddMultipleAttributes(1, _parameters.ToDictionary());
            child.CloseComponent();
        }
    }

</issue_description>

Comments on the Issue (you are @copilot in this section)

@ Thanks for contacting us. We're moving this issue to the `Next sprint planning` milestone for future evaluation / consideration. We will evaluate the request when we are planning the work for the next milestone. To learn more about what to expect next and how this issue will be handled you can read more about our triage process [here](https://github.com/dotnet/aspnetcore/blob/master/docs/TriageProcess.md). @ 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](https://github.com/dotnet/aspnetcore/blob/master/docs/TriageProcess.md). @ 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](https://github.com/dotnet/aspnetcore/blob/main/docs/TriageProcess.md).

💡 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.
Original PR URL: dotnet#64643

Copilot AI and others added 2 commits January 21, 2026 16:00
Co-authored-by: javiercn <6995051+javiercn@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants