aspnetcore icon indicating copy to clipboard operation
aspnetcore copied to clipboard

SectionContent doesn't work correctly with render modes

Open surayya-MS opened this issue 2 years ago • 12 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Describe the bug

SectionContent doesn't inherit render mode (SectionOutlet does instead).

Expected Behavior

SectionContent should inherit render mode

Steps To Reproduce

In interactive server app add in top-row div in MainLayout.razor

<SectionOutlet SectionName="topbar" />

In Counter.razor add

<SectionContent SectionName="topbar">
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
</SectionContent>

The result is that the button in the topbar does not increase the counter.

The workaround is to add interactive server mode to SectionOutlet:

<SectionOutlet SectionName="topbar" @rendermode="@RenderMode.InteractiveServer" />

Then the button is interctive.

However, if the app uses all render modes the bahavior is ugly.

If I have ServerCounter.razor, AutoCounter.razor, WasmCounter.razor (same Counter.razor but with the corresponding render mode) then there is a problem even with the workaround.

In case

<SectionOutlet SectionName="topbar" @rendermode="@RenderMode.InteractiveServer" />

https://github.com/dotnet/aspnetcore/assets/114938397/ca0c3976-06c7-47e1-8847-62085c821e50

Changing to interactive Auto is also bad

https://github.com/dotnet/aspnetcore/assets/114938397/6ef13ce4-7493-46c3-8308-38c0b41fc44a

Exceptions (if any)

No response

.NET Version

No response

Anything else?

No response

surayya-MS avatar Oct 04 '23 15:10 surayya-MS

@mkArtakMSFT this I feel is related: #51132

gragra33 avatar Oct 04 '23 16:10 gragra33

Agreed, this issue is related to itself :)

SteveSandersonMS avatar Oct 04 '23 16:10 SteveSandersonMS

Opps @SteveSandersonMS ... I meant #50998

gragra33 avatar Oct 04 '23 17:10 gragra33

Thanks for filing this, @surayya-MS! I've been looking into it and think I understand now.

Regarding the initial case you mentioned, i.e.,

In Counter.razor add < SectionContent SectionName="topbar"> <button class="btn btn-primary" @onclick="IncrementCount">Click me < /SectionContent>

There are multiple reasons why this doesn't work:

  • Nothing tells the renderer to introduce a rendermode boundary for SectionOutletContentRenderer
    • We only introduce a rendermode boundary when a rendermode is set either on the component type itself or at the callsite, and in this case, neither is true
  • You might think we could change the code in SectionOutlet that creates SectionOutletContentRenderer and make it explicitly assign the rendermode from _currentContentProvider, but that doesn't actually make sense
    • ... because then SectionOutletContentRenderer would become an interactive root, which means we have to serialize all its params, but we can't serialize the RenderFragment you're actually trying to render as the section content
  • You might think people could work around it themselves by putting some extra layer of component inside the SectionContent, e.g., a MyButton component, but that doesn't work either:
    • Again, it won't be treated as an interactive root if it doesn't have any rendermode set on itself or at the callsite
    • You might think you could work around that by setting an explicit rendermode at the callsite, e.g., <MyButton @rendermode=... OnClick=SomeCallback />
      • ... but that doesn't work either because SomeCallback will be a delegate and hence can't be serialized, so even though MyButton now does run as a server component, it can't invoke a callback like you want it to

Altogether the intuition for why this can't work is that it would involve creating an interactive root for the section outlet, but how would we serialize a definition of what content should go into it? There isn't an actual component name for the content (it's just a RenderFragment) and in general you can be referring to nonserializable things.

To make something like this work, we'd need some further abstraction around the idea of a component marker, so that instead of just describing a type+params, it would have to describe some kind of abstract slot that may later be filled by interactively-generated content. Maybe we'd have a special marker specifically for "section outlet" based on its name.

SteveSandersonMS avatar Oct 04 '23 17:10 SteveSandersonMS

Thanks for contacting us.

We're moving this issue to the .NET 9 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s). If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

ghost avatar Oct 09 '23 16:10 ghost

Thanks for contacting us.

We're moving this issue to the .NET 9 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s). If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

ghost avatar Dec 20 '23 17:12 ghost

There are two parts involved here:

  1. Throw an error when the render modes between SectionContent and SectionOutlet don't match
  2. Find a proper solution to avoid this problem altogether

We'll use this issue to track no. 1 above.

mkArtakMSFT avatar Jan 16 '24 17:01 mkArtakMSFT

The PageTitle issues 52368/50267/50268/52689, got closed just because it is related to this one. Not sure how they are related, but in all the tickets for the PageTitle issue, I never found a work around. So is PageTitle just broke until .net 9 comes out?

nateinindy avatar Mar 20 '24 14:03 nateinindy

@nateinindy Would it be possible to file an issue with repro steps for your scenario? We don't know for sure what specific problem you might be encountering.

SteveSandersonMS avatar Mar 20 '24 14:03 SteveSandersonMS

Hey Steve. Yeah, the following code does not set the page title.

@page "/test"

@rendermode @(new InteractiveServerRenderMode(false))

<PageTitle>@pageTitle</PageTitle>

@code {
    private string pageTitle = "";

    protected override async Task OnInitializedAsync()
    {
        await Task.Delay(1);
        pageTitle = "no show";
    }
}

nateinindy avatar Mar 21 '24 13:03 nateinindy

Thanks for clarifying, @nateinindy. I'm reopening https://github.com/dotnet/aspnetcore/issues/50268 since that seems like the best issue for tracking the specific limitation with PageTitle.

SteveSandersonMS avatar Mar 21 '24 13:03 SteveSandersonMS

Any progress on this issue? Just want to mention that this functionality is critical to SEO, as no head elements are rendered when bots (for example Google crawler) are indexing the page. This is a really serious blocker for websites.

Enabling prerender is not an answer for production pages, as the flicker is bad for usability.

andrei-mu avatar Jun 18 '25 16:06 andrei-mu