Skip to content

Add UsePlatformHandler<T> for custom BlazorWebView backends - #34225

Merged
kubaflo merged 7 commits into
inflight/currentfrom
dev/redth/fix-34103
Jun 7, 2026
Merged

Add UsePlatformHandler<T> for custom BlazorWebView backends#34225
kubaflo merged 7 commits into
inflight/currentfrom
dev/redth/fix-34103

Conversation

@Redth

@Redth Redth commented Feb 25, 2026

Copy link
Copy Markdown
Member

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

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:

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

Adds IMauiBlazorWebViewBuilder.UsePlatformHandler<THandler>() extension
method that allows custom platform backends to replace the default
BlazorWebViewHandler while reusing all shared service registrations
from AddMauiBlazorWebView().

This enables scenarios like:
  builder.Services.AddMauiBlazorWebView()
      .UsePlatformHandler<GtkBlazorWebViewHandler>();

Fixes #34103

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings February 25, 2026 01:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new MAUI BlazorWebView builder extension to allow custom platform backends (e.g., Linux/GTK) to override the default BlazorWebViewHandler while keeping the shared service registrations from AddMauiBlazorWebView().

Changes:

  • Introduces IMauiBlazorWebViewBuilder.UsePlatformHandler<THandler>() to register a custom IBlazorWebView handler via ConfigureMauiHandlers.
  • Updates PublicAPI files to declare the new public extension type and method.
  • Adds a core unit test asserting that a second ConfigureMauiHandlers call replaces an earlier handler registration.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/BlazorWebView/src/Maui/MauiBlazorWebViewBuilderExtensions.cs Adds the new UsePlatformHandler<THandler>() public extension method.
src/BlazorWebView/src/Maui/PublicAPI/net/PublicAPI.Unshipped.txt Declares the new public extension type + method in PublicAPI.
src/BlazorWebView/src/Maui/PublicAPI/net-android/PublicAPI.Unshipped.txt Declares the new public extension type + method in PublicAPI (Android TFM).
src/BlazorWebView/src/Maui/PublicAPI/net-ios/PublicAPI.Unshipped.txt Declares the new public extension type + method in PublicAPI (iOS TFM).
src/BlazorWebView/src/Maui/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt Declares the new public extension type + method in PublicAPI (MacCatalyst TFM).
src/BlazorWebView/src/Maui/PublicAPI/net-tizen/PublicAPI.Unshipped.txt Declares the new public extension type + method in PublicAPI (Tizen TFM).
src/BlazorWebView/src/Maui/PublicAPI/net-windows/PublicAPI.Unshipped.txt Declares the new public extension type + method in PublicAPI (Windows TFM).
src/Core/tests/UnitTests/Hosting/HostBuilderHandlerTests.cs Adds a test asserting later ConfigureMauiHandlers registrations override earlier ones.

Comment thread src/Core/tests/UnitTests/Hosting/HostBuilderHandlerTests.cs Outdated
Comment thread src/BlazorWebView/src/Maui/MauiBlazorWebViewBuilderExtensions.cs Outdated
…t stub type

- Constrain UsePlatformHandler<THandler> to IViewHandler instead of
  IElementHandler since it registers for IBlazorWebView (an IView)
- Replace AlternateButtonHandlerStub with AlternateViewHandlerStub
  in test to match the IViewStub registration type

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

github-actions Bot commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 34225

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 34225"

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Comment on lines +22 to +28
public static IMauiBlazorWebViewBuilder UsePlatformHandler<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] THandler>(
this IMauiBlazorWebViewBuilder builder)
where THandler : IViewHandler
{
builder.Services.ConfigureMauiHandlers(handlers =>
handlers.AddHandler<IBlazorWebView, THandler>());
return builder;

Copilot AI Mar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UsePlatformHandler<THandler>() registers the handler via handlers.AddHandler<IBlazorWebView, THandler>(), which ultimately creates handler instances using Activator.CreateInstance(ImplementationType) in MauiFactory. This requires THandler to have a public parameterless constructor; otherwise it will fail at runtime with a MissingMethodException. Consider enforcing this contract with a new() generic constraint, or switch to the factory overload (AddHandler<TType>(Func<IServiceProvider, IElementHandler>)) so handlers with non-parameterless constructors can be created safely.

Copilot uses AI. Check for mistakes.
@MauiBot

This comment has been minimized.

@MauiBot MauiBot added s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-win AI found a better alternative fix than the PR s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Mar 23, 2026
Redth and others added 2 commits April 1, 2026 19:07
- Add new() constraint to UsePlatformHandler<THandler>() to make the
  public parameterless constructor requirement explicit at compile time
- Add factory-based UsePlatformHandler(Func<IServiceProvider, IElementHandler>)
  overload for handlers that need dependency injection
- Add ArgumentNullException.ThrowIfNull guard on factory parameter
- Update all 6 TFM PublicAPI.Unshipped.txt files with new overload
- Add FactoryBasedHandlerRegistrationReplacesHandler test

Addresses review comment about Activator.CreateInstance requiring
parameterless constructors and MauiBot recommendation for DI-friendly
handler activation path.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

github-actions Bot commented Apr 1, 2026

Copy link
Copy Markdown
Contributor

🧪 PR Test Evaluation

Overall Verdict: ⚠️ Tests need improvement

The tests verify the underlying handler replacement mechanism but don't directly exercise the new UsePlatformHandler extension methods that form the actual public API surface of this PR.

👍 / 👎 — Was this evaluation helpful? React to let us know!

📊 Expand Full Evaluation

PR Test Evaluation Report

PR: #34225 — Add UsePlatformHandler extension method for IMauiBlazorWebViewBuilder
Test files evaluated: 1 (HostBuilderHandlerTests.cs)
Fix files: 1 (MauiBlazorWebViewBuilderExtensions.cs)


Overall Verdict

⚠️ Tests need improvement

The two new unit tests validate the general handler-replacement plumbing (that ConfigureMauiHandlers and factory-based AddHandler overwrite earlier registrations) but never call the new UsePlatformHandler extension methods that are the actual public API added by this PR.


1. Fix Coverage — ⚠️ Partial

The PR introduces two new public extension methods on IMauiBlazorWebViewBuilder:

  • UsePlatformHandler(THandler)() — generic, new() constraint
  • UsePlatformHandler(factory) — factory-based overload

Neither method is called in the tests. The two new tests exercise ConfigureMauiHandlers + AddHandler directly on MauiApp.CreateBuilder(), which is the underlying infrastructure the extension methods rely on — but that infrastructure is already tested by the many existing tests in the same file. The fix-specific surface (i.e. calling UsePlatformHandler on IMauiBlazorWebViewBuilder) is not covered.

If the implementation of UsePlatformHandler had a typo (e.g., AddHandler was accidentally called with the wrong type), the existing tests would still pass.

2. Edge Cases & Gaps — ⚠️ Gaps present

Covered (by the two new tests):

  • Calling ConfigureMauiHandlers twice replaces a type-mapped handler
  • Calling ConfigureMauiHandlers with a factory lambda replaces a type-mapped handler

Missing:

  • UsePlatformHandler(THandler)() is never called — no test verifies it registers IBlazorWebViewTHandler
  • UsePlatformHandler(factory) is never called — no test verifies the factory overload registers the correct mapping for IBlazorWebView
  • Null guardArgumentNullException.ThrowIfNull(factory) exists in the factory overload but is not tested; a quick [Fact] calling builder.UsePlatformHandler(null!) and expecting ArgumentNullException would confirm it
  • Ordering — no test verifies that calling UsePlatformHandler after AddMauiBlazorWebView actually replaces the default BlazorWebViewHandler (the intended use case described in the XML docs)

3. Test Type Appropriateness — ✅ Correct type

Current: Unit tests (xUnit [Fact])
Recommendation: Same — handler registration and DI wiring is pure logic, no platform context needed. Unit tests are exactly the right choice here.

The new extension methods should also be tested as unit tests (not device or UI tests).

4. Convention Compliance — ✅ Pass

  • [Fact] attributes used correctly
  • Descriptive method names (SecondConfigureMauiHandlersCallReplacesHandler, FactoryBasedHandlerRegistrationReplacesHandler)
  • Inner AlternateViewHandlerStub class is a clean, minimal stub
  • No anti-patterns detected by the automated script

5. Flakiness Risk — ✅ Low

Pure in-memory DI tests with no async, no timers, no platform interaction. These tests are inherently deterministic.

6. Duplicate Coverage — ⚠️ Potential overlap

The "second call replaces handler" and "factory replaces type handler" behaviors are variants of patterns already well-exercised by the ~17 existing tests in HostBuilderHandlerTests.cs. The new tests aren't redundant (they confirm specific overload combinations), but without also testing UsePlatformHandler directly, the new tests mostly re-verify infrastructure that was already working — adding little incremental confidence.

7. Platform Scope — ⚠️ Concern

The fix file is cross-platform. Unit tests run on all platforms by default (no TFM restriction in the unit test project), so the tests do exercise the fix on all platforms where the handler registration mechanism matters. However, since MauiBlazorWebViewBuilderExtensions is scoped to the BlazorWebView namespace and registered handlers are platform-specific, a brief device test or a test that spins up a real MAUI host with AddMauiBlazorWebView().UsePlatformHandler(MyCustomHandler)() and resolves the handler would give stronger confidence on each platform.

This is a minor concern — unit tests are sufficient for the DI wiring logic.

8. Assertion Quality — ✅ Good (for what is tested)

Assert.NotNull(handlerService);
Assert.IsType(AlternateViewHandlerStub)(handlerService);

Both assertions are specific: they verify the exact concrete type returned, not just non-null. If the replacement failed, Assert.IsType would catch it.

9. Fix-Test Alignment — ❌ Misaligned

Fix Test
MauiBlazorWebViewBuilderExtensions.UsePlatformHandler(THandler)() Not tested
MauiBlazorWebViewBuilderExtensions.UsePlatformHandler(factory) Not tested
handlers.AddHandler(IBlazorWebView, THandler)() called internally Tested indirectly (generic overload on different types)
handlers.AddHandler(IBlazorWebView)(factory) called internally Tested indirectly (factory overload on different types)

The test file is in Core.UnitTests while the fix is in BlazorWebView. The tests verify the Core handler infrastructure — not the BlazorWebView-specific extension methods. If the IBlazorWebView type mapping were accidentally omitted from UsePlatformHandler, no test would catch it.


Recommendations

  1. Add direct tests for UsePlatformHandler — Create a test that calls builder.Services.AddMauiBlazorWebView(b => b.UsePlatformHandler(CustomHandlerStub)()), builds the app, resolves the handler for IBlazorWebView, and asserts it is a CustomHandlerStub. Repeat for the factory overload.

  2. Test the null guard — Add a [Fact] asserting ArgumentNullException is thrown when null is passed to the factory overload.

  3. Consider a "replaces default" test — Verify that UsePlatformHandler specifically overwrites the BlazorWebViewHandler that AddMauiBlazorWebView registers by default, since that is the primary use-case described in the XML docs.

Warning

⚠️ Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • dc.services.visualstudio.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "dc.services.visualstudio.com"

See Network Configuration for more information.

Note

🔒 Integrity filtering filtered 1 item

Integrity filtering activated and filtered the following item during workflow execution.
This happens when a tool call accesses a resource that does not meet the required integrity or secrecy level of the workflow.

🧪 Test evaluation by Evaluate PR Tests

- Add ArgumentNullException.ThrowIfNull(builder) to both overloads
  for consistent null validation
- Change factory overload parameter from Func<IServiceProvider, IElementHandler>
  to Func<IServiceProvider, IViewHandler> for type safety consistency
  with the generic overload's IViewHandler constraint
- Update PublicAPI files to reflect the tighter factory signature

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Redth

Redth commented Apr 1, 2026

Copy link
Copy Markdown
Member Author

Review Feedback Addressed

Pushed two commits to address all review feedback:

Commit 1: 1da8458 — Core feedback from inline reviews

  • new() constraint added to UsePlatformHandler<THandler>() — makes the public parameterless constructor requirement compile-time enforced, addressing the Copilot reviewer comment about Activator.CreateInstance failing at runtime
  • Factory-based overload addedUsePlatformHandler(Func<IServiceProvider, IViewHandler> factory) for handlers that need DI or lack a parameterless constructor, addressing MauiBot recommendation for DI-friendly handler activation
  • ArgumentNullException.ThrowIfNull guard on factory parameter
  • All 6 TFM PublicAPI files updated with new overload
  • New test FactoryBasedHandlerRegistrationReplacesHandler verifying factory-based handler replacement

Commit 2: f7e68c1 — Multi-model review fixes

  • builder null checks added to both overloads for consistent argument validation
  • Factory parameter tightened from Func<IServiceProvider, IElementHandler> to Func<IServiceProvider, IViewHandler> — ensures type safety consistency between the generic and factory overloads (both now require IViewHandler)

Summary of review findings addressed

Finding Source Status
Constructor activation trap (missing new()) Copilot inline review ✅ Fixed
No DI-friendly registration path MauiBot AI review ✅ Fixed (factory overload)
Missing builder null checks Multi-model consensus ✅ Fixed
IElementHandler vs IViewHandler mismatch Multi-model consensus ✅ Fixed

All builds pass. All 25 handler tests pass (including 2 new tests).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

Copilot AI added 2 commits May 7, 2026 20:50
Three reviewers (Claude Opus 4.7-xhigh, Claude Sonnet 4.6, GPT-5.5) flagged two
shared concerns on the new UsePlatformHandler API:

1. Tests don't actually call UsePlatformHandler. The two existing
   HostBuilderHandlerTests prove the underlying ConfigureMauiHandlers replacement
   mechanism with stub types but never exercise the new public BlazorWebView API
   surface. A typo in MauiBlazorWebViewBuilderExtensions (wrong type argument,
   wrong service type, missing closure capture) would not be caught.

2. The XML doc on the factory overload claims it 'supports handlers that require
   dependency injection,' but the IServiceProvider passed by MauiFactory to the
   factory delegate is the MauiHandlersFactory itself — not the application's
   root IServiceProvider. It can resolve handler-collection services only.

This commit:

* Adds two direct device-test Facts in BlazorWebViewTests.Services.cs that call
  AddMauiBlazorWebView().UsePlatformHandler<T>() / .UsePlatformHandler(factory)
  and assert the IBlazorWebView handler resolves to the custom type. The stub
  inherits BlazorWebViewHandler so it satisfies IViewHandler/new() on every
  device-test target without reimplementing the handler surface.
* Tightens the XML docs on both overloads with a <remarks> block explaining the
  last-registration-wins ordering rule (call after AddMauiBlazorWebView, and
  call last when downstream libraries may re-invoke AddMauiBlazorWebView).
* Clarifies the factory-overload contract so readers don't expect arbitrary
  app-level DI to flow through the factory delegate's IServiceProvider.

No public API surface changes — only XML docs and tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
GPT-5.5 reviewer caught a build-breaking CS1574 introduced by the previous
commit's <remarks> block: the file does not 'using
Microsoft.Extensions.DependencyInjection;', so '<see cref="IServiceCollection"/>'
fails to resolve and breaks docs compilation.

Fully qualify the cref to match the file's existing pattern (see the cref to
BlazorWebViewServiceCollectionExtensions.AddMauiBlazorWebView elsewhere in this
file, which uses 'M:Microsoft.Extensions.DependencyInjection.BlazorWebViewServiceCollectionExtensions...').

