[Extensibility] BlazorWebView: Add custom platform handler registration - #36658
Conversation
…4225) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ## Description Adds `IMauiBlazorWebViewBuilder.UsePlatformHandler<THandler>()` extension method that allows custom platform backends (e.g., Linux/GTK) to replace the default `BlazorWebViewHandler` while reusing all shared service registrations from `AddMauiBlazorWebView()`. ### Problem Custom platform backends cannot use `AddMauiBlazorWebView()` because it hardcodes the built-in `BlazorWebViewHandler`. They must bypass it entirely and duplicate all internal service registrations (JSInterop, navigation, static assets, etc.). ### Solution New extension method on `IMauiBlazorWebViewBuilder`: ```csharp builder.Services.AddMauiBlazorWebView() .UsePlatformHandler<GtkBlazorWebViewHandler>(); ``` This keeps all shared services from `AddMauiBlazorWebView()` while allowing the platform-specific handler to be swapped via `ConfigureMauiHandlers` + `AddHandler` (which replaces the prior registration). ### Changes - **New file**: `MauiBlazorWebViewBuilderExtensions.cs` — `UsePlatformHandler<THandler>()` extension method - **PublicAPI updates**: New API entry added to all 6 TFM PublicAPI.Unshipped.txt files - **Unit test**: Validates that a second `ConfigureMauiHandlers` call correctly replaces the handler Fixes dotnet#34103 --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit 21409fa)
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 36658Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 36658" |
|
Azure Pipelines: Successfully started running 1 pipeline(s). There may be pipelines that require an authorized user to comment /azp run to run. |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Pull request overview
Adds an extensibility point for MAUI Blazor Hybrid so custom platform backends can replace the default BlazorWebViewHandler without reimplementing AddMauiBlazorWebView() service registration, forward-ported to net11.0.
Changes:
- Introduces
IMauiBlazorWebViewBuilder.UsePlatformHandler<THandler>()andUsePlatformHandler(Func<IServiceProvider, IViewHandler>)to override theIBlazorWebViewhandler registration viaConfigureMauiHandlers. - Adds Core unit tests validating “last registration wins” behavior across multiple
ConfigureMauiHandlerscalls and factory-based handler registrations. - Adds device tests validating the new public API replaces the default BlazorWebView handler end-to-end, plus PublicAPI entries for all relevant TFMs.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/Core/tests/UnitTests/Hosting/HostBuilderHandlerTests.cs | Adds unit coverage proving handler registrations are replaceable (type + factory) across multiple ConfigureMauiHandlers calls. |
| src/BlazorWebView/tests/DeviceTests/Elements/BlazorWebViewTests.Services.cs | Adds device tests validating UsePlatformHandler overrides the default BlazorWebView handler in practice. |
| src/BlazorWebView/src/Maui/PublicAPI/net/PublicAPI.Unshipped.txt | Declares new public extension type + methods (net). |
| src/BlazorWebView/src/Maui/PublicAPI/net-windows/PublicAPI.Unshipped.txt | Declares new public extension type + methods (net-windows). |
| src/BlazorWebView/src/Maui/PublicAPI/net-tizen/PublicAPI.Unshipped.txt | Declares new public extension type + methods (net-tizen). |
| src/BlazorWebView/src/Maui/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt | Declares new public extension type + methods (net-maccatalyst). |
| src/BlazorWebView/src/Maui/PublicAPI/net-ios/PublicAPI.Unshipped.txt | Declares new public extension type + methods (net-ios). |
| src/BlazorWebView/src/Maui/PublicAPI/net-android/PublicAPI.Unshipped.txt | Declares new public extension type + methods (net-android). |
| src/BlazorWebView/src/Maui/MauiBlazorWebViewBuilderExtensions.cs | Implements the new UsePlatformHandler overloads with null guards and trimming annotations. |
|
🤖 AI-generated CI analysis (GitHub Copilot CLI, on behalf of @kubaflo).
All BlazorWebView-specific code/build tests and the remaining CI legs passed. No PR-caused failure was found; re-running CI. |
|
/azp run |
|
Azure Pipelines: Successfully started running 3 pipeline(s). |
|
🤖 AI-generated device-test analysis (GitHub Copilot CLI, on behalf of @kubaflo).
No PR-caused device-test failure was found. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
🤖 AI-generated CI analysis update (GitHub Copilot CLI, on behalf of @kubaflo). The newly completed iOS CollectionView failure in |
|
🤖 AI-generated CI analysis update (GitHub Copilot CLI, on behalf of @kubaflo). The two Image-category failures in UI build 1516322 also exactly match the |
|
🤖 AI-generated CI analysis update (GitHub Copilot CLI, on behalf of @kubaflo). UI build 1516322 is complete. Its final MacCatalyst CollectionView job exceeded the 180-minute job limit after |
|
/azp run |
This comment has been minimized.
This comment has been minimized.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 66f84348-6476-4097-8b7f-f240338e85c3
This comment has been minimized.
This comment has been minimized.
|
/azp run |
|
Azure Pipelines: Successfully started running 3 pipeline(s). |
|
Current-head CI evidence (builds still active): device build 1531528 currently has failed MacCatalyst CoreCLR, iOS Mono, and iOS CoreCLR legs. Current |
|
Updated device evidence for 1531528: Windows Helix completed with both MauiBlazorWebView packaged and unpackaged work items green; Core, Essentials, and Graphics also passed. Only baseline Controls packaged/unpackaged failed. The remaining failed platform job names match current |
|
Final UI 1531526 classification: |
|
/azp run maui-pr-uitests |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
|
Replacement UI 1531707 currently has one unrelated Android UI timeout: |
|
Final CI classification: main 1531521 is fully green. Windows device Helix confirms MauiBlazorWebView packaged/unpackaged passed; device reds are baseline Controls/platform jobs. UI replacement 1531707 has only current-base CollectionView/vlatest CollectionView, Material3 API36, and API30 Shell failures, plus the unrelated Issue32871 SafeArea element timeout and known cancellation/timeout infrastructure. Further reruns add no signal. CI is ready for the unrelated-red exception after human approval. |
Note
Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!
Description
Forward-ports #34225 to
net11.0and completes its custom-handler contract.Adds
IMauiBlazorWebViewBuilder.UsePlatformHandleroverloads for handlers implementing the newIBlazorWebViewHandlercapability interface:UsePlatformHandler<THandler>()for handlers with public parameterless constructors;UsePlatformHandler(Func<IServiceProvider, IBlazorWebViewHandler>)for handlers needing controlled construction.IBlazorWebViewHandlerexposes the two operations used byBlazorWebView: static-file-provider creation and scoped-service dispatch. This lets independent handlers work end-to-end without deriving from the built-inBlazorWebViewHandler. The built-in handler implements the capability explicitly, shared code no longer hard-casts to the concrete handler, and Windows teardown performs the required WebView2 cleanup based on the platform-view type for the built-in handler and custom handlers that expose WebView2 directly as their platform view. Custom handlers that wrap WebView2 instead are documented to close the owned control in their own disconnect logic.Both registration overloads replace the default handler through
ConfigureMauiHandlers. PublicAPI entries cover every MAUI TFM, and device tests use non-derived handlers to verify generic registration, UI-thread factory registration, file-provider creation, dispatch, and incompatible-handler diagnostics.Fixes #34103
Part of #34099
Testing
Microsoft.AspNetCore.Components.WebView.Maui.csprojnet11.0build with PublicAPI analyzers: passedCategory=BlazorWebView: 26 passed, 0 failed, 1 ignoredUsePlatformHandlerGenericReplacesDefaultBlazorWebViewHandlerUsePlatformHandlerFactoryReplacesDefaultBlazorWebViewHandlerBlazorWebViewUsesCustomHandlerOperationsThe remaining Android category tests timed out waiting for the emulator's WebView/Blazor runtime to initialize and did not involve the custom-handler path.