Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Event handlers in layout do not seem to fire in a .NET 8 RC1 blazor application #50712

Closed
1 task done
akorchev opened this issue Sep 14, 2023 · 11 comments
Closed
1 task done
Labels
area-blazor Includes: Blazor, Razor Components

Comments

@akorchev
Copy link

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

Originally reported as a problem with the Radzen.Blazor component library which we maintain. After troubleshooting it turned out that no event handlers are firing (no exceptions or any other problems).

I tested without Radzen.Blazor and managed to reproduce the problem with a vanilla button click handler taken from the Counter.razor component that comes from the default application template.

For some reason event handlers defined in the layout do not fire out of the box.

Expected Behavior

I expected event handlers in layouts to work as in earlier Blazor and .NET versions. Maybe some configuration is missing (related to the new mixed rendering model).

Steps To Reproduce

  1. Create a new .NET 8 Blazor application by running dotnet new blazor -o BlazorNET8
  2. Open Components/MainLayout.razor.
  3. Delete everything and paste
     @inherits LayoutComponentBase
    
     <div class="page">
     <div class="sidebar">
         <NavMenu />
     </div>
    
     <main>
         <div class="top-row px-4">
             <p role="status">Current count: @currentCount</p>
             <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
             <a href="https://learn.microsoft.com/aspnet/core/" target="_blank">About</a>
         </div>
    
         <article class="content px-4">
             @Body
         </article>
     </main>
    </div>
    
     <div id="blazor-error-ui">
     An unhandled error has occurred.
     <a href="" class="reload">Reload</a>
     <a class="dismiss">🗙</a>
     </div>
    
     @code {
     private int currentCount = 0;
    
     private void IncrementCount()
     {
         currentCount++;
     }
    }
    
  4. Run the application and try clicking the Click me button in the header. The displayed counter value remains 0 instead of incrementing. In .NET 7 this works as expected.

Exceptions (if any)

No response

.NET Version

8.0.100-rc.1.23455.8

Anything else?

I am testing on macOS (M1, Ventura 13.4.1).

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-blazor Includes: Blazor, Razor Components label Sep 14, 2023
@JasonWeise
Copy link

Definintely does this on .Net 8 RC1 on Windows 10 as descibed above as well.
I hope this bug doesn't make it into GA.

@gragra33
Copy link

@akorchev By default, Blazor renders static pages. You need to tell Blazor how to render.

From your example, the Counter.razor page has the following attribute:

@attribute [RenderModeServer]

There are modes: aspcore/src/Components/Web/src/RenderMode/RenderMode.cs

There was a short-lived discussion here: Clarify the names of the interactive render modes for Blazor and rationalize with the component tag helper #50636

@akorchev
Copy link
Author

akorchev commented Sep 15, 2023

Thank you for the clarification @gragra33. I tried adding @attribute [RenderModeServer] to MainLayout.razor and ended up with a different exception.

InvalidOperationException: Cannot pass the parameter 'Body' to component 'MainLayout' with rendermode 'ServerRenderMode'. This is because the parameter is of the delegate type 'Microsoft.AspNetCore.Components.RenderFragment', which is arbitrary code and cannot be serialized.

What are the required steps to enable events in the MainLayout? I tried with RenderModeServer(false), RenderModeWebAssembly. All lead to the same exception.

It sounds as related to #50433 but I am not sure.

I found this and it seems that in order to enable interactivity in the layout one has to create child components with their RenderMode set and use them.

This however makes it hard (if not impossible) to use @Body as the ChildContent of a component that needs interactivity.

@gragra33
Copy link

gragra33 commented Sep 15, 2023

@akorchev I was looking at a different issue #50724 and noticed that behavior too.

Yeah, the workaround is to have a wrapper component 'WrapperComponent .razor':

@ChildContent

@code {
    public RenderFragment ChildContent { get; set; }
}

Then in the MainLayout.razor:

<article class="content px-4">
    <WrapperComponent @rendermode="@RenderMode.Server">
        <ChildContent>
            @Body
        </ChildContent>
    </WrapperComponent>
</article>

I removed the render modes on the sample pages and this works.

@akorchev
Copy link
Author

I see this is all by design. By the way we seem to have the same issue as #50724 ... Also I've spent 15 minutes wondering why a click event was not firing in Home.razor - it was all because @attribute [RenderModeServer] was missing. I wonder why static rendering was picked as the default mode.

@gragra33
Copy link

gragra33 commented Sep 15, 2023

@akorchev Yep, this will be a big headache as it breaks how it works by default.

I suggested an interactivity opt-out attribute, so interactive by default, but was told too much work at this late stage.

@akorchev
Copy link
Author

I was having doubts about those mixed rendering modes but didn't expect components to not be interactive by default. We will see how the Blazor community reacts.

@akorchev
Copy link
Author

I am closing the issue as it is the new default behavior. There will be a new switch in dotnet new blazor that will enable full application interactivity by default. Enabling it now is as simple as changing <Routes /> in App.razor to <Routes @rendermode=@RenderMode.Server />.

@TimPurdum
Copy link

This bit me today, same deal, I replace MainLayout with my own code on .NET 8 and had no interactivity. Worse, I share pages and components with MAUI hybrid, so sprinking "RenderMode" throughout that shared code seems like a dangerous idea. Is there no way to go back to .NET7 default server rendering, but still preserve the options of adding other modes in the future?

@TimPurdum
Copy link

Also, the workaround did not work, even with a WrapperComponent, I got the same error @akorchev described above.

@iancoetzer
Copy link

I am closing the issue as it is the new default behavior. There will be a new switch in dotnet new blazor that will enable full application interactivity by default. Enabling it now is as simple as changing <Routes /> in App.razor to <Routes @rendermode=@RenderMode.Server />.

Thank you, after almost two hours I found your solution.

@ghost ghost locked as resolved and limited conversation to collaborators Oct 30, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-blazor Includes: Blazor, Razor Components
Projects
None yet
Development

No branches or pull requests

5 participants