Verified: 'dotnet build src/BlazorWebView/src/Maui/Microsoft.AspNetCore.Components.WebView.Maui.csproj
-f net10.0' now succeeds with 0 warnings, 0 errors.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@kubaflo

kubaflo commented May 7, 2026

Copy link
Copy Markdown
Contributor

🤖 Multi-Model Code Review — Round 2 Convergence

I ran an adversarial multi-model code review of this PR using three top-tier reviewers in parallel: Claude Opus 4.7 (xhigh reasoning), Claude Sonnet 4.6, and GPT-5.5. Each followed the code-review skill's independence-first workflow (read code before PR narrative, full source files not just diffs, MAUI-specific 30-dimension checklist, devil's-advocate pass).

Round 1 — divergent findings

Reviewer Verdict Key concerns
Opus 4.7 xhigh LGTM (3 💡) Document call-order requirement; tests don't exercise the new public API; optional null-guard test
Sonnet 4.6 NEEDS_CHANGES (2 ⚠️ + 2 💡) Tests don't directly call UsePlatformHandler; XML docs don't warn about double-registration hazard if a downstream library re-calls AddMauiBlazorWebView()
GPT-5.5 NEEDS_DISCUSSION (2 ⚠️ + 1 💡) Factory overload XML doc claim "supports handlers that require dependency injection" is misleading — the IServiceProvider passed to the factory is the MauiHandlersFactory itself, not the app's root SP (verified against MauiFactory.cs:60-61)

Multi-model agreement: all three reviewers independently flagged that the new tests verified the underlying ConfigureMauiHandlers replacement mechanism with stub types but never exercised the new UsePlatformHandler public API surface end-to-end.

Fixes applied

a41994f381 — Address multi-model code-review feedback:

  • MauiBlazorWebViewBuilderExtensions.cs — XML doc updates only (no API surface change):
    • Both overloads got <remarks> blocks describing the last-registration-wins ordering rule (call after AddMauiBlazorWebView(); call last when downstream libraries may re-invoke).
    • Factory overload's "supports dependency injection" claim was rewritten to clarify the IServiceProvider is the MAUI handler factory's SP and can only resolve handler-collection services.
  • BlazorWebViewTests.Services.cs — added 2 direct device tests + 1 stub:
    • UsePlatformHandlerGenericReplacesDefaultBlazorWebViewHandler — calls AddMauiBlazorWebView().UsePlatformHandler<CustomBlazorWebViewHandlerStub>() and asserts IMauiHandlersFactory.GetHandlerType(typeof(BlazorWebView)) == typeof(CustomBlazorWebViewHandlerStub).
    • UsePlatformHandlerFactoryReplacesDefaultBlazorWebViewHandler — exercises the factory overload, asserts factory invocation AND GetHandler(typeof(BlazorWebView)) returns the stub instance.
    • CustomBlazorWebViewHandlerStub : BlazorWebViewHandler — minimal stub inheriting the real handler so IViewHandler/new() is satisfied on every device-test target framework.

f146082ab0 — Fix unresolved cref to IServiceCollection:

  • GPT-5.5 (the only reviewer that actually built the project) caught a CS1574 introduced by the previous commit — <see cref="IServiceCollection"/> could not resolve because the file does not import Microsoft.Extensions.DependencyInjection. Fully qualified the cref to match the existing pattern in the same file.
  • Verified clean: dotnet build src/BlazorWebView/src/Maui/Microsoft.AspNetCore.Components.WebView.Maui.csproj -f net10.0 → 0 warnings, 0 errors.

Round 2 — convergence

Reviewer Verdict Notes
Opus 4.7 xhigh LGTM (high) All concerns addressed; surgical doc updates; tests verified end-to-end against the actual MauiHandlersFactory / RegisteredHandlerServiceTypeSet resolution path
Sonnet 4.6 LGTM (high) Both ⚠️ Warnings resolved; new tests are well-formed and compile across all device-test TFMs
GPT-5.5 (after cref fix verified) LGTM Build is clean; doc rewording is accurate; gh pr checks 34225 shows no failures

Final consensus: ✅ LGTM across all three models with high confidence.

