How to render Blazor component with RenderFragment Parameter from Razor Page

1k views Asked by At

I have following Blazor component:

Button.razor

<button params...>
    @ChildContent
</button>

@code {
    [Parameter]
    public RenderFragment ChildContent { get; set; }
}

I want to use it in the Razor page. I know I can use: @(await Html.RenderComponentAsync<Button>(RenderMode.ServerPrerendered)) for that. But how do I pass the RenderFragment parameter to this component? The RenderComponentAsunc has a second argument where I can pass parameters for component so I think something like this should be possible:

Page.cshtml

@(await Html.RenderComponentAsync<Button>(RenderMode.ServerPrerendered, new
{
    ChildContent = "Button text"
}))

However this ends with error:

InvalidCastException: Unable to cast object of type 'System.String' to type 'Microsoft.AspNetCore.Components.RenderFragment'.

So I tried to pass RenderFragment directly. I created extension method that create RenderFragment from string:

public static class StringExtensions
{
    public static RenderFragment ToRenderFragment(this string s) => b => b.AddContent(0, s);
}

And then render it this way:

@(await Html.RenderComponentAsync<Button>(RenderMode.ServerPrerendered, new
{
    ChildContent = "Button text".ToRenderFragment()
}))

I wasn't successful with this approach either.

NotSupportedException: Serialization and deserialization of 'Microsoft.AspNetCore.Components.RenderFragment' instances are not supported.NotSupportedException: Serialization and deserialization of 'Microsoft.AspNetCore.Components.RenderFragment' instances are not supported.NotSupportedException: Serialization and deserialization of 'Microsoft.AspNetCore.Components.RenderFragment' instances are not supported.

The component can be also rendered with using <component> tag. So I tried it.

<component type="typeof(Button)" render-mode="ServerPrerendered">
    Button text    
</component>

But this renders html incorrectly

<button></button>
Button text

And I want

<button>
    Button text
</button>

How to do that? I am using button as simplied example here so direct use of markup in the .cshtml file would be inconvenient duplication of code.

1

There are 1 answers

2
Jonathan On

You could simply add a parameter of type MarkupString, which supports HTML content. In the blazor component you can just say @MyMarkupString and it'll be rendered as HTML.

If you do want to use the RenderFragment, you can use a normal string as parameter. Then in the component itself, you can call the ToRenderFragment on that string, if it has a value.

Both of these options should work around the NotSupportedException you got as string and MarkupString are serializable.