Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the limitations of Blazor CascadingValue? Complex objects are not being passed

I have an IClipboardService I was injecting into components, but as there is only ever one, I decided to try using a CascadingValue instead.

I recreated all this in a minimal test case. Just add these changes to a basic WebAssembly Blazor app:

I created a CascadingClipboard.razor component that looks like this

<CascadingValue Value="_clipboardService">
    @ChildContent
</CascadingValue>

@inject ClipboardService _clipboardService

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

I also created a far simpler test CascadingInt.razor component with an int value

<CascadingValue IsFixed=true Value="_int">
    @ChildContent
</CascadingValue>

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

    public int _int { get; set; } = 123;
}

I wrapped the MainLayout.razor with both:

@inherits LayoutComponentBase
<CascadingClipboard>
    <CascadingInt>
    <div class="page">
        <div class="sidebar">
            <NavMenu />
        </div>

        <main>
            <div class="top-row px-4">
                <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
            </div>

            <article class="content px-4">
                @Body
            </article>
        </main>
    </div>
    </CascadingInt>
</CascadingClipboard>

Added receiving CascadingParameters in Index.razor

@page "/"
<PageTitle>Index</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.
<SurveyPrompt Title="How is Blazor working for you?" />
@code{
    [CascadingParameter]
    public CascadingClipboard _cascadingClipboard { get; set; }

    [CascadingParameter]
    public int IntValue { get; set; }

    protected override async Task OnParametersSetAsync()
    {
        // BREAKPOINT HERE TO CHECK VALUES
        await base.OnParametersSetAsync();
    }
}

The simple value is always present. The complex object is always null.

I have tried using an explicit assignment instead of injection, but no difference.

Is this simply a limitation of Blazor CascadingValues?

More info:

The reason I tried this in the first place, is that my clipboard singleton needed to be initialised from local storage (to happily survive a refresh, or even returning later). Having a Cascading component makes that easy, but leaving the mechanics as a separate injectable service means I can still inject it into non-components (whereas Cascading only works with components). I now have a pattern for the best of both worlds.

like image 568
Gone Coding Avatar asked Sep 18 '25 06:09

Gone Coding


1 Answers

I feel like a bit of an idiot, but this may help someone else:

Assignment of a CascadingValue to a CascadingParameter works similar to as casting in C#. If the value types do not match it will be null.

If you look at my example, it had the same typo as in my original app, I was effectively trying to assign a ClipboardService object to a CascadingClipboard parameter.

It does not pay to trust Intellisence all the time :)

like image 126
Gone Coding Avatar answered Sep 19 '25 19:09

Gone Coding