Final PR state

  • 9 files / +179 / -0 (1 production file, 6 PublicAPI files, 2 test files)
  • No public API surface change in the second commit (XML docs only)
  • All 3 reviewers verified the new tests actually exercise both UsePlatformHandler overloads end-to-end against the real IBlazorWebView/BlazorWebView types

Items intentionally not addressed

  • 💡 Naming (UsePlatformHandler vs UseHandler / UseBlazorWebViewHandler) — Sonnet flagged this as a soft nit. The author has retained the name; both Anthropic models considered this non-blocking and consistent with Microsoft.Extensions.Hosting-style fluent builder conventions.
  • 💡 Optional null-guard test for the factory overload — runtime guard via ArgumentNullException.ThrowIfNull(factory) is in place; explicit test deemed not worth the noise.

Per code-review SKILL.md: I'm only posting a comment — never --approve or --request-changes. Approval is a human decision.

Reviewed with Claude Opus 4.7 (xhigh) + Claude Sonnet 4.6 + GPT-5.5 in parallel via the GitHub Copilot CLI multi-model review workflow.

@kubaflo

kubaflo commented May 7, 2026

Copy link
Copy Markdown
Contributor

/azp run maui-pr-uitests, maui-pr-devicetests

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 2 pipeline(s).

MauiBot

This comment was marked as outdated.

@MauiBot MauiBot added s/agent-review-incomplete and removed s/agent-changes-requested AI agent recommends changes - found a better alternative or issues labels May 24, 2026
@kubaflo

kubaflo commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

/review -b feature/enhanced-reviewer -p android

@MauiBot MauiBot added s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates and removed s/agent-fix-win AI found a better alternative fix than the PR labels Jun 7, 2026

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Review Summary

@Redth — new AI review results are available based on this last commit: f146082.
Fix unresolved cref to IServiceCollection in XML doc To request a fresh review after new comments or commits, comment /review rerun.

Gate Failed Code Review In Review Confidence High Platform Android

Review Sessions — click to expand
Gate — Test Before & After Fix

Gate Result: ❌ FAILED

Platform: ANDROID · Base: main · Merge base: e904e900

🩺 Fix breaks tests — one or more tests fail with the fix applied, and none of the failures are resolved by the fix.

Test Without Fix (expect FAIL) With Fix (expect PASS)
📱 BlazorWebViewTests (UsePlatformHandlerGenericReplacesDefaultBlazorWebViewHandler, UsePlatformHandlerFactoryReplacesDefaultBlazorWebViewHandler) Category=BlazorWebView ✅ FAIL — 983s ❌ FAIL — 958s
🧪 HostBuilderHandlerTests HostBuilderHandlerTests ❌ PASS — 157s ✅ PASS — 21s
🔴 Without fix — 📱 BlazorWebViewTests (UsePlatformHandlerGenericReplacesDefaultBlazorWebViewHandler, UsePlatformHandlerFactoryReplacesDefaultBlazorWebViewHandler): FAIL ✅ · 983s

(truncated to last 15,000 chars)

AndroidX.Navigation.Runtime.Android.dll -> Xamarin.AndroidX.Navigation.Runtime.Android.dll.so
  [58/137] Xamarin.AndroidX.Navigation.UI.dll -> Xamarin.AndroidX.Navigation.UI.dll.so
  [59/137] Xamarin.AndroidX.RecyclerView.dll -> Xamarin.AndroidX.RecyclerView.dll.so
  [60/137] Xamarin.AndroidX.SavedState.SavedState.Android.dll -> Xamarin.AndroidX.SavedState.SavedState.Android.dll.so
  [136/137] Mono.Android.dll -> Mono.Android.dll.so
  [61/137] Xamarin.AndroidX.SwipeRefreshLayout.dll -> Xamarin.AndroidX.SwipeRefreshLayout.dll.so
  [62/137] Xamarin.AndroidX.ViewPager.dll -> Xamarin.AndroidX.ViewPager.dll.so
  [63/137] Xamarin.AndroidX.ViewPager2.dll -> Xamarin.AndroidX.ViewPager2.dll.so
  [64/137] Xamarin.Google.Android.Material.dll -> Xamarin.Google.Android.Material.dll.so
  [65/137] Xamarin.Kotlin.StdLib.dll -> Xamarin.Kotlin.StdLib.dll.so
  [66/137] Xamarin.KotlinX.Coroutines.Core.Jvm.dll -> Xamarin.KotlinX.Coroutines.Core.Jvm.dll.so
  [67/137] Xamarin.KotlinX.Serialization.Core.Jvm.dll -> Xamarin.KotlinX.Serialization.Core.Jvm.dll.so
  [68/137] xunit.abstractions.dll -> xunit.abstractions.dll.so
  [69/137] xunit.assert.dll -> xunit.assert.dll.so
  [70/137] xunit.core.dll -> xunit.core.dll.so
  [71/137] xunit.execution.dotnet.dll -> xunit.execution.dotnet.dll.so
  [72/137] xunit.runner.utility.netcoreapp10.dll -> xunit.runner.utility.netcoreapp10.dll.so
  [137/137] System.Private.CoreLib.dll -> System.Private.CoreLib.dll.so
  [73/137] System.Collections.Concurrent.dll -> System.Collections.Concurrent.dll.so
  [74/137] System.Collections.Immutable.dll -> System.Collections.Immutable.dll.so
  [75/137] System.Collections.NonGeneric.dll -> System.Collections.NonGeneric.dll.so
  [76/137] System.Collections.Specialized.dll -> System.Collections.Specialized.dll.so
  [77/137] System.Collections.dll -> System.Collections.dll.so
  [78/137] System.ComponentModel.Primitives.dll -> System.ComponentModel.Primitives.dll.so
  [79/137] System.ComponentModel.TypeConverter.dll -> System.ComponentModel.TypeConverter.dll.so
  [80/137] System.ComponentModel.dll -> System.ComponentModel.dll.so
  [81/137] System.Console.dll -> System.Console.dll.so
  [82/137] System.Diagnostics.Debug.dll -> System.Diagnostics.Debug.dll.so
  [83/137] System.Diagnostics.DiagnosticSource.dll -> System.Diagnostics.DiagnosticSource.dll.so
  [84/137] System.Diagnostics.Process.dll -> System.Diagnostics.Process.dll.so
  [85/137] System.Diagnostics.Tools.dll -> System.Diagnostics.Tools.dll.so
  [86/137] System.Diagnostics.TraceSource.dll -> System.Diagnostics.TraceSource.dll.so
  [87/137] System.Diagnostics.Tracing.dll -> System.Diagnostics.Tracing.dll.so
  [88/137] System.Drawing.Primitives.dll -> System.Drawing.Primitives.dll.so
  [89/137] System.Drawing.dll -> System.Drawing.dll.so
  [90/137] System.Formats.Asn1.dll -> System.Formats.Asn1.dll.so
  [91/137] System.Globalization.dll -> System.Globalization.dll.so
  [92/137] System.IO.Compression.Brotli.dll -> System.IO.Compression.Brotli.dll.so
  [93/137] System.IO.Compression.dll -> System.IO.Compression.dll.so
  [94/137] System.IO.FileSystem.Watcher.dll -> System.IO.FileSystem.Watcher.dll.so
  [95/137] System.IO.FileSystem.dll -> System.IO.FileSystem.dll.so
  [96/137] System.IO.Pipelines.dll -> System.IO.Pipelines.dll.so
  [97/137] System.IO.dll -> System.IO.dll.so
  [98/137] System.Linq.Expressions.dll -> System.Linq.Expressions.dll.so
  [99/137] System.Linq.dll -> System.Linq.dll.so
  [100/137] System.Memory.dll -> System.Memory.dll.so
  [101/137] System.Net.Http.dll -> System.Net.Http.dll.so
  [102/137] System.Net.NameResolution.dll -> System.Net.NameResolution.dll.so
  [103/137] System.Net.Primitives.dll -> System.Net.Primitives.dll.so
  [104/137] System.Net.Requests.dll -> System.Net.Requests.dll.so
  [105/137] System.Net.Sockets.dll -> System.Net.Sockets.dll.so
  [106/137] System.Numerics.Vectors.dll -> System.Numerics.Vectors.dll.so
  [107/137] System.ObjectModel.dll -> System.ObjectModel.dll.so
  [108/137] System.Private.Uri.dll -> System.Private.Uri.dll.so
  [109/137] System.Private.Xml.Linq.dll -> System.Private.Xml.Linq.dll.so
  [110/137] System.Private.Xml.dll -> System.Private.Xml.dll.so
  [111/137] System.Reflection.Extensions.dll -> System.Reflection.Extensions.dll.so
  [112/137] System.Reflection.TypeExtensions.dll -> System.Reflection.TypeExtensions.dll.so
  [113/137] System.Reflection.dll -> System.Reflection.dll.so
  [114/137] System.Runtime.Extensions.dll -> System.Runtime.Extensions.dll.so
  [115/137] System.Runtime.InteropServices.RuntimeInformation.dll -> System.Runtime.InteropServices.RuntimeInformation.dll.so
  [116/137] System.Runtime.InteropServices.dll -> System.Runtime.InteropServices.dll.so
  [117/137] System.Runtime.Loader.dll -> System.Runtime.Loader.dll.so
  [118/137] System.Runtime.Numerics.dll -> System.Runtime.Numerics.dll.so
  [119/137] System.Runtime.dll -> System.Runtime.dll.so
  [120/137] System.Security.Cryptography.dll -> System.Security.Cryptography.dll.so
  [121/137] System.Text.Encoding.dll -> System.Text.Encoding.dll.so
  [122/137] System.Text.Encodings.Web.dll -> System.Text.Encodings.Web.dll.so
  [123/137] System.Text.Json.dll -> System.Text.Json.dll.so
  [124/137] System.Text.RegularExpressions.dll -> System.Text.RegularExpressions.dll.so
  [125/137] System.Threading.Tasks.dll -> System.Threading.Tasks.dll.so
  [126/137] System.Threading.Thread.dll -> System.Threading.Thread.dll.so
  [127/137] System.Threading.ThreadPool.dll -> System.Threading.ThreadPool.dll.so
  [128/137] System.Threading.dll -> System.Threading.dll.so
  [129/137] System.Xml.Linq.dll -> System.Xml.Linq.dll.so
  [130/137] System.Xml.ReaderWriter.dll -> System.Xml.ReaderWriter.dll.so
  [131/137] System.Xml.XDocument.dll -> System.Xml.XDocument.dll.so
  [132/137] System.dll -> System.dll.so
  [133/137] netstandard.dll -> netstandard.dll.so
  [134/137] Java.Interop.dll -> Java.Interop.dll.so
  [135/137] Mono.Android.Runtime.dll -> Mono.Android.Runtime.dll.so
  [136/137] Mono.Android.dll -> Mono.Android.dll.so
  [137/137] System.Private.CoreLib.dll -> System.Private.CoreLib.dll.so

