Skip to content

Improving type-safety of RazorComponentResult<T> #51923

@KennethHoff

Description

@KennethHoff

Background and Motivation

ASP.Net Core 8 introduced the RazorComponentResult<T> which allows a developer to render Razor Components from normal endpoints. This is very useful for for example HTMX as it allows you to create very simple endpoints like this, which will return a pre-rendered Razor Component as raw HTML over the wire.

image

However, there is one huge problem with the ergonomics here when it comes to parameter passing, as you have to pass in dynamic objects, like the following:

image

Without any further context you might not realize the problem, but here's the component:

image

As you can see, this will not function as you'd expect - in fact, it will throw at runtime. The reason is that I passed in AuthorId when I should've passed in UserId. You might think, "Oh, I'll just pass in a model of type SomeRandomComponent" (I certainly did..), but that will give you this compiler error (https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0005):

image
image

error BL0005: Component parameter 'UserId' should not be set outside of its component. 

So the only solution we have is to pass in an anonymous object and pray we did it right.

This is not only a problem for when you forget to add a prop, but also when you forget to remove a prop, as if the component doesn't have a prop with the name you specified, you also get a runtime error:

InvalidOperationException: Object of type 'MyNamespace.SomeRandomComponent' does not have a property matching the name 'AuthorId'.

There is also the problem with the fact that - as you can see in the third image (The one with the Component code), I have [EditorRequired] on the parameter, but the component renders just fine - no warning or anything - despite me not passing it in (in the first example)

Proposed API

I don't have any specific APIs in mind, but in an ideal world I'd love for there to be an overload that works something like this:

image

Usage Examples

image

Alternative Designs

  • Roslyn Analyzer that analyzes usages of RazorComponentResult<T> constructors and warns you (with quick fixes) whenever you don't address all errors (Removes invalid ones, and adds all parameters, as well as type-checks them)
  • Roslyn Source Generator that creates custom RazorComponentResult<T> for each Component:
    • image
    • image
    • There are a few cons for this however, and that mostly comes from the fact that we lost the object initializer syntax, so we lost optional-ness as well as the ordering being semi-random (Re-ordering the component parameters would reorder the constructor parameters)

Risks

The proposed API presumably cannot be implemented; I just mentioned what would I consider more-or-less ideal. Assuming we go that direction, then the component parameter assignment logic would presumably need to be rewritten somewhat, which could be quite a huge undertaking.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Pillar: Complete Blazor WebanalyzerIndicates an issue which is related to analyzer experienceapi-suggestionEarly API idea and discussion, it is NOT ready for implementationarea-blazorIncludes: Blazor, Razor ComponentsenhancementThis issue represents an ask for new feature or an enhancement to an existing onefeature-full-stack-web-uiFull stack web UI with Blazor

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions