跪拜 Guibai
← All articles
.NET

Blazor in .NET 10 Gets Circuit State Persistence, Passkeys, and a Declarative State Model

By 葡萄城技术团队 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Circuit state persistence and the declarative state model remove two long-standing friction points for Blazor Server and auto-render-mode apps: losing in-progress work on disconnect and writing repetitive prerendering state code. Passkey support brings passwordless authentication into the default Identity stack without third-party libraries.

Summary

Blazor Web Apps can now persist user session state across long disconnections or deliberate circuit pauses, using far fewer server resources than keeping a live circuit. A new `[SupplyParameterFromPersistentComponentState]` attribute eliminates the manual `PersistentComponentState` plumbing previously required to carry state from prerendering into interactive components. ASP.NET Core Identity gains built-in WebAuthn/FIDO2 passkey support, and the Preview 6 template ships with ready-made passkey management and login.

Routing gets a dedicated `NotFoundPage` parameter on the `Router` component, `NavigationManager.NavigateTo` stops throwing `NavigationException` during static SSR, and same-page navigation no longer scrolls to the top. `QuickGrid` picks up a `RowClass` parameter for conditional row styling and a `HideColumnOptionsAsync` method. On the interop side, Blazor can now construct JavaScript objects and get/set properties directly through new `IJSRuntime` and `IJSInProcessRuntime` methods.

Under the hood, response streaming is on by default for `HttpClient` in WebAssembly, Blazor scripts ship as fingerprinted static web assets, and standalone WebAssembly apps can opt into client-side fingerprinting for JavaScript modules. The custom Blazor cache and `BlazorCacheBootResources` MSBuild property are gone, replaced by standard browser caching.

Takeaways
Circuit state now persists across disconnections or deliberate pauses, consuming only developer-controlled memory instead of a full live circuit.
A new `[SupplyParameterFromPersistentComponentState]` attribute auto-persists component and service properties during prerendering, removing manual `PersistentComponentState` code.
ASP.NET Core Identity supports WebAuthn/FIDO2 passkeys; the Preview 6 Blazor Web App template includes passkey management and login out of the box.
`Router` gains a `NotFoundPage` parameter that takes a page type, supports routing and status-code middleware, and works in non-Blazor scenarios.
`NavigationManager.NavigateTo` no longer throws `NavigationException` during static SSR, matching interactive rendering behavior.
Same-page navigation no longer scrolls to the top, so changing query strings or fragments preserves the viewport position.
`QuickGrid` adds `RowClass` for conditional row CSS and `HideColumnOptionsAsync` to programmatically close the column options UI.
Response streaming for `HttpClient` in WebAssembly is now on by default; synchronous stream reads will break unless opted out.
Blazor scripts are served as fingerprinted, compressed static web assets instead of embedded resources, improving CDN and cache usage.
Standalone Blazor WebAssembly apps can opt into client-side fingerprinting for JS modules via `OverrideHtmlAssetPlaceholders` and import maps.
New JS interop methods allow constructing JS objects and getting/setting properties synchronously and asynchronously on `IJSRuntime` and `IJSInProcessRuntime`.
Form validation now handles nested objects and collection items when models are declared in separate C# files and annotated with `[ValidatableType]`.
The `ReconnectModal` component in the project template dispatches a `components-reconnect-state-changed` event and exposes a `retrying` CSS class for finer reconnection UI control.
`NavLinkMatch.All` ignores query strings and fragments by default; the old behavior is behind an `AppContext` switch.
Custom Blazor caching and the `BlazorCacheBootResources` MSBuild property are removed; browser-native caching takes over.
Standalone WebAssembly apps set the environment via `<WasmApplicationEnvironmentName>` in the `.csproj` file, not `launchSettings.json`.
Blazor's boot configuration is inlined into `dotnet.js` instead of a separate `blazor.boot.json` file.
Build output can be made bundler-friendly for tools like Webpack and Rollup by setting `WasmBundlerFriendlyBootConfig` to true.
Conclusions

Circuit state persistence changes the cost model for Blazor Server: a paused session now costs a small fixed memory allocation rather than a live CPU-and-memory-consuming circuit, which makes aggressive circuit suspension viable in production.

The declarative state model and the new form validation both depend on source generators, and the validation feature explicitly requires model types in separate C# files because one source generator's output cannot yet feed another — a constraint that reveals the current compiler pipeline boundary.

Default-enabling response streaming in WebAssembly HttpClient is a breaking change for any code that calls synchronous `Stream.Read` on response content; the fix is either an explicit opt-out or a manual copy to `MemoryStream`.

Removing `NavigationException` from static SSR `NavigateTo` calls eliminates a long-standing behavioral split between rendering modes, but it also silently breaks any code that caught that exception to short-circuit execution.

The shift from `blazor.boot.json` to an inlined config inside `dotnet.js` and the removal of custom Blazor caching both point toward a simpler, browser-native asset story that relies on standard fingerprinting and HTTP caching rather than framework-specific mechanisms.

Concepts & terms
Circuit State Persistence
A Blazor Server feature that saves user session state to a memory cache when the SignalR circuit disconnects or is paused, allowing the session to resume later without losing in-progress work. It uses far fewer server resources than keeping the circuit alive.
Passkeys (WebAuthn/FIDO2)
A passwordless authentication standard based on public-key cryptography. Users authenticate via device-based methods like biometrics or hardware security keys. ASP.NET Core Identity now includes built-in support for registering and signing in with passkeys.
Declarative State Persistence
A new Blazor model where adding the `[SupplyParameterFromPersistentComponentState]` attribute to a property automatically persists its value through the `PersistentComponentState` service during prerendering, eliminating manual serialization code.
Client-side Fingerprinting
A build-time process that appends a content hash to static asset filenames (e.g., `blazor.webassembly.js` becomes `blazor.webassembly#[.{fingerprint}].js`). This enables aggressive browser caching because the filename changes whenever the content changes.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