Build succeeded.

/home/vsts/work/1/s/src/BlazorWebView/src/Maui/MauiBlazorWebViewBuilderExtensions.cs(11,22): warning RS0016: Symbol 'Microsoft.AspNetCore.Components.WebView.Maui.MauiBlazorWebViewBuilderExtensions' is not part of the declared public API (https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md) [/home/vsts/work/1/s/src/BlazorWebView/src/Maui/Microsoft.AspNetCore.Components.WebView.Maui.csproj::TargetFramework=net10.0-android36.0]
/home/vsts/work/1/s/src/BlazorWebView/src/Maui/MauiBlazorWebViewBuilderExtensions.cs(32,43): warning RS0016: Symbol 'static Microsoft.AspNetCore.Components.WebView.Maui.MauiBlazorWebViewBuilderExtensions.UsePlatformHandler<THandler>(this Microsoft.AspNetCore.Components.WebView.Maui.IMauiBlazorWebViewBuilder! builder) -> Microsoft.AspNetCore.Components.WebView.Maui.IMauiBlazorWebViewBuilder!' is not part of the declared public API (https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md) [/home/vsts/work/1/s/src/BlazorWebView/src/Maui/Microsoft.AspNetCore.Components.WebView.Maui.csproj::TargetFramework=net10.0-android36.0]
/home/vsts/work/1/s/src/BlazorWebView/src/Maui/MauiBlazorWebViewBuilderExtensions.cs(64,43): warning RS0016: Symbol 'static Microsoft.AspNetCore.Components.WebView.Maui.MauiBlazorWebViewBuilderExtensions.UsePlatformHandler(this Microsoft.AspNetCore.Components.WebView.Maui.IMauiBlazorWebViewBuilder! builder, System.Func<System.IServiceProvider!, Microsoft.Maui.IViewHandler!>! factory) -> Microsoft.AspNetCore.Components.WebView.Maui.IMauiBlazorWebViewBuilder!' is not part of the declared public API (https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md) [/home/vsts/work/1/s/src/BlazorWebView/src/Maui/Microsoft.AspNetCore.Components.WebView.Maui.csproj::TargetFramework=net10.0-android36.0]
    3 Warning(s)
    0 Error(s)

