Review feedback on the public API proposed in #66393 (BrowserConfiguration for server-to-client configuration). Overall the feature is welcome and justified — Blazor apps commonly need server-authored browser boot options across render modes, and the current mechanisms are fragmented. The notes below are shape/placement suggestions; the endpoint-builder entry point is already in good shape.
Need / scenarios
- Commonality: happy-path; audience: end-app developer.
- Environments: flows wherever the server emits the boot document — static SSR/prerendered, Interactive Server, Interactive WebAssembly hosted by ASP.NET Core, and Auto. It is inert for purely client-side standalone WebAssembly with no server-rendered document — worth documenting.
- Inputs naturally come from
IHostEnvironment, logging options, request culture, and endpoint/middleware configuration.
Recommended shape changes
BrowserConfiguration (the root model)
- Rename to
BrowserOptions — it's an options bag; the Options suffix matches the rest of ASP.NET Core and avoids confusion with IConfiguration.
- Seal it (options/DTO types are sealed by default; can unseal later).
LogLevel: use Microsoft.Extensions.Logging.LogLevel? instead of int? — the usage example passes a magic integer (LogLevel = 2 // Warning); a strongly-typed enum prevents that.
- Make the nested
Server/Ssr/WebAssembly properties non-null and initialized (get-only). The proposed usage config.Server.ReconnectionMaxRetries = 10 NREs unless each sub-object is pre-allocated — a pit-of-failure for the common path.
ServerBrowserOptions
- Consider renaming to
InteractiveServerBrowserOptions — here "Server" means interactive server rendering, not static SSR or the physical server; aligning with Blazor render-mode vocabulary avoids ambiguity.
- Seal it.
ReconnectionRetryIntervalMilliseconds → ReconnectionRetryInterval of type TimeSpan?. Public .NET options express durations as TimeSpan; the serialized browser format can still use milliseconds internally.
SsrBrowserOptions
- Seal it.
CircuitInactivityTimeoutMs → CircuitInactivityTimeout (TimeSpan?).
DisableDomPreservation → positive PreserveDom (public options prefer positive Enable*/Allow*/Preserve* over Disable*; nullable still distinguishes "unset").
WebAssemblyBrowserOptions
- Seal it.
EnvironmentVariables: expose as a non-null, initialized IDictionary<string, string> (get-only) rather than a settable concrete Dictionary<,> — avoids handing out a concrete type and avoids a null collection on the common path.
ConfigureBrowser (component)
- Seal it.
- Add
[Parameter] (and [EditorRequired] on the required options) — component parameters need their attributes visible in the API shape and bound by the runtime.
- Rename
Configuration → Options for consistency with the renamed model.
- Model
HttpContext as a [CascadingParameter] (infrastructure that's absent once execution moves to the browser), not a normal settable parameter.
BrowserConfigurationHttpContextExtensions (the HttpContext accessor)
- Move it out of
Microsoft.AspNetCore.Http into the Blazor feature namespace, and rename to match the options type (GetBrowserOptions).
- Why (grounded in the shipped API): feature-specific
HttpContext extensions live in the feature's namespace, not the broad Microsoft.AspNetCore.Http one — of the 27 this HttpContext extension methods in the shipped public API, only 3 sit in Microsoft.AspNetCore.Http (core concepts like GetEndpoint/server variables); 20 are in Microsoft.AspNetCore.Authentication, 2 in Microsoft.AspNetCore.Routing, and the closest Blazor precedent — AcceptsInteractiveRouting — is in Microsoft.AspNetCore.Components.Routing. Placing this helper in the broad HTTP namespace would surface it on every HttpContext via IntelliSense.
What's already right
WithBrowserConfiguration(this RazorComponentsEndpointConventionBuilder, Action<…>) is the correct entry point: it's an endpoint-builder extension, so Microsoft.AspNetCore.Builder is the right namespace and returning the same builder follows the With* convention. (Only a consistency rename to track the options type — e.g. WithBrowserOptions/configureOptions — would be needed.)
Note on the serialized format
The <!--Blazor-Configuration:{}--> payload is effectively a wire format; consider treating its schema as versioned/internal so future changes aren't breaking, as called out in the proposal's Risks.
Filed as consolidated API-review feedback for #66393.
Review feedback on the public API proposed in #66393 (
BrowserConfigurationfor server-to-client configuration). Overall the feature is welcome and justified — Blazor apps commonly need server-authored browser boot options across render modes, and the current mechanisms are fragmented. The notes below are shape/placement suggestions; the endpoint-builder entry point is already in good shape.Need / scenarios
IHostEnvironment, logging options, request culture, and endpoint/middleware configuration.Recommended shape changes
BrowserConfiguration(the root model)BrowserOptions— it's an options bag; theOptionssuffix matches the rest of ASP.NET Core and avoids confusion withIConfiguration.LogLevel: useMicrosoft.Extensions.Logging.LogLevel?instead ofint?— the usage example passes a magic integer (LogLevel = 2 // Warning); a strongly-typed enum prevents that.Server/Ssr/WebAssemblyproperties non-null and initialized (get-only). The proposed usageconfig.Server.ReconnectionMaxRetries = 10NREs unless each sub-object is pre-allocated — a pit-of-failure for the common path.ServerBrowserOptionsInteractiveServerBrowserOptions— here "Server" means interactive server rendering, not static SSR or the physical server; aligning with Blazor render-mode vocabulary avoids ambiguity.ReconnectionRetryIntervalMilliseconds→ReconnectionRetryIntervalof typeTimeSpan?. Public .NET options express durations asTimeSpan; the serialized browser format can still use milliseconds internally.SsrBrowserOptionsCircuitInactivityTimeoutMs→CircuitInactivityTimeout(TimeSpan?).DisableDomPreservation→ positivePreserveDom(public options prefer positiveEnable*/Allow*/Preserve*overDisable*; nullable still distinguishes "unset").WebAssemblyBrowserOptionsEnvironmentVariables: expose as a non-null, initializedIDictionary<string, string>(get-only) rather than a settable concreteDictionary<,>— avoids handing out a concrete type and avoids a null collection on the common path.ConfigureBrowser(component)[Parameter](and[EditorRequired]on the required options) — component parameters need their attributes visible in the API shape and bound by the runtime.Configuration→Optionsfor consistency with the renamed model.HttpContextas a[CascadingParameter](infrastructure that's absent once execution moves to the browser), not a normal settable parameter.BrowserConfigurationHttpContextExtensions(theHttpContextaccessor)Microsoft.AspNetCore.Httpinto the Blazor feature namespace, and rename to match the options type (GetBrowserOptions).HttpContextextensions live in the feature's namespace, not the broadMicrosoft.AspNetCore.Httpone — of the 27this HttpContextextension methods in the shipped public API, only 3 sit inMicrosoft.AspNetCore.Http(core concepts likeGetEndpoint/server variables); 20 are inMicrosoft.AspNetCore.Authentication, 2 inMicrosoft.AspNetCore.Routing, and the closest Blazor precedent —AcceptsInteractiveRouting— is inMicrosoft.AspNetCore.Components.Routing. Placing this helper in the broad HTTP namespace would surface it on everyHttpContextvia IntelliSense.What's already right
WithBrowserConfiguration(this RazorComponentsEndpointConventionBuilder, Action<…>)is the correct entry point: it's an endpoint-builder extension, soMicrosoft.AspNetCore.Builderis the right namespace and returning the same builder follows theWith*convention. (Only a consistency rename to track the options type — e.g.WithBrowserOptions/configureOptions— would be needed.)Note on the serialized format
The
<!--Blazor-Configuration:{}-->payload is effectively a wire format; consider treating its schema as versioned/internal so future changes aren't breaking, as called out in the proposal's Risks.Filed as consolidated API-review feedback for #66393.