dotnet / dotnet/aspnetcore

[Validation] Setting BrowserOptions from server code

Open
#68,815 4 comments 0 reactions 1 assignee Claimed by @irfanajaffer View on GitHub
area-blazor Validation validation-scenario
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 6h
Merged PRs (30d)
290

Description

**Scenario contact:** @javiercn

## Scenario

Settings that govern how a Blazor app behaves in the browser, such as how noisy its logging is and how hard it tries to reconnect after losing its connection, have traditionally been written in JavaScript at the bottom of a page. That puts them out of reach of configuration files, feature flags and anything that varies per request. This validates that those settings can be decided in server code instead, including differently for different visitors.

## Minimum build

.NET 11 RC1 or later.

## Configurations to cover

* Blazor Web App
* [x] Static SSR
* [x] Interactive Server
* [ ] Interactive WebAssembly
* [x] Interactive Auto
* [ ] Standalone WebAssembly
* [ ] Hybrid (MAUI)

## Also exercise

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

## Setup

You need to be able to stop and restart the server while the browser stays open, so you can watch what happens to a live app when its connection drops and comes back.

Two places set these options, and both are worth covering:

* `MapRazorComponents().WithBrowserOptions(...)` in server startup, which applies to the whole endpoint.
* A `` component in the page, which can vary per request.

`BrowserOptions.GetBrowserOptions(httpContext)` reads what is currently in effect.

## What to build

An app whose browser-side behavior is decided in server code rather than in a script on the page. Through `WithBrowserOptions`, set `LogLevel`, and set `InteractiveServer.ReconnectionMaxRetries` and `InteractiveServer.ReconnectionRetryInterval` to something clearly different from the default, such as far fewer attempts spaced further apart. Point `InteractiveServer.ReconnectionDialogId` at reconnection UI of your own so you can tell yours from the built-in one.

Then add a `` in the page that varies some of these by request, for example turning detailed logging on only for requests carrying a particular query string or header, or only for a signed-in administrator, so you can compare two browsers side by side.

Add a page whose content changes when you navigate to it, and drive `StaticServer.PreserveDom` from the server, so you can see the effect of DOM preservation being switched off.

## Things to try

* Loading the app and watching the browser console for the amount of logging you asked for.
* Loading it again with the condition that turns on detailed logging, and comparing.
* Opening two browsers at once, one meeting the condition and one not.
* Stopping the server while the app is open, and watching the reconnection attempts and your own reconnection dialog.
* Restarting the server and seeing whether the app recovers.
* Stopping it for longer than your reconnection settings allow, so the attempts run out.
* Navigating between pages with `StaticServer.PreserveDom` set to `true` and to `false`.
* Setting an option at the endpoint and overriding it per request with ``, to see which wins.
* Reading back the values with `BrowserOptions.GetBrowserOptions(httpContext)` and comparing them with what the browser actually did.
* Removing the server-side settings entirely to confirm the defaults return.

## Expected behavior

Options set in server code reach the browser, and options that vary by request vary independently for each visitor.

### Must hold

* The browser console shows the level set in `LogLevel`, not the default level.
* Reconnection follows `ReconnectionMaxRetries` and `ReconnectionRetryInterval` rather than the defaults, and the dialog named by `ReconnectionDialogId` is used instead of the built-in one.
* Two browsers loading the app at the same time, one meeting the request-based condition and one not, receive different settings.
* Setting `StaticServer.PreserveDom` to `false` visibly stops DOM preservation across enhanced navigation, and `true` restores it. This property is the inverse of the underlying option, so confirm the sense is not flipped.
* When the attempts run out, the app reaches the same end state it would have reached with the defaults.
* Removing the server-side configuration restores the default behavior with nothing left over.

### Expected differences between configurations

* Reconnection behavior is only observable in the configurations that keep a live connection to the server. In Interactive Auto it applies on the visits that run on the server.

## Documentation to use

* [ASP.NET Core Blazor startup](https://learn.microsoft.com/aspnet/core/blazor/fundamentals/startup?view=aspnetcore-11.0)
* [ASP.NET Core Blazor SignalR guidance](https://learn.microsoft.com/aspnet/core/blazor/fundamentals/signalr?view=aspnetcore-11.0)
* [ASP.NET Core Blazor logging](https://learn.microsoft.com/aspnet/core/blazor/fundamentals/logging?view=aspnetcore-11.0)

The API names above were taken from the shipped code, not from docs. If you cannot find this documented anywhere, say so in the report.

## What to report

Report results using the format described in the [validation testing manual](https://github.com/dotnet/aspnetcore/issues/68479). Include link to a repository with the test app.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.