Time Elapsed 00:10:04.43
[11.0.0-prerelease.26230.4+92962e5c46ac08a66ded4c5696209cc60f1a232f] XHarness command issued: android test --app /home/vsts/work/1/s/artifacts/bin/MauiBlazorWebView.DeviceTests/Release/net10.0-android/com.microsoft.maui.mauiblazorwebview.devicetests-Signed.apk --package-name com.microsoft.maui.mauiblazorwebview.devicetests --device-id emulator-5554 -o artifacts/log --timeout 01:00:00 -v --arg TestFilter=Category=BlazorWebView
�[40m�[37mdbug�[39m�[22m�[49m: ADBRunner using ADB.exe supplied from /home/vsts/.nuget/packages/microsoft.dotnet.xharness.cli/11.0.0-prerelease.26230.4/tools/net10.0/any/../../../runtimes/any/native/adb/linux/adb
�[40m�[37mdbug�[39m�[22m�[49m: Full resolved path:'/home/vsts/.nuget/packages/microsoft.dotnet.xharness.cli/11.0.0-prerelease.26230.4/runtimes/any/native/adb/linux/adb'
�[40m�[32minfo�[39m�[22m�[49m: Will attempt to find device supporting architectures: 'arm64-v8a', 'x86_64'
�[40m�[37mdbug�[39m�[22m�[49m: Executing command: '/home/vsts/.nuget/packages/microsoft.dotnet.xharness.cli/11.0.0-prerelease.26230.4/runtimes/any/native/adb/linux/adb start-server'
�[40m�[37mdbug�[39m�[22m�[49m: 
�[40m�[32minfo�[39m�[22m�[49m: Finding attached devices/emulators...
�[40m�[37mdbug�[39m�[22m�[49m: Executing command: '/home/vsts/.nuget/packages/microsoft.dotnet.xharness.cli/11.0.0-prerelease.26230.4/runtimes/any/native/adb/linux/adb devices -l'
�[40m�[37mdbug�[39m�[22m�[49m: Found 1 possible devices
�[40m�[37mdbug�[39m�[22m�[49m: Evaluating output line for device serial: emulator-5554          device product:sdk_gphone_x86_64 model:sdk_gphone_x86_64 device:generic_x86_64_arm64 transport_id:3
�[40m�[37mdbug�[39m�[22m�[49m: Executing command: '/home/vsts/.nuget/packages/microsoft.dotnet.xharness.cli/11.0.0-prerelease.26230.4/runtimes/any/native/adb/linux/adb -s emulator-5554 shell getprop ro.product.cpu.abilist'
�[40m�[37mdbug�[39m�[22m�[49m: Found 1 possible devices. Using 'emulator-5554'
�[40m�[32minfo�[39m�[22m�[49m: Active Android device set to serial 'emulator-5554'
�[40m�[37mdbug�[39m�[22m�[49m: Executing command: '/home/vsts/.nuget/packages/microsoft.dotnet.xharness.cli/11.0.0-prerelease.26230.4/runtimes/any/native/adb/linux/adb -s emulator-5554 -s emulator-5554 shell getprop ro.product.cpu.abi'
�[40m�[37mdbug�[39m�[22m�[49m: Executing command: '/home/vsts/.nuget/packages/microsoft.dotnet.xharness.cli/11.0.0-prerelease.26230.4/runtimes/any/native/adb/linux/adb -s emulator-5554 -s emulator-5554 shell getprop ro.build.version.sdk'
�[40m�[32minfo�[39m�[22m�[49m: Waiting for device to be available (max 5 minutes)
�[40m�[37mdbug�[39m�[22m�[49m: Executing command: '/home/vsts/.nuget/packages/microsoft.dotnet.xharness.cli/11.0.0-prerelease.26230.4/runtimes/any/native/adb/linux/adb -s emulator-5554 wait-for-device'
�[40m�[37mdbug�[39m�[22m�[49m: Executing command: '/home/vsts/.nuget/packages/microsoft.dotnet.xharness.cli/11.0.0-prerelease.26230.4/runtimes/any/native/adb/linux/adb -s emulator-5554 -s emulator-5554 shell getprop sys.boot_completed'
�[40m�[37mdbug�[39m�[22m�[49m: sys.boot_completed = '1'
�[40m�[37mdbug�[39m�[22m�[49m: Waited 0 seconds for device boot completion
�[40m�[37mdbug�[39m�[22m�[49m: Working with emulator-5554 (API 30)
�[40m�[37mdbug�[39m�[22m�[49m: Check current adb install and/or package verification settings
�[40m�[37mdbug�[39m�[22m�[49m: Executing command: '/home/vsts/.nuget/packages/microsoft.dotnet.xharness.cli/11.0.0-prerelease.26230.4/runtimes/any/native/adb/linux/adb -s emulator-5554 shell settings get global verifier_verify_adb_installs'
�[40m�[37mdbug�[39m�[22m�[49m: verifier_verify_adb_installs = 0
�[40m�[37mdbug�[39m�[22m�[49m: Executing command: '/home/vsts/.nuget/packages/microsoft.dotnet.xharness.cli/11.0.0-prerelease.26230.4/runtimes/any/native/adb/linux/adb -s emulator-5554 shell settings get global package_verifier_enable'
�[40m�[37mdbug�[39m�[22m�[49m: package_verifier_enable = 
�[40m�[1m�[33mwarn�[39m�[22m�[49m: Installing debug apks on a device might be rejected with INSTALL_FAILED_VERIFICATION_FAILURE. Make sure to set 'package_verifier_enable' to '0'
�[40m�[32minfo�[39m�[22m�[49m: Attempting to remove apk 'com.microsoft.maui.mauiblazorwebview.devicetests'..
�[40m�[37mdbug�[39m�[22m�[49m: Executing command: '/home/vsts/.nuget/packages/microsoft.dotnet.xharness.cli/11.0.0-prerelease.26230.4/runtimes/any/native/adb/linux/adb -s emulator-5554 uninstall com.microsoft.maui.mauiblazorwebview.devicetests'
�[41m�[30mfail�[39m�[22m�[49m: Waiting for command timed out: execution may be compromised
�[41m�[30mfail�[39m�[22m�[49m: Error: Exit code: -2
      Std out:
      
      
      
�[40m�[32minfo�[39m�[22m�[49m: Attempting to install /home/vsts/work/1/s/artifacts/bin/MauiBlazorWebView.DeviceTests/Release/net10.0-android/com.microsoft.maui.mauiblazorwebview.devicetests-Signed.apk
�[40m�[37mdbug�[39m�[22m�[49m: Executing command: '/home/vsts/.nuget/packages/microsoft.dotnet.xharness.cli/11.0.0-prerelease.26230.4/runtimes/any/native/adb/linux/adb -s emulator-5554 install /home/vsts/work/1/s/artifacts/bin/MauiBlazorWebView.DeviceTests/Release/net10.0-android/com.microsoft.maui.mauiblazorwebview.devicetests-Signed.apk'
�[41m�[30mfail�[39m�[22m�[49m: Error:
      Exit code: 1
      Std out:
      Serving...
      Performing Incremental Install
      cmd: Failure calling service package: Broken pipe (32)
      Performing Streamed Install
      
      
      Std err:
      All files should be loaded. Notifying the device.
      adb: failed to install /home/vsts/work/1/s/artifacts/bin/MauiBlazorWebView.DeviceTests/Release/net10.0-android/com.microsoft.maui.mauiblazorwebview.devicetests-Signed.apk: cmd: Can't find service: package
      
      
      
�[41m�[1m�[37mcrit�[39m�[22m�[49m: Install failure: Test command cannot continue
�[40m�[32minfo�[39m�[22m�[49m: Attempting to remove apk 'com.microsoft.maui.mauiblazorwebview.devicetests'..
�[40m�[37mdbug�[39m�[22m�[49m: Executing command: '/home/vsts/.nuget/packages/microsoft.dotnet.xharness.cli/11.0.0-prerelease.26230.4/runtimes/any/native/adb/linux/adb -s emulator-5554 uninstall com.microsoft.maui.mauiblazorwebview.devicetests'
�[41m�[30mfail�[39m�[22m�[49m: Error: Exit code: 20
      Std out:
      
      
      Std err:
      cmd: Can't find service: package
      
      
      
�[40m�[32minfo�[39m�[22m�[49m: Attempting to remove apk 'com.microsoft.maui.mauiblazorwebview.devicetests'..
�[40m�[37mdbug�[39m�[22m�[49m: Executing command: '/home/vsts/.nuget/packages/microsoft.dotnet.xharness.cli/11.0.0-prerelease.26230.4/runtimes/any/native/adb/linux/adb -s emulator-5554 uninstall com.microsoft.maui.mauiblazorwebview.devicetests'
�[41m�[30mfail�[39m�[22m�[49m: Error: Exit code: 20
      Std out:
      
      
      Std err:
      cmd: Can't find service: package
      
      
      
XHarness exit code: 78 (PACKAGE_INSTALLATION_FAILURE)
  Tests completed with exit code: 78

🟢 With fix — 📱 BlazorWebViewTests (UsePlatformHandlerGenericReplacesDefaultBlazorWebViewHandler, UsePlatformHandlerFactoryReplacesDefaultBlazorWebViewHandler): FAIL ❌ · 958s

(truncated to last 15,000 chars)

--
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.DeviceTests.AssertionExtensions.<<AttachAndRun>g__Run|21_0>d`1[[System.Boolean, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.DeviceTests.AssertionExtensions.<AttachAndRun>d__21`1[[System.Boolean, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.DeviceTests.AssertionExtensions.<>c__DisplayClass72_0`2.<<AttachAndRun>g__Run|0>d[[System.Boolean, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[Microsoft.Maui.IPlatformViewHandler, Microsoft.Maui, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()
      06-07 12:17:01.087 16496 16900 I DOTNET  : --- End of stack trace from previous location ---
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.Dispatching.DispatcherExtensions.<>c__DisplayClass2_0`1.<<DispatchAsync>b__0>d[[System.Boolean, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
      06-07 12:17:01.087 16496 16900 I DOTNET  : --- End of stack trace from previous location ---
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.MauiBlazorWebView.DeviceTests.Elements.BlazorWebViewTests.RunTest(Func`3 test)
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.MauiBlazorWebView.DeviceTests.Elements.BlazorWebViewTests.RunUrlResolutionTest(String path, String mode, Action`1 assertion)
      06-07 12:17:01.087 16496 16900 I DOTNET  : --- End of stack trace from previous location ---
      06-07 12:17:01.087 16496 16900 I DOTNET  :    Execution time: 30.2548012
      06-07 12:17:01.087 16496 16900 I DOTNET  :    Test trait name: Category
      06-07 12:17:01.087 16496 16900 I DOTNET  :       value: BlazorWebView
      06-07 12:17:01.087 16496 16900 I DOTNET  : 
      06-07 12:17:01.087 16496 16900 I DOTNET  : 18) 	[FAIL] BlazorWebViewWithoutDispatchFailsToGetScopedServices   Test name: BlazorWebViewWithoutDispatchFailsToGetScopedServices
      06-07 12:17:01.087 16496 16900 I DOTNET  :    Assembly:  [Microsoft.Maui.MauiBlazorWebView.DeviceTests, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]
      06-07 12:17:01.087 16496 16900 I DOTNET  :    Exception messages: System.Exception : Waited 30000ms but couldn't get window.Blazor to be non-null *and* have window.__BlazorStarted to be true.   Exception stack traces:    at Microsoft.Maui.MauiBlazorWebView.DeviceTests.WebViewHelpers.Retry(Func`1 tryAction, Func`2 createExceptionWithTimeoutMS)
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.MauiBlazorWebView.DeviceTests.WebViewHelpers.WaitForWebViewReady(WebView webview)
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.MauiBlazorWebView.DeviceTests.Elements.BlazorWebViewTests.<>c__DisplayClass32_0.<<BlazorWebViewWithoutDispatchFailsToGetScopedServices>b__1>d.MoveNext()
      06-07 12:17:01.087 16496 16900 I DOTNET  : --- End of stack trace from previous location ---
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.Dispatching.DispatcherExtensions.<>c__DisplayClass3_0.<<DispatchAsync>b__0>d.MoveNext()
      06-07 12:17:01.087 16496 16900 I DOTNET  : --- End of stack trace from previous location ---
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.Dispatching.DispatcherExtensions.<>c__DisplayClass2_0`1.<<DispatchAsync>b__0>d[[System.Boolean, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
      06-07 12:17:01.087 16496 16900 I DOTNET  : --- End of stack trace from previous location ---
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.MauiBlazorWebView.DeviceTests.Elements.BlazorWebViewTests.BlazorWebViewWithoutDispatchFailsToGetScopedServices()
      06-07 12:17:01.087 16496 16900 I DOTNET  : --- End of stack trace from previous location ---
      06-07 12:17:01.087 16496 16900 I DOTNET  :    Execution time: 30.0698148
      06-07 12:17:01.087 16496 16900 I DOTNET  :    Test trait name: Category
      06-07 12:17:01.087 16496 16900 I DOTNET  :       value: BlazorWebView
      06-07 12:17:01.087 16496 16900 I DOTNET  : 
      06-07 12:17:01.087 16496 16900 I DOTNET  : 19) 	[FAIL] BasicRazorComponentClick   Test name: BasicRazorComponentClick
      06-07 12:17:01.087 16496 16900 I DOTNET  :    Assembly:  [Microsoft.Maui.MauiBlazorWebView.DeviceTests, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]
      06-07 12:17:01.087 16496 16900 I DOTNET  :    Exception messages: System.Exception : Waited 30000ms but couldn't get window.Blazor to be non-null *and* have window.__BlazorStarted to be true.   Exception stack traces:    at Microsoft.Maui.MauiBlazorWebView.DeviceTests.WebViewHelpers.Retry(Func`1 tryAction, Func`2 createExceptionWithTimeoutMS)
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.MauiBlazorWebView.DeviceTests.WebViewHelpers.WaitForWebViewReady(WebView webview)
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.MauiBlazorWebView.DeviceTests.Elements.BlazorWebViewTests.<>c__DisplayClass2_0.<<BasicRazorComponentClick>b__1>d.MoveNext()
      06-07 12:17:01.087 16496 16900 I DOTNET  : --- End of stack trace from previous location ---
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.Dispatching.DispatcherExtensions.<>c__DisplayClass3_0.<<DispatchAsync>b__0>d.MoveNext()
      06-07 12:17:01.087 16496 16900 I DOTNET  : --- End of stack trace from previous location ---
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.Dispatching.DispatcherExtensions.<>c__DisplayClass2_0`1.<<DispatchAsync>b__0>d[[System.Boolean, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
      06-07 12:17:01.087 16496 16900 I DOTNET  : --- End of stack trace from previous location ---
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.MauiBlazorWebView.DeviceTests.Elements.BlazorWebViewTests.BasicRazorComponentClick()
      06-07 12:17:01.087 16496 16900 I DOTNET  : --- End of stack trace from previous location ---
      06-07 12:17:01.087 16496 16900 I DOTNET  :    Execution time: 30.0695581
      06-07 12:17:01.087 16496 16900 I DOTNET  :    Test trait name: Category
      06-07 12:17:01.087 16496 16900 I DOTNET  :       value: BlazorWebView
      06-07 12:17:01.087 16496 16900 I DOTNET  : 
      06-07 12:17:01.087 16496 16900 I DOTNET  : 20) 	[FAIL] RequestsCanBeInterceptedAndCustomDataReturnedForDifferentHosts   Test name: RequestsCanBeInterceptedAndCustomDataReturnedForDifferentHosts(uriBase: "https://echo.free.beeceptor.com/sample-request")   Test case: RequestsCanBeInterceptedAndCustomDataReturnedForDifferentHosts
      06-07 12:17:01.087 16496 16900 I DOTNET  :    Assembly:  [Microsoft.Maui.MauiBlazorWebView.DeviceTests, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]
      06-07 12:17:01.087 16496 16900 I DOTNET  :    Exception messages: System.Exception : Waited 30000ms but couldn't get window.Blazor to be non-null *and* have window.__BlazorStarted to be true.   Exception stack traces:    at Microsoft.Maui.MauiBlazorWebView.DeviceTests.WebViewHelpers.Retry(Func`1 tryAction, Func`2 createExceptionWithTimeoutMS)
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.MauiBlazorWebView.DeviceTests.WebViewHelpers.WaitForWebViewReady(WebView webview)
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.MauiBlazorWebView.DeviceTests.Elements.BlazorWebViewTests.<>c__DisplayClass26_0.<<RunTest>b__1>d.MoveNext()
      06-07 12:17:01.087 16496 16900 I DOTNET  : --- End of stack trace from previous location ---
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.DeviceTests.HandlerTestBasement.<>c__DisplayClass20_0.<<AttachAndRun>b__0>d.MoveNext()
      06-07 12:17:01.087 16496 16900 I DOTNET  : --- End of stack trace from previous location ---
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.DeviceTests.AssertionExtensions.<<AttachAndRun>g__Run|21_0>d`1[[System.Boolean, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.DeviceTests.AssertionExtensions.<AttachAndRun>d__21`1[[System.Boolean, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.DeviceTests.AssertionExtensions.<>c__DisplayClass72_0`2.<<AttachAndRun>g__Run|0>d[[System.Boolean, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[Microsoft.Maui.IPlatformViewHandler, Microsoft.Maui, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()
      06-07 12:17:01.087 16496 16900 I DOTNET  : --- End of stack trace from previous location ---
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.Dispatching.DispatcherExtensions.<>c__DisplayClass2_0`1.<<DispatchAsync>b__0>d[[System.Boolean, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
      06-07 12:17:01.087 16496 16900 I DOTNET  : --- End of stack trace from previous location ---
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.MauiBlazorWebView.DeviceTests.Elements.BlazorWebViewTests.RunTest(Func`3 test)
      06-07 12:17:01.087 16496 16900 I DOTNET  : --- End of stack trace from previous location ---
      06-07 12:17:01.087 16496 16900 I DOTNET  :    Execution time: 30.2194039
      06-07 12:17:01.087 16496 16900 I DOTNET  :    Test trait name: Category
      06-07 12:17:01.087 16496 16900 I DOTNET  :       value: BlazorWebView
      06-07 12:17:01.087 16496 16900 I DOTNET  : 
      06-07 12:17:01.087 16496 16900 I DOTNET  : 21) 	[FAIL] RequestsCanBeInterceptedAndCaseInsensitiveHeadersRead   Test name: RequestsCanBeInterceptedAndCaseInsensitiveHeadersRead(uriBase: "https://echo.free.beeceptor.com/sample-request")   Test case: RequestsCanBeInterceptedAndCaseInsensitiveHeadersRead
      06-07 12:17:01.087 16496 16900 I DOTNET  :    Assembly:  [Microsoft.Maui.MauiBlazorWebView.DeviceTests, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]
      06-07 12:17:01.087 16496 16900 I DOTNET  :    Exception messages: System.Exception : Waited 30000ms but couldn't get window.Blazor to be non-null *and* have window.__BlazorStarted to be true.   Exception stack traces:    at Microsoft.Maui.MauiBlazorWebView.DeviceTests.WebViewHelpers.Retry(Func`1 tryAction, Func`2 createExceptionWithTimeoutMS)
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.MauiBlazorWebView.DeviceTests.WebViewHelpers.WaitForWebViewReady(WebView webview)
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.MauiBlazorWebView.DeviceTests.Elements.BlazorWebViewTests.<>c__DisplayClass26_0.<<RunTest>b__1>d.MoveNext()
      06-07 12:17:01.087 16496 16900 I DOTNET  : --- End of stack trace from previous location ---
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.DeviceTests.HandlerTestBasement.<>c__DisplayClass20_0.<<AttachAndRun>b__0>d.MoveNext()
      06-07 12:17:01.087 16496 16900 I DOTNET  : --- End of stack trace from previous location ---
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.DeviceTests.AssertionExtensions.<<AttachAndRun>g__Run|21_0>d`1[[System.Boolean, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.DeviceTests.AssertionExtensions.<AttachAndRun>d__21`1[[System.Boolean, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.DeviceTests.AssertionExtensions.<>c__DisplayClass72_0`2.<<AttachAndRun>g__Run|0>d[[System.Boolean, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[Microsoft.Maui.IPlatformViewHandler, Microsoft.Maui, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()
      06-07 12:17:01.087 16496 16900 I DOTNET  : --- End of stack trace from previous location ---
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.Dispatching.DispatcherExtensions.<>c__DisplayClass2_0`1.<<DispatchAsync>b__0>d[[System.Boolean, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
      06-07 12:17:01.087 16496 16900 I DOTNET  : --- End of stack trace from previous location ---
      06-07 12:17:01.087 16496 16900 I DOTNET  :    at Microsoft.Maui.MauiBlazorWebView.DeviceTests.Elements.BlazorWebViewTests.RunTest(Func`3 test)
      06-07 12:17:01.087 16496 16900 I DOTNET  : --- End of stack trace from previous location ---
      06-07 12:17:01.087 16496 16900 I DOTNET  :    Execution time: 30.2891763
      06-07 12:17:01.087 16496 16900 I DOTNET  :    Test trait name: Category
      06-07 12:17:01.087 16496 16900 I DOTNET  :       value: BlazorWebView
      06-07 12:17:01.087 16496 16900 I DOTNET  : 
      06-07 12:17:01.114 16496 16900 I DOTNET  : Xml file was written to the provided writer.
      06-07 12:17:01.115 16496 16900 I DOTNET  : Tests run: 25 Passed: 3 Inconclusive: 0 Failed: 21 Ignored: 0
�[41m�[30mfail�[39m�[22m�[49m: Non-success instrumentation exit code: 1, expected: 0
�[40m�[32minfo�[39m�[22m�[49m: <<XHARNESS_RESULT_START>>
      {
        "version": 1,
        "machineName": "runnervmm79r7",
        "exitCode": 1,
        "exitCodeName": "TESTS_FAILED",
        "platform": "android",
        "instrumentationExitCode": 1,
        "device": "emulator-5554",
        "deviceOsVersion": "API 30",
        "architecture": "x86_64",
        "files": [
          {
            "name": "testResults.xml",
            "type": "test-results"
          },
          {
            "name": "adb-logcat-com.microsoft.maui.mauiblazorwebview.devicetests-default.log",
            "type": "logcat"
          }
        ]
      }
      <<XHARNESS_RESULT_END>>
�[40m�[32minfo�[39m�[22m�[49m: Attempting to remove apk 'com.microsoft.maui.mauiblazorwebview.devicetests'..
�[40m�[37mdbug�[39m�[22m�[49m: Executing command: '/home/vsts/.nuget/packages/microsoft.dotnet.xharness.cli/11.0.0-prerelease.26230.4/runtimes/any/native/adb/linux/adb -s emulator-5554 uninstall com.microsoft.maui.mauiblazorwebview.devicetests'
�[40m�[32minfo�[39m�[22m�[49m: Successfully uninstalled com.microsoft.maui.mauiblazorwebview.devicetests
XHarness exit code: 1 (TESTS_FAILED)
  Tests completed with exit code: 1

🔴 Without fix — 🧪 HostBuilderHandlerTests: PASS ❌ · 157s
  Determining projects to restore...
  Restored /home/vsts/work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 1.11 sec).
  Restored /home/vsts/work/1/s/src/Core/src/Core.csproj (in 1.27 sec).
  Restored /home/vsts/work/1/s/src/TestUtils/src/TestUtils/TestUtils.csproj (in 209 ms).
  Restored /home/vsts/work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 214 ms).
  Restored /home/vsts/work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 30 ms).
  Restored /home/vsts/work/1/s/src/Essentials/src/Essentials.csproj (in 58 ms).
  Restored /home/vsts/work/1/s/src/Core/tests/UnitTests/Core.UnitTests.csproj (in 2.04 sec).
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14306458
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14306458
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14306458
  Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14306458
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
  TestUtils -> /home/vsts/work/1/s/artifacts/bin/TestUtils/Debug/netstandard2.0/Microsoft.Maui.TestUtils.dll
  Core.UnitTests -> /home/vsts/work/1/s/artifacts/bin/Core.UnitTests/Debug/net10.0/Microsoft.Maui.UnitTests.dll
Test run for /home/vsts/work/1/s/artifacts/bin/Core.UnitTests/Debug/net10.0/Microsoft.Maui.UnitTests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (x64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.14]   Discovering: Microsoft.Maui.UnitTests
[xUnit.net 00:00:00.73]   Discovered:  Microsoft.Maui.UnitTests
[xUnit.net 00:00:00.74]   Starting:    Microsoft.Maui.UnitTests
  Passed HostBuilderThrowsWhenOnlyInterfacesRelatedByInheritanceAreRegistered [82 ms]
  Passed HostBuilderCanRegisterAndResolveCorrespondingHandlerService(registerHandlerServicesWithGenerics: False, retrieveHandlerServiceWithGenerics: True) [6 ms]
  Passed HostBuilderCanRegisterAndResolveCorrespondingHandlerService(registerHandlerServicesWithGenerics: False, retrieveHandlerServiceWithGenerics: False) [< 1 ms]
  Passed HostBuilderCanRegisterAndResolveCorrespondingHandlerService(registerHandlerServicesWithGenerics: True, retrieveHandlerServiceWithGenerics: True) [< 1 ms]
  Passed HostBuilderCanRegisterAndResolveCorrespondingHandlerService(registerHandlerServicesWithGenerics: True, retrieveHandlerServiceWithGenerics: False) [< 1 ms]
  Passed FactoryBasedHandlerRegistrationReplacesHandler [1 ms]
  Passed SecondConfigureMauiHandlersCallReplacesHandler [< 1 ms]
  Passed HostBuilderDoesNotResolveHandlersRegisteredUnderMoreDerivedTypes [< 1 ms]
  Passed HostBuilderResolvesToHandlerRegisteredUnderConcreteTypeDespiteAmbiguousInterfacesRegistered [< 1 ms]
  Passed HostBuilderWithoutDefaultsDoesNotRegisterMauiHandlersFactory [2 ms]
  Passed HostBuilderCanBuildAHost [< 1 ms]
  Passed HostBuilderResolvesHandlerRegisteredUnderBaseInterfaceType(baseInterfaceType: typeof(Microsoft.Maui.UnitTests.Hosting.HostBuilderHandlerTests+IMyDerivedViewStub)) [2 ms]
  Passed HostBuilderResolvesHandlerRegisteredUnderBaseInterfaceType(baseInterfaceType: typeof(Microsoft.Maui.UnitTests.Hosting.HostBuilderHandlerTests+IMyBaseViewStub)) [< 1 ms]
  Passed HostBuilderResolvesHandlerRegisteredUnderBaseInterfaceType(baseInterfaceType: typeof(Microsoft.Maui.UnitTests.IViewStub)) [< 1 ms]
  Passed HostBuilderResolvesToHandlerRegisteredUnderConcreteTypeOverInterfaceType [< 1 ms]
  Passed HostBuilderResolvesHandlerTypeForServiceRegisteredWithType [2 ms]
  Passed HostBuilderResolvesClosestApplicableServiceType(type: typeof(Microsoft.Maui.UnitTests.ViewStub), expectedHandlerType: typeof(Microsoft.Maui.UnitTests.ViewHandlerStub)) [< 1 ms]
  Passed HostBuilderResolvesClosestApplicableServiceType(type: typeof(Microsoft.Maui.UnitTests.Hosting.HostBuilderHandlerTests+MyDerivedViewStub), expectedHandlerType: typeof(Microsoft.Maui.UnitTests.Hosting.HostBuilderHandlerTests+MyBaseHandlerStub)) [2 ms]
[xUnit.net 00:00:01.05]   Finished:    Microsoft.Maui.UnitTests
  Passed HostBuilderResolvesClosestApplicableServiceType(type: typeof(Microsoft.Maui.UnitTests.Hosting.HostBuilderHandlerTests+MyBaseViewStub), expectedHandlerType: typeof(Microsoft.Maui.UnitTests.Hosting.HostBuilderHandlerTests+MyBaseHandlerStub)) [< 1 ms]
  Passed HostBuilderResolvesClosestApplicableServiceType(type: typeof(Microsoft.Maui.UnitTests.IViewStub), expectedHandlerType: typeof(Microsoft.Maui.UnitTests.ViewHandlerStub)) [< 1 ms]
  Passed HostBuilderCannotResolveHandlerTypeForServiceRegisteredWithFactory [2 ms]
  Passed HostBuilderResolvesLastRegisteredHandlerServiceForServiceType [1 ms]
  Passed HostBuilderThrowsWhenNoMatchingHandlerServiceTypeIsRegistered [< 1 ms]
  Passed HostBuilderResolvesToHandlerRegisteredUnderMostDerivedBaseInterfaceType [2 ms]
  Passed HostBuilderWithDefaultsRegistersMauiHandlersFactory [< 1 ms]

Test Run Successful.
Total tests: 25
     Passed: 25
 Total time: 2.0414 Seconds

🟢 With fix — 🧪 HostBuilderHandlerTests: PASS ✅ · 21s
  Determining projects to restore...
  Restored /home/vsts/work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 1.03 sec).
  Restored /home/vsts/work/1/s/src/Essentials/src/Essentials.csproj (in 1.04 sec).
  Restored /home/vsts/work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 298 ms).
  Restored /home/vsts/work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 88 ms).
  Restored /home/vsts/work/1/s/src/Core/src/Core.csproj (in 479 ms).
  2 of 7 projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14306458
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14306458
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14306458
  Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14306458
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
  TestUtils -> /home/vsts/work/1/s/artifacts/bin/TestUtils/Debug/netstandard2.0/Microsoft.Maui.TestUtils.dll
  Core.UnitTests -> /home/vsts/work/1/s/artifacts/bin/Core.UnitTests/Debug/net10.0/Microsoft.Maui.UnitTests.dll
Test run for /home/vsts/work/1/s/artifacts/bin/Core.UnitTests/Debug/net10.0/Microsoft.Maui.UnitTests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (x64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.22]   Discovering: Microsoft.Maui.UnitTests
[xUnit.net 00:00:00.84]   Discovered:  Microsoft.Maui.UnitTests
[xUnit.net 00:00:00.86]   Starting:    Microsoft.Maui.UnitTests
  Passed HostBuilderThrowsWhenOnlyInterfacesRelatedByInheritanceAreRegistered [124 ms]
  Passed HostBuilderCanRegisterAndResolveCorrespondingHandlerService(registerHandlerServicesWithGenerics: False, retrieveHandlerServiceWithGenerics: True) [10 ms]
  Passed HostBuilderCanRegisterAndResolveCorrespondingHandlerService(registerHandlerServicesWithGenerics: False, retrieveHandlerServiceWithGenerics: False) [< 1 ms]
  Passed HostBuilderCanRegisterAndResolveCorrespondingHandlerService(registerHandlerServicesWithGenerics: True, retrieveHandlerServiceWithGenerics: True) [< 1 ms]
  Passed HostBuilderCanRegisterAndResolveCorrespondingHandlerService(registerHandlerServicesWithGenerics: True, retrieveHandlerServiceWithGenerics: False) [< 1 ms]
  Passed FactoryBasedHandlerRegistrationReplacesHandler [1 ms]
  Passed SecondConfigureMauiHandlersCallReplacesHandler [< 1 ms]
  Passed HostBuilderDoesNotResolveHandlersRegisteredUnderMoreDerivedTypes [1 ms]
  Passed HostBuilderResolvesToHandlerRegisteredUnderConcreteTypeDespiteAmbiguousInterfacesRegistered [1 ms]
  Passed HostBuilderWithoutDefaultsDoesNotRegisterMauiHandlersFactory [1 ms]
  Passed HostBuilderCanBuildAHost [< 1 ms]
  Passed HostBuilderResolvesHandlerRegisteredUnderBaseInterfaceType(baseInterfaceType: typeof(Microsoft.Maui.UnitTests.Hosting.HostBuilderHandlerTests+IMyDerivedViewStub)) [4 ms]
  Passed HostBuilderResolvesHandlerRegisteredUnderBaseInterfaceType(baseInterfaceType: typeof(Microsoft.Maui.UnitTests.Hosting.HostBuilderHandlerTests+IMyBaseViewStub)) [< 1 ms]
  Passed HostBuilderResolvesHandlerRegisteredUnderBaseInterfaceType(baseInterfaceType: typeof(Microsoft.Maui.UnitTests.IViewStub)) [< 1 ms]
  Passed HostBuilderResolvesToHandlerRegisteredUnderConcreteTypeOverInterfaceType [1 ms]
  Passed HostBuilderResolvesHandlerTypeForServiceRegisteredWithType [< 1 ms]
  Passed HostBuilderResolvesClosestApplicableServiceType(type: typeof(Microsoft.Maui.UnitTests.ViewStub), expectedHandlerType: typeof(Microsoft.Maui.UnitTests.ViewHandlerStub)) [< 1 ms]
  Passed HostBuilderResolvesClosestApplicableServiceType(type: typeof(Microsoft.Maui.UnitTests.Hosting.HostBuilderHandlerTests+MyDerivedViewStub), expectedHandlerType: typeof(Microsoft.Maui.UnitTests.Hosting.HostBuilderHandlerTests+MyBaseHandlerStub)) [2 ms]
[xUnit.net 00:00:01.19]   Finished:    Microsoft.Maui.UnitTests
  Passed HostBuilderResolvesClosestApplicableServiceType(type: typeof(Microsoft.Maui.UnitTests.Hosting.HostBuilderHandlerTests+MyBaseViewStub), expectedHandlerType: typeof(Microsoft.Maui.UnitTests.Hosting.HostBuilderHandlerTests+MyBaseHandlerStub)) [< 1 ms]
  Passed HostBuilderResolvesClosestApplicableServiceType(type: typeof(Microsoft.Maui.UnitTests.IViewStub), expectedHandlerType: typeof(Microsoft.Maui.UnitTests.ViewHandlerStub)) [< 1 ms]
  Passed HostBuilderCannotResolveHandlerTypeForServiceRegisteredWithFactory [< 1 ms]
  Passed HostBuilderResolvesLastRegisteredHandlerServiceForServiceType [2 ms]
  Passed HostBuilderThrowsWhenNoMatchingHandlerServiceTypeIsRegistered [< 1 ms]
  Passed HostBuilderResolvesToHandlerRegisteredUnderMostDerivedBaseInterfaceType [2 ms]
  Passed HostBuilderWithDefaultsRegistersMauiHandlersFactory [< 1 ms]

Test Run Successful.
Total tests: 25
     Passed: 25
 Total time: 2.4186 Seconds

⚠️ Failure Details

  • HostBuilderHandlerTests PASSED without fix (should fail) — tests don't catch the bug
  • BlazorWebViewTests (UsePlatformHandlerGenericReplacesDefaultBlazorWebViewHandler, UsePlatformHandlerFactoryReplacesDefaultBlazorWebViewHandler) FAILED with fix (should pass)
📁 Fix files reverted (7 files)
  • eng/pipelines/ci-copilot.yml
  • src/BlazorWebView/src/Maui/PublicAPI/net-android/PublicAPI.Unshipped.txt
  • src/BlazorWebView/src/Maui/PublicAPI/net-ios/PublicAPI.Unshipped.txt
  • src/BlazorWebView/src/Maui/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt
  • src/BlazorWebView/src/Maui/PublicAPI/net-tizen/PublicAPI.Unshipped.txt
  • src/BlazorWebView/src/Maui/PublicAPI/net-windows/PublicAPI.Unshipped.txt
  • src/BlazorWebView/src/Maui/PublicAPI/net/PublicAPI.Unshipped.txt

New files (not reverted):

  • src/BlazorWebView/src/Maui/MauiBlazorWebViewBuilderExtensions.cs

UI Tests — WebView

Detected UI test categories: WebView


Pre-Flight — Context & Validation

Issue: #34103 - BlazorWebView handler registration needs extensibility for custom platforms - Custom backends must bypass and reimplement AddMauiBlazorWebView() entirely
PR: #34225 - Add UsePlatformHandler for custom BlazorWebView backends
Platforms Affected: Cross-platform BlazorWebView handler registration; testing requested on Android
Files Changed: 7 implementation/API, 2 test

Key Findings

  • The linked issue asks for custom platform backends such as Linux/GTK to reuse AddMauiBlazorWebView() shared services while replacing the platform handler.
  • The current PR adds UsePlatformHandler<THandler>() and UsePlatformHandler(Func<IServiceProvider,IViewHandler>), updates PublicAPI across TFMs, and adds direct tests that exercise both overloads with real BlazorWebView types.
  • Prior review feedback already addressed the constructor activation trap (new()), DI-friendly factory overload, IViewHandler constraint, null checks, and XML documentation about handler-factory service-provider scope and call ordering.
  • Android gate was previously reported failed/not applicable; this run did not recreate or overwrite gate/content.md.

Code Review Summary

Verdict: LGTM
Confidence: high
Errors: 0 | Warnings: 1 | Suggestions: 1

Key code review findings:

  • ⚠️ Direct UsePlatformHandler tests validate DI registration only and may be better suited to unit-test feedback loops than device tests.
  • 💡 Factory overload docs could include an example clarifying that the factory IServiceProvider is handler-scoped, not the app root provider.

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #34225 Add UsePlatformHandler<THandler>() and factory overload on IMauiBlazorWebViewBuilder to override the default IBlazorWebView handler while preserving AddMauiBlazorWebView() service registrations ❌ Gate previously failed/not applicable MauiBlazorWebViewBuilderExtensions.cs, PublicAPI files, BlazorWebView/Core tests Current PR is explicit and correct, but still relies on documented call ordering

Code Review — Deep Analysis

Code Review — PR #34225

Independent Assessment

What this changes: Adds two extension methods (UsePlatformHandler<THandler>() and UsePlatformHandler(Func<IServiceProvider, IViewHandler>)) on IMauiBlazorWebViewBuilder that let a custom platform backend swap the default BlazorWebViewHandler registered by AddMauiBlazorWebView() while preserving all its shared service registrations. Two Core unit tests verify the underlying ConfigureMauiHandlers replacement mechanism; two device tests exercise the new API with real BlazorWebView types end-to-end.
Inferred motivation: Third-party or community platform targets (e.g., Linux/GTK) want to plug a custom BlazorWebView backend into the MAUI BlazorWebView stack without reimplementing all the internal JSInterop / navigation / static-assets service wiring.

Reconciliation with PR Narrative

Author claims: Adds UsePlatformHandler<T>() to let custom backends replace BlazorWebViewHandler while reusing shared services; the mechanism is last-registration-wins; factory overload serves handlers lacking parameterless constructors.
Agreement/disagreement: Agreement. The implementation realizes the stated design. The last-registration-wins claim is grounded in MauiServiceCollection/MauiFactory, and the factory overload documentation correctly calls out the handler-factory service-provider scope.

Findings

⚠️ Warning — New direct tests are device tests even though the covered behavior is DI-only

UsePlatformHandlerGenericReplacesDefaultBlazorWebViewHandler and UsePlatformHandlerFactoryReplacesDefaultBlazorWebViewHandler in BlazorWebViewTests.Services.cs build a MauiApp, resolve IMauiHandlersFactory, and assert handler mappings. They do not render a WebView or create platform views. The tests are functionally correct, but this pure registration behavior would provide faster feedback as unit coverage.

💡 Suggestion — Factory overload docs could include a short IServiceProvider-scope example

The XML docs accurately state that the factory receives the handler factory's provider rather than the app root provider. A short example would make this common footgun more obvious for handlers expecting app-level DI services.

Devil's Advocate

The generic overload's new() constraint is justified because type-based handler activation uses Activator.CreateInstance. The factory overload gives a path for handlers that cannot satisfy that constraint. The ordering caveat is real, but the PR documents it and matches MAUI handler registration semantics.

Verdict: LGTM

Confidence: high
Summary: The PR implementation is correct, trimmer-safe, and complete for its explicit API design. The main concern is test placement/discoverability of the provider-scope caveat, not a correctness blocker.


Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix-1 Replace builder extension with primary AddMauiBlazorWebView<THandler>() / factory overloads and make the default handler provisional via TryAddHandler ⚠️ PARTIAL: BlazorWebView net10.0 build passed; Android execution blocked Shared registration file, PublicAPI files, BlazorWebView tests Stronger call-site API, but same public API count and Android run did not complete
2 try-fix-2 Add Core PostConfigureMauiHandlers plus UseBlazorWebViewHandler to make overrides order-independent ❌ REJECTED before patch/test None Too broad; changes Core public API and global handler ordering for a BlazorWebView-specific issue
3 try-fix-3 Remove new public API and rely on existing concrete BlazorWebView handler registration overriding the default IBlazorWebView mapping ⚠️ PARTIAL: BlazorWebView net10.0 build passed; Android device-test build progressed but execution blocked Removed extension/PublicAPI entries; retargeted tests to concrete handler override Smallest diff, but weaker discoverability and not clearly better than PR
PR PR #34225 Add explicit UsePlatformHandler<THandler>() and factory overload with docs/tests ❌ Gate previously failed/not applicable Production API, PublicAPI, tests Current fix remains the most discoverable passing design based on available local validation

Cross-Pollination

Model Round New Ideas? Details
claude-sonnet-4.6 1 Yes Primary AddMauiBlazorWebView<THandler>() / factory overloads plus TryAddHandler default
claude-sonnet-4.6 2 Yes Core PostConfigureMauiHandlers plus UseBlazorWebViewHandler; rejected as too broad
gpt-5.5 3 Yes Existing concrete handler override convention; applied and partially validated

Exhausted: Yes
Selected Fix: PR #34225 — No alternative passed all requested Android validation or was demonstrably better. Candidate 1 is plausible but changes API shape; Candidate 2 is too broad; Candidate 3 is smallest but less discoverable and does not provide the explicit affordance requested by the issue.


Report — Final Recommendation

Comparative Report — PR #34225

Candidates Compared

Rank Candidate Result Assessment
1 pr Expert review LGTM; Android gate failed Best available fix. Adds explicit IMauiBlazorWebViewBuilder.UsePlatformHandler APIs that directly address the issue, preserve AddMauiBlazorWebView() shared service registration, support type and factory activation, and document last-registration-wins ordering.
1 pr-plus-reviewer Same as pr Expert reviewer had no actionable feedback, so this candidate is identical to pr; it does not improve or regress the raw PR.
3 try-fix-1 Build passed; Android execution blocked Plausible API alternative using AddMauiBlazorWebView<THandler>() and TryAddHandler, with better override ordering for some call sequences. It is broader than the PR, changes the primary API shape, and was not validated on Android.
4 try-fix-3 Build passed; Android execution blocked Smallest implementation because it relies on existing concrete handler registration semantics and avoids new API. It is less discoverable and does not provide the explicit BlazorWebView-specific affordance requested by the issue.
5 try-fix-2 Rejected before patch/test Addresses ordering with a Core-level post-configure concept, but the blast radius is too broad for a BlazorWebView-specific extensibility issue and would require separate API/design review.

Regression/Test Weighting

The Android gate for the PR failed and must prevent treating the PR as fully validated. However, no candidate in STEP 5a has a passing Android regression result: try-fix-1 and try-fix-3 only reached build/partial validation before Android execution was blocked, and try-fix-2 was not implemented or tested. Because there is no candidate with passing Android regression tests, the final ranking is based on code correctness, API fit, blast radius, and available validation.

Decision

Winner: pr

The raw PR fix is the strongest candidate because it is explicit, surgical, discoverable, and matches existing MAUI handler registration semantics. pr-plus-reviewer is equivalent because the expert reviewer found no actionable changes to apply. The try-fix alternatives either expand API/design scope, reduce discoverability, or lack completed Android validation, so none is demonstrably better than the submitted PR fix.


Future Action — review latest findings

No alternative fix was selected for this run. Review the session findings and CI results before merging.

@kubaflo
kubaflo changed the base branch from main to inflight/current June 7, 2026 19:50
@kubaflo
kubaflo merged commit 21409fa into inflight/current Jun 7, 2026
150 of 163 checks passed
@kubaflo
kubaflo deleted the dev/redth/fix-34103 branch June 7, 2026 19:50
@github-actions github-actions Bot added this to the .NET 10.0 SR8 milestone Jun 7, 2026
PureWeen pushed a commit that referenced this pull request Jun 11, 2026
<!-- 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 #34103

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@sheiksyedm sheiksyedm modified the milestones: .NET 10 SR8, .NET 10 SR9 Jun 18, 2026
PureWeen pushed a commit that referenced this pull request Jun 22, 2026
<!-- 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 #34103

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
kubaflo pushed a commit that referenced this pull request Jun 25, 2026
<!-- 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 #34103

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
kubaflo pushed a commit that referenced this pull request Jul 3, 2026
<!-- 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 #34103

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@kubaflo kubaflo mentioned this pull request Jul 6, 2026
kubaflo pushed a commit that referenced this pull request Jul 6, 2026
<!-- 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 #34103

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
PureWeen pushed a commit that referenced this pull request Jul 7, 2026
<!-- 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 #34103

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
PureWeen pushed a commit that referenced this pull request Jul 7, 2026
<!-- 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 #34103

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
kubaflo pushed a commit that referenced this pull request Jul 10, 2026
<!-- 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 #34103

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
kubaflo pushed a commit that referenced this pull request Jul 15, 2026
<!-- 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 #34103

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 19, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet

6 participants