Skip to content

[Validation] Navigating between pages that use different render modes #68516

Description

@oroztocil

Scenario contact: @javiercn

Scenario

Blazor writes bookkeeping into the page as HTML comments: WebAssembly options, persisted component state, JavaScript initializers. In .NET 10 those comments were pulled into Blazor's logical tree during the first render, then removed from the DOM during component discovery, leaving the tree pointing at nodes that no longer existed. The next enhanced navigation across a render-mode boundary hit one of those dangling references and threw Cannot read properties of null (reading 'insertBefore'): the address bar changed, no new page appeared, and only a full reload or forceLoad: true recovered.

This is a .NET 10 regression. The <!--Blazor-WebAssembly:...--> comment arrived in .NET 10 with WebAssembly options discovery, and nothing filtered it out of the tree. .NET 11 skips metadata comments when the logical tree is built. Two separate customer reports drove the fix, and this scenario reproduces both: navigating from a WebAssembly page to an Interactive Server page, and navigating away from a page that sets no <PageTitle>.

Minimum build

.NET 11 Preview 7 or later.

Configurations to cover

  • Blazor Web App
    • Static SSR
    • Interactive Server
    • Interactive WebAssembly
    • Interactive Auto
  • Standalone WebAssembly
  • Hybrid (MAUI)

This is one app containing all three modes, not three runs. The ticks say which page render modes the app needs, because the bug only appears when navigating from one mode to another.

The app must be WebAssembly-capable, since that is what emits the Blazor-WebAssembly comment the regression was about. Create it with -int Auto or -int WebAssembly and then set the mode per page. Interactive Auto is left unticked as a page mode: an Auto page is Server on the first visit and WebAssembly afterwards, so it exercises the same two paths the other pages already cover.

Also exercise

  • Published output
  • An existing .NET 10 app upgraded to .NET 11
  • Trimming or ahead-of-time compilation
  • More than one server instance, or a proxy in front
  • Hot Reload
  • An IDE as well as the command line
  • Container

Published output is included because the Blazor-WebAssembly comment carries the fingerprinted resource collection, so its contents differ from a development build.

What to build

Create the app with dotnet new blazor -int Auto, leaving interactivity per page rather than global. The two reported repros need a specific arrangement, so follow this table exactly:

Route Render mode Project <PageTitle>
/ @rendermode InteractiveWebAssembly .Client yes
/counter @rendermode InteractiveWebAssembly .Client none
/weather @rendermode InteractiveServer server yes
/about none, so it is statically rendered server none

Two details in that table are load-bearing and easy to undo by accident:

  • /counter and /about must have no <PageTitle> at all. Adding one is the documented workaround for the reported bug, so a page that has it cannot reproduce anything. You can tell these pages apart in the browser because the tab shows the address instead of a name.
  • The home page at / must live in the .Client project and render on WebAssembly. The report that started this was written against exactly that arrangement.

Put a link to each page in the nav menu. Navigation has to happen by clicking links, because a typed address is a full page load and does not go through the code being fixed.

The metadata comments are what the fix is about, so make sure the page emits them. Add a component using [PersistentState] and a JavaScript initializer. Before testing, view the page source and confirm you can find comments beginning with:

<!--Blazor-WebAssembly:
<!--Blazor-Web-Initializers:
<!--Blazor-Server-Component-State:
<!--Blazor-WebAssembly-Component-State:

Those four are the ones this setup produces. The fix also filters <!--Blazor-Configuration:, which appears only if the app sets browser options, so add a <ConfigureBrowser> to the page if you want that one covered too.

If none of these appear, the app is not set up to reproduce the bug and a pass means nothing.

Things to try

Open the browser console and leave it open. Then, clicking nav links rather than typing addresses:

  • / to /weather, WebAssembly to Interactive Server. This is the first reported repro.
  • /counter to /, WebAssembly to WebAssembly, having first landed on /counter, which has no title. This is the second reported repro.
  • /counter to /about, WebAssembly to static.
  • The remaining ordered pairs between the four pages.
  • The same navigations using browser back and forward.
  • Typing a destination address directly, which worked in .NET 10 even when clicking the link did not. This separates enhanced navigation from a full page load.
  • The same app on .NET 10, to see both failures this fixes.

Expected behavior

Every navigation renders the destination page, whatever render modes the two pages use and whether or not either page sets a title.

Must hold

  • Navigating from / to /weather by clicking the nav link renders the weather page.
  • Navigating from /counter to /, and from /counter to /about, renders the destination page. Visiting a page with no <PageTitle> does not break navigation from that point on.
  • No Cannot read properties of null (reading 'insertBefore') error appears in the browser console during any navigation, nor any other error.
  • Every ordered pair of the four pages navigates successfully, in both directions, and the address bar and the visible content agree.
  • On pages that set a <PageTitle>, the document title changes to it. On /counter and /about the tab shows the address instead, which is expected and is not the failure being tested.
  • A page reached by clicking a nav link becomes interactive, the same as when it is loaded directly by typing its address.
  • No navigation needs a reload or forceLoad: true to recover.
  • Going around all four pages five times without reloading ends with the app still working and the console still clean.

Expected differences between configurations

  • The first visit to /server-page waits for a circuit and the first visit to /wasm-page waits for the runtime, so both are slower than a static page. Slower is expected; a page that does not render is a finding.

Evidence to capture

For any navigation that failed, the full browser console output including the stack trace, plus the page source of the page you navigated away from, since that is where the metadata comments live. Note whether the page you left had a <PageTitle>.

Documentation to use

What to report

Report results using the format described in the validation testing manual. Include link to a repository with the test app.

Metadata

Metadata

Labels

ValidationThis issue is used to track validation effortsarea-blazorIncludes: Blazor, Razor Componentsvalidation-scenarioThis issue describes a validation testing scenario

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions