dotnet / dotnet/aspnetcore

[Validation] Offloading work with the blazorwebworker template

Open
#68,818 1 comment 0 reactions 1 assignee Claimed by @Vinoth2562000 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:** @ilonatommy

## Scenario

Long-running .NET work on the browser's main thread freezes the UI: the page stops repainting, buttons stop responding, and the browser may offer to kill the tab. The `blazorwebworker` template scaffolds a client that moves that work onto a web worker so the page stays responsive. This validates that the template produces a working project, that the generated client offloads work as intended, and that the app stays usable while the worker is busy.

**It also validates that a reported bug is fixed.** A worker that ran correctly during development failed in the **published** app with `Unhandled exception rendering component: Worker encountered an error` in the browser console, because the worker could not resolve the fingerprinted framework files. Publishing is therefore not an optional extra here; it is where the bug lived. ([#65820](https://github.com/dotnet/aspnetcore/issues/65820))

## Minimum build

.NET 11 Preview 7 or later.

## Configurations to cover

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

Web workers only exist in the browser, so the worker is reachable only from client-side rendered code. Interactive Server and static SSR are out of scope.

## Also exercise

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

## Setup

Create the worker project with `dotnet new blazorwebworker`, and also from the template list in an IDE, since the rename from the old .NET Web Worker name is part of what is being validated. Reference it from a Blazor app that renders on the client.

## What to build

A Blazor app with a page that gives the user something to do while work is happening: a counter they can click, an input they can type into, or an animation. Reference a project created from the `blazorwebworker` template.

In the worker project, add `[JSExport]` methods next to the generated `Greet` sample: one that returns a value after several seconds of real computation, one that returns nothing, and one that throws. Then call them from the page through `WebWorkerClient`, using `InvokeAsync` for the first and `InvokeVoidAsync` for the second, and show the results on screen.

Add the same slow computation on the main thread as well, behind its own button, so you have a direct comparison.

## Things to try

* Running the slow work on the main thread and then in the worker, clicking the counter throughout both.
* **Publishing the app and running the published output.** This is the reported repro: the worker worked in development and failed once published, where framework files are fingerprinted. Do this early rather than last.
* Calling the method that returns nothing and confirming it ran.
* Calling the method that throws, and reading what reaches the .NET side.
* Several calls in flight at once.
* Disposing the client while a call is still running, and navigating away mid-call.
* Creating a second client on the same page.
* Publishing with trimming or ahead-of-time compilation enabled.
* Creating the project from the IDE template list as well as from the command line.

## Expected behavior

Work handed to the worker runs off the main thread, and the page stays usable while it does.

### Must hold

* `dotnet new blazorwebworker` creates a project that builds without edits, and the template is listed under that name in `dotnet new list` and in the IDE.
* While the worker is running the slow computation, the counter still increments and the page still repaints. Running the same computation on the main thread visibly blocks it.
* `InvokeAsync` returns the worker's value, and `InvokeVoidAsync` runs the method and completes without asking for one.
* An exception thrown inside the worker surfaces on the .NET side as a failure carrying a usable message, rather than hanging or failing silently.
* Disposing the client, and navigating away mid-call, produce no unhandled error in the browser console.
* The published app loads its worker successfully, with no failed request for framework files in the network log, and no `Worker encountered an error` message in the browser console.

### Expected differences between configurations

* No differences are expected between Standalone WebAssembly and a Blazor Web App's Interactive WebAssembly pages.

## Evidence to capture

A short screen recording showing the counter continuing to respond while the worker runs the slow computation, and the same counter freezing when the computation runs on the main thread.

## Documentation to use

* [New Blazor Web Worker template, .NET 11 release notes](https://learn.microsoft.com/aspnet/core/release-notes/aspnetcore-11#new-blazor-web-worker-template-blazorwebworker)
* [ASP.NET Core Blazor with .NET on web workers](https://learn.microsoft.com/aspnet/core/blazor/blazor-with-dotnet-on-web-workers?view=aspnetcore-11.0)

## 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.