[Sample] Remove obsolete Router.PreferExactMatches from gallery sample - #36892
Conversation
The PreferExactMatches parameter was a .NET 5-era parameter on Microsoft.AspNetCore.Components.Routing.Router. It became a no-op in .NET 6 and has since been removed from the type, so Blazor's parameter binding now throws at runtime when the gallery sample's BlazorWebView page loads. Exact matching is the default (and only) behavior now, so there is no behavior change. This was the last occurrence in the repo. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8d49898c-b01b-411c-b02e-b82db45c9fa8
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 36892Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 36892" |
|
Azure Pipelines: Successfully started running 1 pipeline(s). There may be pipelines that require an authorized user to comment /azp run to run. |
|
Azure Pipelines: Successfully started running 1 pipeline(s). There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Pull request overview
Removes the now-removed Blazor Router.PreferExactMatches parameter from the MAUI Controls gallery sample to prevent a runtime ThrowForUnknownIncomingParameterName exception when running against ASP.NET Core 11.
Changes:
- Remove
PreferExactMatches="true"from the<Router>in the gallery sample’sMain.razor.
AI Review Summary
🗂️ Review Sessions — click to expand🚦 Gate — Test Before & After FixGate Result:
|
| Category | Tests | Snapshot diffs |
|---|---|---|
Navigation |
88/89 ✓ | — |
WebView |
50/51 (app crashed; 1 couldn't complete) | — |
⚠️ WebView — app crashed mid-run; 1 test could not complete
The HostApp crashed during this category (a test failed in TearDown with investigate as possible crash); every following OneTimeSetUp then timed out waiting for the test gallery to reappear. This can be an emulator/infrastructure flake OR a regression introduced by this PR — review the screenshots and logcat in the ui-diagnostics folder of the artifact before concluding.
The app was expected to be running still, investigate as possible crash
TearDown : The app was expected to be running still, investigate as possible crash
at UITest.Appium.NUnit.UITestBase.UITestBaseTearDown() in /_/src/TestUtils/src/UITest.NUnit/UITestBase.cs:line 159
at UITest.Appium.NUnit.UITestBase.TestTearDown() in /_/src/TestUtils/src/UITest.NUnit/UITestBase.cs:line 45
--TearDown
at UITest.Appium.NUnit.UITestBase.UITestBaseTearDown() in /_/src/TestUtils/src/UITest.NUnit/UITestBase.cs:line 159
at UITest.Appium.NUnit.UITestBase.TestTearDown() in /_/src/TestUtils/src/UITest.NUnit/UITestBase.cs:line 45
1) at UITest.Appium.NUnit.UITestBase.UITestBaseTearDown() in /_/src/TestUtils/src/UITest.NUnit/UITestBase.cs:line 159
at UITest.Appium.NUnit.UITestBase.TestTearDown() in /_/src/TestUtils/src/UITest.NUnit/UITestBase.cs:line 45
📎 Download drop-deep-uitests artifact (TRX + snapshot diffs)
📋 Pre-Flight — Context & Validation
Issue: None filed
PR: #36892 - [Sample] Remove obsolete Router.PreferExactMatches from gallery sample
Platforms Affected: BlazorWebView sample route loading on .NET 11; reported on Windows, Android build used for this review loop
Files Changed: 1 implementation, 0 test
Key Findings
- PR removes the last active
PreferExactMatchesusage fromsrc/Controls/samples/Controls.Sample/Main.razor. - Root cause matches ASP.NET Core 11 removal of the obsolete
Router.PreferExactMatchesparameter; exact route matching has been the default since .NET 6. - Gate was skipped before this run because no tests were detected in the PR; no regression test was added.
- Public PR metadata was available through unauthenticated REST;
ghchecks were unavailable due missing auth.
Code Review Summary
Verdict: NEEDS_DISCUSSION
Confidence: low
Errors: 0 | Warnings: 0 | Suggestions: 0
Key code review findings:
- ℹ No code correctness findings. Confidence is low only because required CI status was unavailable/undetermined.
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #36892 | Remove obsolete/no-op PreferExactMatches="true" from the sample Router. |
src/Controls/samples/Controls.Sample/Main.razor |
Original PR; simplest approach and aligns with upstream breaking-change guidance. |
🔬 Code Review — Deep Analysis
Code Review — PR #36892
Independent Assessment
What this changes: Removes PreferExactMatches="true" from src/Controls/samples/Controls.Sample/Main.razor:1.
Inferred motivation: The sample targets net11.0, where Blazor removed the obsolete Router.PreferExactMatches parameter.
Reconciliation with PR Narrative
Author claims: This fixes a runtime Blazor parameter-binding error in the Controls gallery sample.
Agreement/disagreement: Agree. ASP.NET Core 11 removed this API, and exact matching is already the default.
Prior Review Reconciliation
No prior ❌ Error findings found.
Blast Radius Assessment
- Runs for all instances: No — sample Blazor router only.
- Startup impact: Only sample Blazor page routing.
- Static/shared state: No.
CI Status
- Required-check result: undetermined —
gh pr checks --requiredunavailable due missing GitHub auth. - Classification: undetermined; public fallback showed PR head had pending/failing check runs.
- Action taken: invoked
azdo-build-investigator; confidence capped low, no LGTM per skill rules.
Findings
No ❌ Errors,
Failure-Mode Probing
- Older behavior regression: No expected behavior change; exact matching is default since .NET 6.
- Remaining usages: Search found no remaining active
PreferExactMatchesusages after the PR. - Invalid Router markup: Full file remains valid with unchanged
Found/NotFoundblocks.
Verdict: NEEDS_DISCUSSION
Confidence: low
Summary: Code review found no issues in the one-line sample fix. Formal verdict is not LGTM only because required CI status could not be verified and fallback check data was not clean/complete.
🛠️ Fix — Analysis & Comparison
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| 1 | try-fix | Add local CompatRouter component that accepts PreferExactMatches but does not forward it. |
2 files | Android build initially lacked restore assets; restore-enabled run was stopped after no output for several minutes. Expert review judged this over-engineered. | |
| 2 | try-fix | Use complete TFM-conditional Router blocks: omit PreferExactMatches for NET11_0_OR_GREATER, keep it for older TFMs. |
✅ Pass | 1 file | Android sample build passed after fixing the initial malformed Razor conditional. Not better than PR due duplicated markup/complexity. |
| PR | PR #36892 | Remove obsolete/no-op PreferExactMatches="true" from Main.razor. |
1 file | Original PR; simplest and matches upstream recommended action. |
Cross-Pollination
| Model | Round | New Ideas? | Details |
|---|---|---|---|
| maui-expert-reviewer / gpt-5.5 | 2 | No | NO NEW IDEAS: Direct removal is the minimal correct fix; other approaches add compatibility indirection or conditional complexity for an obsolete/no-op parameter. |
Exhausted: Yes
Selected Fix: PR's fix — Candidate 2 passes the Android build but is not demonstrably better. The PR's direct removal has the smallest blast radius and avoids preserving obsolete API shape.
🏁 Report — Final Recommendation
Comparative Fix Report — PR #36892
Candidates compared
| Rank | Candidate | Regression/build result | Assessment |
|---|---|---|---|
| 1 | pr |
Gate skipped; no tests detected | Winner. Removes the obsolete/no-op PreferExactMatches attribute directly. This matches the upstream ASP.NET Core 11 breaking-change guidance and has the smallest blast radius. |
| 2 | pr-plus-reviewer |
Same as pr |
Equivalent to pr; the expert reviewer found no actionable feedback, so no sandbox changes were applied. Ranked just below pr only because it is not a distinct improvement. |
| 3 | try-fix-2 |
Android sample build passed | Functionally viable, but duplicates the entire Router markup behind NET11_0_OR_GREATER solely to preserve an obsolete/no-op parameter on older TFMs. This is more complex than needed and creates avoidable maintenance risk. |
| 4 | try-fix-1 |
Blocked; not proven passing | Adds a local compatibility CompatRouter wrapper to accept and discard PreferExactMatches. This is over-engineered for a removed/no-op API and was not proven by regression/build validation in this environment. |
Candidate details
pr
The raw PR fix changes only src/Controls/samples/Controls.Sample/Main.razor by removing PreferExactMatches="true" from the sample Router. This directly addresses the ASP.NET Core 11 removal of Router.PreferExactMatches and preserves behavior because exact matching has been the default since .NET 6.
pr-plus-reviewer
The expert reviewer produced no inline findings:
[]No reviewer-suggested changes were applied, so this candidate is identical to pr.
try-fix-1
This candidate introduced a sample-local CompatRouter wrapper and changed Main.razor to use it with PreferExactMatches="true". It was blocked by environment/build validation and is not better than direct removal because it preserves an obsolete API shape and adds a new component abstraction for a parameter that should simply be removed.
try-fix-2
This candidate used complete TFM-conditional Router blocks: omit PreferExactMatches on NET11_0_OR_GREATER, keep it on older TFMs. The Android sample build passed, so it ranks above the blocked candidate. However, it duplicates markup and keeps obsolete/no-op behavior alive unnecessarily; the PR's direct removal is cleaner and less risky.
Winning candidate
Winner: pr
The raw PR fix is the single best candidate because it is the minimal correct change, matches upstream guidance exactly, removes the last repository occurrence of the removed API, and avoids compatibility wrappers or conditional Razor duplication. No candidate with passing validation provides a behavioral or maintainability advantage over the submitted PR fix.
🧭 Next Steps — review latest findings
No alternative fix was selected for this run. Review the session findings and CI results before merging.
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 of Change
Running the .NET MAUI gallery sample (
src/Controls/samples/Controls.Sample) on Windows produced a runtime error as soon as the BlazorWebView page loaded:Root cause
Router.PreferExactMatcheswas a .NET 5-era parameter onMicrosoft.AspNetCore.Components.Routing.Router. It became a no-op/obsolete in .NET 6 and has now been removed from the type entirely in ASP.NET Core 11. Because this branch builds against an ASP.NET Core 11 preview, Blazor's parameter binding no longer finds a matching property and throwsThrowForUnknownIncomingParameterNameat runtime.This is documented as an official upstream breaking change:
Router.PreferExactMatchesis the first entry in the Affected APIs list, with the recommended action: "Remove the assignment. Exact matching has been the default since .NET 6."Fix
Removed the
PreferExactMatches="true"attribute fromsrc/Controls/samples/Controls.Sample/Main.razor:Exact matching is the default (and only) behavior now, so there is no behavior change — this matches the recommended action in the breaking-change doc verbatim.
This was the last remaining occurrence of
PreferExactMatchesin the repo — every other<Router>already omits it, e.g.src/BlazorWebView/samples/BlazorWpfApp/Main.razor,src/BlazorWebView/samples/BlazorWinFormsApp/Main.razor,src/BlazorWebView/samples/WebViewAppShared/RouterComponent.razor, and both Blazor templates undersrc/Templates/src/templates/.Issues Fixed
None filed.
Validation
This is a
.razormarkup change in a sample, so a targeted build was used:Both succeeded with 0 errors and 0 warnings. A repo-wide search confirms there are now zero occurrences of
PreferExactMatches.