Skip to content

Fix culture persistence to not have public API#67367

Merged
dariatiurina merged 9 commits into
dotnet:mainfrom
dariatiurina:fix-culture-api
Jun 29, 2026
Merged

Fix culture persistence to not have public API#67367
dariatiurina merged 9 commits into
dotnet:mainfrom
dariatiurina:fix-culture-api

Conversation

@dariatiurina

@dariatiurina dariatiurina commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Fix culture persistence to not have public API

Summary

Reworks how interactive WebAssembly culture persistence is configured so it no longer requires a public API surface, and changes the default behavior. Instead of a public options class and a configuration callback overload (defaulting culture capture on), culture capture is now opt-in and driven by the Components:UseCultureFromServer configuration value, with a fallback based on whether localization is registered.

Changes

  • Removed the public WebAssemblyComponentsOptions class and its UseCultureFromServer property.
  • Removed the public AddInteractiveWebAssemblyComponents(this IRazorComponentsBuilder, Action<WebAssemblyComponentsOptions>?) overload. Only the parameterless AddInteractiveWebAssemblyComponents()` remains.
  • Added internal WebAssemblyComponentsServiceOptions with a nullable UseCultureFromServer property.
  • Added internal WebAssemblyComponentsServiceOptionsConfiguration, an IPostConfigureOptions<WebAssemblyComponentsServiceOptions> that reads the Components:UseCultureFromServer configuration value and sets the option to true when the value is "true" or "1" (case-insensitive).
  • Added a Microsoft.Extensions.Localization.Abstractions reference to the project so the registration can probe for IStringLocalizerFactory.
  • Updated PublicAPI.Unshipped.txt to drop the removed public API entries.
  • Updated the Components.TestServer startup to set Components:UseCultureFromServer via configuration instead of using the removed callback overload.

Details

  • The CultureStateProvider is now always registered as a scoped service and always added as a persistent component state registration for RenderMode.InteractiveWebAssembly. Previously both registrations were conditional on UseCultureFromServer being true.
  • The decision to capture the culture is moved from registration time to provider construction time. The scoped factory only calls CaptureCurrentCulture() when culture capture is enabled, computed as:
    options.UseCultureFromServer ?? (IStringLocalizerFactory is registered).
    This honors an explicit Components:UseCultureFromServer configuration value, and otherwise falls back to enabling culture capture when localization has been added (since AddLocalization registers IStringLocalizerFactory).

Behavior Change

  • This intentionally changes the default behavior. Previously culture capture was on by default (WebAssemblyComponentsOptions.UseCultureFromServer defaulted to true). Now culture is only captured when Components:UseCultureFromServer is explicitly enabled, or — when not explicitly configured — when localization (IStringLocalizerFactory) is registered. Apps that relied on the previous always-on behavior must now opt in via the Components:UseCultureFromServer configuration value or by adding localization.

Testing

  • RazorComponentEndpointsStartup now toggles the behavior through the Components:UseCultureFromServer configuration key ("true"/"false") based on the existing EnforceServerCultureOnClient setting, exercising the new configuration path through the existing E2E culture scenarios.

Breaking Changes

  • The previously proposed public API (WebAssemblyComponentsOptions and the Action<WebAssemblyComponentsOptions>? overload) is removed. These were unshipped (no PublicAPI.Shipped.txt entries), so no released package is affected. Consumers configuring this behavior should now set the Components:UseCultureFromServer configuration value instead of passing an options callback.
  • See Behavior Change above: culture is no longer captured by default.

Fixes #66829

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR removes the unshipped public options/configuration surface for interactive WebAssembly culture persistence and replaces it with an internal options type driven by the Components:UseCultureFromServer configuration key.

Changes:

  • Removes WebAssemblyComponentsOptions and the AddInteractiveWebAssemblyComponents(..., Action<WebAssemblyComponentsOptions>?) overload, leaving only the parameterless AddInteractiveWebAssemblyComponents().
  • Introduces internal WebAssemblyComponentsServiceOptions plus an IPostConfigureOptions<> to read Components:UseCultureFromServer.
  • Updates the test server startup to set Components:UseCultureFromServer via configuration, and updates PublicAPI.Unshipped.txt accordingly.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/Components/WebAssembly/Server/src/WebAssemblyRazorComponentsBuilderExtensions.cs Removes the public overload and switches culture capture behavior to be driven by internal options/config.
src/Components/WebAssembly/Server/src/WebAssemblyComponentsServiceOptionsConfiguration.cs Adds post-configure hook to read Components:UseCultureFromServer from configuration.
src/Components/WebAssembly/Server/src/WebAssemblyComponentsServiceOptions.cs Adds internal options container (defaults UseCultureFromServer to true).
src/Components/WebAssembly/Server/src/WebAssemblyComponentsOptions.cs Removes the (unshipped) public options type.
src/Components/WebAssembly/Server/src/PublicAPI.Unshipped.txt Removes unshipped public API entries for the deleted options type and overload.
src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsStartup.cs Updates test server wiring to set the new configuration key instead of using the removed overload.

@dariatiurina dariatiurina marked this pull request as ready for review June 23, 2026 11:23
@dariatiurina dariatiurina requested a review from a team as a code owner June 23, 2026 11:23
@dariatiurina dariatiurina requested a review from ilonatommy June 23, 2026 11:23
@dariatiurina dariatiurina added this to the 11.0-preview7 milestone Jun 25, 2026
@dariatiurina dariatiurina added the area-blazor Includes: Blazor, Razor Components label Jun 25, 2026
@dariatiurina dariatiurina requested a review from ilonatommy June 25, 2026 15:57
Comment thread src/Components/WebAssembly/Server/src/WebAssemblyComponentsServiceOptions.cs Outdated

@ilonatommy ilonatommy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will push a draft PR with the cleanup proposal.

@ilonatommy ilonatommy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added allocation removal and cleanup ideas. The issue with setting false from config gave me an idea to check the test coverage. It looks like we have a few gaps. To keep it cheap they should be unit tests.
It would be good to cover the matrix with dimensions: config true/false/not configured, config 1/0, config True/False/garbage e.g. "yes", service registered/not registered.

@dariatiurina dariatiurina enabled auto-merge (squash) June 29, 2026 10:24
@dariatiurina dariatiurina merged commit 0d9143a into dotnet:main Jun 29, 2026
25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-blazor Includes: Blazor, Razor Components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

API Proposal: CulturePersistance from WebAssembly

4 participants