Support hosted services in WebAssemblyHost#63814
Conversation
Co-authored-by: javiercn <6995051+javiercn@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR adds hosted service (IHostedService) lifecycle management to WebAssemblyHost, enabling Blazor WebAssembly applications to use background services automatically. This addresses the limitation where services registered with AddHostedService were previously ignored in WebAssembly applications, and was specifically requested to support libraries like OpenTelemetry that rely on hosted services.
Key changes:
- Hosted services are automatically started during
RunAsyncCore()after component state restoration - Hosted services are stopped during
DisposeAsync()with error aggregation and logging - Added dependency on
Microsoft.Extensions.Hosting.Abstractionsto enableIHostedServicesupport
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/Components/WebAssembly/WebAssembly/src/Microsoft.AspNetCore.Components.WebAssembly.csproj |
Adds reference to Microsoft.Extensions.Hosting.Abstractions package |
src/Components/WebAssembly/WebAssembly/src/Hosting/WebAssemblyHost.cs |
Implements hosted service lifecycle with start/stop methods and disposal integration |
src/Components/WebAssembly/WebAssembly/test/Microsoft.AspNetCore.Components.WebAssembly.Tests.csproj |
Adds reference to Microsoft.Extensions.Hosting.Abstractions for test project |
src/Components/WebAssembly/WebAssembly/test/Hosting/WebAssemblyHostTest.cs |
Adds comprehensive tests for hosted service startup, shutdown, and error handling scenarios |
You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.
| var logger = Services.GetService<ILogger<WebAssemblyHost>>(); | ||
| logger?.LogError(ex, "An error occurred stopping hosted services during disposal."); |
There was a problem hiding this comment.
Consider using the LoggerMessage source generator pattern for structured logging. The codebase convention in WebAssemblyRenderer and WebAssemblyNavigationManager uses partial static Log classes with [LoggerMessage] attributes for better performance and consistency. Add a private static partial class Log with a LoggerMessage method for this error.
There was a problem hiding this comment.
Updated to use LoggerMessage source generator pattern with a private static partial Log class. Changes in commit d8752fb.
| } | ||
|
|
||
| // Throw an aggregate exception if there were any exceptions | ||
| if (exceptions is not null) |
There was a problem hiding this comment.
[nitpick] The condition check uses is not null which is correct according to nullable reference type conventions. However, the HostedServiceExecutor in src/Hosting/Hosting/src/Internal/HostedServiceExecutor.cs:43 uses != null for the same pattern. Consider using is not null consistently for better code alignment with C# null pattern matching practices, which this codebase already follows (see line 84, 105).
Co-authored-by: javiercn <6995051+javiercn@users.noreply.github.com>
src/Components/WebAssembly/WebAssembly/src/Hosting/WebAssemblyHost.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: javiercn <6995051+javiercn@users.noreply.github.com>
src/Components/WebAssembly/WebAssembly/src/Hosting/WebAssemblyHost.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: javiercn <6995051+javiercn@users.noreply.github.com>
This PR adds support for hosted services (
IHostedService) inWebAssemblyHost, enabling automatic startup and shutdown of background services in Blazor WebAssembly applications.Description
Applications using
WebAssemblyHost(e.g. Blazor WebAssembly clients) did not support hosted services out of the box. Services registered withAddHostedServicewere ignored when usingWebAssemblyHostBuilder, unlike in applications built withWebApplicationBuilderorHostApplicationBuilder. This prevented libraries like OpenTelemetry from working properly in Blazor WebAssembly apps, as they rely on hosted services for initialization.The implementation adds hosted service lifecycle management to
WebAssemblyHost:IHostedServiceimplementations from the DI containerRunAsyncCore()after component state restorationDisposeAsync()with proper error handlingWebAssemblyHostsimply resolves the executor from DI and calls it at the appropriate times, maintaining clean separation of concernsUsage
Developers can now register hosted services in Blazor WebAssembly apps:
Implementation Details
Microsoft.Extensions.Hosting.Abstractionsreference to enableIHostedServicesupportHostedServiceExecutorclass in the WebAssembly project to encapsulate hosted service lifecycle managementHostedServiceExecutoras a singleton in DI inWebAssemblyHostBuilder.InitializeDefaultServices()HostedServiceExecutoracceptsILogger<HostedServiceExecutor>and handles all exception aggregation and logging internallyWebAssemblyRendererandWebAssemblyNavigationManagerWebAssemblyHostresolves the executor from DI and coordinates its invocation at the right timesTesting
Added comprehensive test coverage:
All existing WebAssemblyHost functionality remains unchanged and all tests pass.
Original prompt
💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.