[BlazorWebView] Fixed Allow force reload for URLs with dots in query parameters - #29560
Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR fixes a bug in BlazorWebView where dots in query parameters incorrectly trigger a file extension check, preventing force reloads. Key changes include using Uri.AbsolutePath for file extension validation, adding input validation for the URL, and restricting allowed schemes.
Reviewed Changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/BlazorWebView/tests/MauiBlazorWebView.UnitTests/MauiBlazorWebView.UnitTests.csproj | New test project setup for unit tests |
| src/BlazorWebView/tests/MauiBlazorWebView.UnitTests/Extensions_Tests.cs | Comprehensive unit tests for URI handling improvements |
| src/BlazorWebView/src/Maui/Properties/AssemblyInfo.cs | Added InternalsVisibleTo attribute for test project visibility |
| src/BlazorWebView/src/Maui/Extensions/UriExtensions.cs | Updated extension method to check for file extensions only on the URI’s AbsolutePath |
| MauiBlazorWebView.sln | Updated solution to include the new test project |
Comments suppressed due to low confidence (1)
src/BlazorWebView/tests/MauiBlazorWebView.UnitTests/Extensions_Tests.cs:46
- [nitpick] The test method name suggests a false return value, but the assertion expects true. Consider renaming the method to reflect the correct expected outcome.
public void IsBaseOfPage_IgnoresDotInQuery_AndReturnsFalse_WhenNotBase()
|
Hey there @@tw4! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed. |
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
|
Can I request a review @jsuarezruiz |
kubaflo
left a comment
There was a problem hiding this comment.
Could you please review the AI's summary?
- Remove custom subdomain host/path matching, preserve original Uri.IsBaseOf behavior as the scope of this fix is limited to query/fragment dot handling - Use uri.AbsolutePath for Path.HasExtension check (core bug fix) - Align test project with repo conventions: use $(_MauiDotNetTfm) and centralized package version variables - Update subdomain test expectations to false (Uri.IsBaseOf does not match across different hosts)
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 29560Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 29560" |
|
@kubaflo I've reviewed the AI summary and addressed the requested changes:
The bug fix remains focused: Could you please re-review? |
kubaflo
left a comment
There was a problem hiding this comment.
Could you check the ai's summary?
|
Hey @kubaflo, went through the AI summary. Code review came back LGTM (high confidence) — the only suggestion was a cosmetic file rename, which I'll do ( The gate failure is actually an infrastructure issue, not a real test failure — the verify script bailed out because of uncommitted files in its setup, before any tests ran. That's why On the actual diff: Pushing the rename shortly. |
|
/review -b feature/enhanced-reviewer |
MauiBot
left a comment
There was a problem hiding this comment.
Expert Review — 2 findings
See inline comments for details.
| [InlineData("this is not a uri!", false)] | ||
| [InlineData("https://example.com/", true)] | ||
| [InlineData("https://example.com/page/", true)] | ||
| [InlineData("https://example.com/page?weight=62.5", true)] |
There was a problem hiding this comment.
[moderate] Regression Prevention — The regression case exercises https://example.com/..., but the failing BlazorWebView paths use platform app origins (https://0.0.0.1/... on Android and app://0.0.0.1/... on iOS/MacCatalyst). Add query-dot/fragment-dot cases for those actual origins so the test reproduces the platform scenarios this helper is used for, rather than only a generic HTTPS host.
|
/review -b feature/enhanced-reviewer -p windows |
MauiBot
left a comment
There was a problem hiding this comment.
Expert Review — 2 findings
See inline comments for details.
| Assert.Equal(expected, result); | ||
| } | ||
|
|
||
| [Fact] |
There was a problem hiding this comment.
[minor] Regression Prevention — Test duplication — Five of the six standalone [Fact] methods in this block duplicate [InlineData] cases that already exist in IsBaseOfPage_HandlesVariousUris above:
| Fact method | Duplicate Theory InlineData |
|---|---|
IsBaseOfPage_ReturnsFalse_WhenPathHasFileExtension (line 57) |
("https://example.com/file.txt", false) (line 17) |
IsBaseOfPage_ReturnsTrue_WhenUriIsBaseItself (line 63) |
("https://example.com/", true) (line 13) |
IsBaseOfPage_IgnoresDotInQuery_WhenBaseUriMatches (line 70) |
("https://example.com/page?weight=62.5", true) (line 15) |
IsBaseOfPage_ReturnsFalse_WhenSchemeDiffersFromBase (line 77) |
("ftp://example.com/page", false) (line 19) |
IsBaseOfPage_TreatsFragmentWithDotAsNoExtension (line 100) |
("https://example.com/page#section.1", true) (line 16) |
Consider removing these duplicates and consolidating only the non-redundant case (IsBaseOfPage_DoesNotTreatDotInQueryAsExtension) into the Theory, or keep it as a named Fact with an issue-reference comment (see next finding). Duplicate test cases inflate pass counts without adding coverage and make it harder to identify genuine regression tests at a glance.
| } | ||
|
|
||
| [Fact] | ||
| public void IsBaseOfPage_DoesNotTreatDotInQueryAsExtension() |
There was a problem hiding this comment.
[minor] Regression Prevention — Missing issue reference on primary regression test — IsBaseOfPage_DoesNotTreatDotInQueryAsExtension is the most important test in this file: it is the direct reproduction of issue #25689 (?weight=62.5 being incorrectly identified as a file extension). Add a comment linking it to the issue so reviewers and future maintainers can trace it back to its origin:
// Regression test for https://github.com/dotnet/maui/issues/25689
// A URL with a dot in the query parameter (e.g. ?weight=62.5) must not be
// treated as a file-extension path and must be allowed to fall back to the host page.
[Fact]
public void IsBaseOfPage_DoesNotTreatDotInQueryAsExtension()Without this comment, the test is indistinguishable from the duplicate facts above and its specific regression value is invisible.
kubaflo
left a comment
There was a problem hiding this comment.
Could you please check the ai's suggestions?
The regression tests only exercised a generic https://example.com host, but BlazorWebView uses https://0.0.0.1/ (Android/Windows) and app://0.0.0.1/ (iOS/MacCatalyst) as the app origin. Add a theory covering dot-in-query, dot-in-fragment and real-extension cases for those actual origins so the issue dotnet#25689 scenario is reproduced on the platforms it affects.
|
Hey, thanks for the heads up! Went through the AI comments one by one. Cleaned up the duplicate tests first — a bunch of the The one that actually mattered was the note about the origins. I was only testing against Let me know if there's anything else you'd like me to tweak. |
|
/review -b feature/enhanced-reviewer |
MauiBot
left a comment
There was a problem hiding this comment.
AI Review Summary
@tw4 — new AI review results are available based on this last commit:
a856301.
Test IsBaseOfPage against real platform app origins To request a fresh review after new comments or commits, comment/review rerun.
Review Sessions — click to expand
Gate — Test Before & After Fix
Gate Result: ✅ PASSED
Platform: ANDROID · Base: main · Merge base: e904e900
| Test | Without Fix (expect FAIL) | With Fix (expect PASS) |
|---|---|---|
🧪 UriExtensions_Tests UriExtensions_Tests |
🛠️ BUILD ERROR | ✅ PASS — 24s |
🔴 Without fix — 🧪 UriExtensions_Tests: 🛠️ BUILD ERROR · 136s
Determining projects to restore...
Restored /home/vsts/work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 1.58 sec).
Restored /home/vsts/work/1/s/src/BlazorWebView/tests/MauiBlazorWebView.UnitTests/MauiBlazorWebView.UnitTests.csproj (in 6.41 sec).
Restored /home/vsts/work/1/s/src/Essentials/src/Essentials.csproj (in 3.39 sec).
Restored /home/vsts/work/1/s/src/BlazorWebView/src/Maui/Microsoft.AspNetCore.Components.WebView.Maui.csproj (in 10.85 sec).
Restored /home/vsts/work/1/s/src/Core/src/Core.csproj (in 2.49 sec).
Restored /home/vsts/work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 224 ms).
1 of 7 projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14306429
Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14306429
Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14306429
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.14306429
Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14306429
Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
/home/vsts/work/1/s/src/BlazorWebView/tests/MauiBlazorWebView.UnitTests/UriExtensions_Tests.cs(51,25): error CS1061: 'Uri' does not contain a definition for 'IsBaseOfPage' and no accessible extension method 'IsBaseOfPage' accepting a first argument of type 'Uri' could be found (are you missing a using directive or an assembly reference?) [/home/vsts/work/1/s/src/BlazorWebView/tests/MauiBlazorWebView.UnitTests/MauiBlazorWebView.UnitTests.csproj]
/home/vsts/work/1/s/src/BlazorWebView/tests/MauiBlazorWebView.UnitTests/UriExtensions_Tests.cs(63,23): error CS1061: 'Uri' does not contain a definition for 'IsBaseOfPage' and no accessible extension method 'IsBaseOfPage' accepting a first argument of type 'Uri' could be found (are you missing a using directive or an assembly reference?) [/home/vsts/work/1/s/src/BlazorWebView/tests/MauiBlazorWebView.UnitTests/MauiBlazorWebView.UnitTests.csproj]
/home/vsts/work/1/s/src/BlazorWebView/tests/MauiBlazorWebView.UnitTests/UriExtensions_Tests.cs(78,33): error CS1061: 'Uri' does not contain a definition for 'IsBaseOfPage' and no accessible extension method 'IsBaseOfPage' accepting a first argument of type 'Uri' could be found (are you missing a using directive or an assembly reference?) [/home/vsts/work/1/s/src/BlazorWebView/tests/MauiBlazorWebView.UnitTests/MauiBlazorWebView.UnitTests.csproj]
🟢 With fix — 🧪 UriExtensions_Tests: PASS ✅ · 24s
Determining projects to restore...
All projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14306429
Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14306429
Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14306429
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.14306429
Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14306429
Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
MauiBlazorWebView.UnitTests -> /home/vsts/work/1/s/artifacts/bin/MauiBlazorWebView.UnitTests/Debug/net10.0/Microsoft.Maui.MauiBlazorWebView.UnitTests.dll
Test run for /home/vsts/work/1/s/artifacts/bin/MauiBlazorWebView.UnitTests/Debug/net10.0/Microsoft.Maui.MauiBlazorWebView.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.01] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.29] Discovering: Microsoft.Maui.MauiBlazorWebView.UnitTests
[xUnit.net 00:00:00.53] Discovered: Microsoft.Maui.MauiBlazorWebView.UnitTests
[xUnit.net 00:00:00.56] Starting: Microsoft.Maui.MauiBlazorWebView.UnitTests
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://subdomain.example.com/path/with space", expected: False) [24 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://example.com/file.txt", expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://example.com/test", expected: True) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://example.com/page?weight=62.5", expected: True) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://example.com/page.json?foo=bar", expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://subdomain.example.com/page.html", expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: null, expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://subdomain.example.com/page", expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://subdomain.example.com/page/", expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://example.com/path/with%20encoded%20space", expected: True) [6 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "", expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://subdomain.example.com/test", expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://example.com/page?param=value¶m2=value2", expected: True) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "page/subpage", expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://example.com/page.html", expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://subdomain.example.com/file.txt", expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://subdomain.example.com/folder/file.exe", expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "ftp://subdomain.example.com/page", expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "/relative/path", expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://example.com/", expected: True) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://example.com/path/with/.dot/segment", expected: True) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "this is not a uri!", expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://example.com/page#section.1", expected: True) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "HTTPS://EXAMPLE.COM/PAGE", expected: True) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://subdomain.example.com/path/with/.dot/segme"···, expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://subdomain.example.com/page?param=value&par"···, expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://subdomain.example.com/page?weight=62.5", expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://subdomain.example.com/", expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://example.com/folder/subfolder/", expected: True) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "HTTPS://SUBDOMAIN.EXAMPLE.COM/PAGE", expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://subdomain.example.com/page.json?foo=bar", expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://example.com/path/with space", expected: True) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://subdomain.example.com/page#section.1", expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://example.com/page", expected: True) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://subdomain.example.com/folder/subfolder/", expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://example.com/page/", expected: True) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "ftp://example.com/page", expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://subdomain.example.com/path/with%20encoded%"···, expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesVariousUris(uriString: "https://example.com/folder/file.exe", expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesPlatformAppOrigins(baseUri: "https://0.0.0.1/", uriString: "https://0.0.0.1/customer.json", expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesPlatformAppOrigins(baseUri: "app://0.0.0.1/", uriString: "app://0.0.0.1/customer?weight=62.5", expected: True) [4 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesPlatformAppOrigins(baseUri: "https://0.0.0.1/", uriString: "https://0.0.0.1/customer#section.1", expected: True) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesPlatformAppOrigins(baseUri: "https://0.0.0.1/", uriString: "https://0.0.0.1/customer?weight=62.5", expected: True) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesPlatformAppOrigins(baseUri: "app://0.0.0.1/", uriString: "app://0.0.0.1/customer.json", expected: False) [< 1 ms]
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_HandlesPlatformAppOrigins(baseUri: "app://0.0.0.1/", uriString: "app://0.0.0.1/customer#section.1", expected: True) [< 1 ms]
[xUnit.net 00:00:00.93] Finished: Microsoft.Maui.MauiBlazorWebView.UnitTests
Passed Microsoft.Maui.MauiBlazorWebView.UnitTests.UriExtensions_Tests.IsBaseOfPage_DoesNotTreatDotInQueryAsExtension [< 1 ms]
Test Run Successful.
Total tests: 46
Passed: 46
Total time: 2.6104 Seconds
⚠️ Failure Details
- 🛠️ UriExtensions_Tests without fix: build failed before tests could run
/home/vsts/work/1/s/src/BlazorWebView/tests/MauiBlazorWebView.UnitTests/UriExtensions_Tests.cs(51,25): error CS1061: 'Uri' does not contain a definition for 'IsBaseOfPage' and no accessible extension ...
📁 Fix files reverted (11 files)
Microsoft.Maui-dev.slnMicrosoft.Maui-mac.slnfMicrosoft.Maui-vscode.slnMicrosoft.Maui-windows.slnfMicrosoft.Maui.LegacyControlGallery.slnMicrosoft.Maui.slneng/cake/dotnet.cakeeng/helix.projeng/pipelines/ci-copilot.ymlsrc/BlazorWebView/src/Maui/Extensions/UriExtensions.cssrc/BlazorWebView/src/Maui/Properties/AssemblyInfo.cs
Pre-Flight — Context & Validation
Issue: #25689 - Blazor Hybrid Webview cannot be force reloaded for urls containing query parameters with a dot (.)
PR: #29560 - [BlazorWebView] Fixed Allow force reload for URLs with dots in query parameters
Platforms Affected: Android, iOS, MacCatalyst BlazorWebView (issue labels Android/iOS; helper used by Android/iOS handlers)
Files Changed: 10 implementation/build wiring, 2 test
Key Findings
- Root cause:
Path.HasExtension(uriString)evaluated the entire URI, so query or fragment dots such as?weight=62.5were treated as path file extensions and prevented page fallback/force reload. - PR fix parses absolute URIs, checks only the URI path via
GetComponents(UriComponents.Path, UriFormat.Unescaped), then preservesUri.IsBaseOfsemantics for scheme/host/path matching. - Regression coverage is unit-test based and now wired into
eng/cake/dotnet.cakeandeng/helix.proj; prior review comments specifically requested this wiring and platform-origin cases. - Impacted test type: Unit tests (
src/BlazorWebView/tests/MauiBlazorWebView.UnitTests). No UI category selected for this review because the PR adds helper-level unit coverage rather than UI tests.
Code Review Summary
Verdict: LGTM
Confidence: high
Errors: 0 | Warnings: 0 | Suggestions: 3
Key code review findings:
- 💡 PR description is stale: it says
uri.AbsolutePath, while code usesuri.GetComponents(UriComponents.Path, UriFormat.Unescaped); the committed code is more robust. - 💡 Minor formatting blank line in
src/BlazorWebView/src/Maui/Properties/AssemblyInfo.cs. - 💡 A named regression
[Fact]partially duplicates a theory case, but the issue-reference comment makes it discoverable.
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #29560 | Parse URI, check only unescaped path component for extension, preserve Uri.IsBaseOf, add/wire BlazorWebView unit tests |
✅ PASSED (Gate) | UriExtensions.cs, AssemblyInfo.cs, BlazorWebView unit test project, solution/test wiring |
Original PR; gate result supplied as passed |
Code Review — Deep Analysis
Code Review — PR #29560
Independent Assessment
What this changes: IsBaseOfPage in UriExtensions.cs is refactored to parse the URI first, then extract only the path component via uri.GetComponents(UriComponents.Path, UriFormat.Unescaped) before running Path.HasExtension. Two additional guards are added: a string.IsNullOrWhiteSpace early-exit and Uri.TryCreate(..., UriKind.Absolute, ...) to reject relative or malformed inputs. A new MauiBlazorWebView.UnitTests project is created and wired into eng/cake/dotnet.cake and eng/helix.proj.
Inferred motivation: The old code passed the entire raw URI string to Path.HasExtension. A URL like https://example.com/page?weight=62.5 has .5 near its end, which Path.HasExtension sees as a file extension, so the method returned false (not a page), blocking force-reload. The bug affects Android (WebKitWebViewClient, lines 118, 146) and iOS (BlazorWebViewHandler.iOS.cs, line 317) — both callers pass raw URL strings.
Approach soundness: The fix is direct and well-scoped. Using GetComponents(UriComponents.Path, UriFormat.Unescaped) is strictly superior to the PR description's stated uri.AbsolutePath because it also decodes percent-encoded characters (e.g., /path/with%2Eext -> /path/with.ext) before the extension check, catching disguised extensions. The scheme and host are still validated by the final IsBaseOf call. No alternative simpler fix exists — stripping query strings with regex would be fragile.
Reconciliation with PR Narrative
Author claims: Bug is in Path.HasExtension(uriString) applied to the full raw URI string; fix switches to uri.AbsolutePath; adds input validation with IsNullOrWhiteSpace and TryCreate.
Agreement: The bug description and root cause analysis are exactly right. The claimed behavioral outcome is correct.
Disagreement / discrepancy: The PR description says the fix uses uri.AbsolutePath, but the committed code uses uri.GetComponents(UriComponents.Path, UriFormat.Unescaped). The actual code is more correct than the description states (handles percent-encoded dots) — this looks like the description was written for an earlier iteration and wasn't updated after the final commit.
Findings
💡 Suggestion — PR description is stale: claims uri.AbsolutePath, code uses GetComponents
src/BlazorWebView/src/Maui/Extensions/UriExtensions.cs line 21
The PR description's "After" snippet shows Path.HasExtension(uri.AbsolutePath), but the committed code uses Path.HasExtension(uri.GetComponents(UriComponents.Path, UriFormat.Unescaped)). The committed code is the right choice because it handles %2E-encoded dots that AbsolutePath would miss.
💡 Suggestion — Spurious blank line in AssemblyInfo.cs
src/BlazorWebView/src/Maui/Properties/AssemblyInfo.cs lines 4-5
The added using System.Runtime.CompilerServices; introduces a double blank line before [assembly: Preserve]. Minor formatting issue.
💡 Suggestion — IsBaseOfPage_DoesNotTreatDotInQueryAsExtension duplicates a Theory case
src/BlazorWebView/tests/MauiBlazorWebView.UnitTests/UriExtensions_Tests.cs line 59
The standalone [Fact] is structurally already covered by the weight=62.5 theory case. Keeping it with the issue-reference comment is acceptable for discoverability.
Devil's Advocate
GetComponents is safe after TryCreate. UriKind.Absolute accepts Android https://0.0.0.1/... and iOS/MacCatalyst app://0.0.0.1/... origins, which the tests cover. Windows does not call this helper. The unit test project is wired into both local cake unit-test and Helix lists.
Verdict: LGTM
Confidence: high
Summary: The fix is mechanically correct: extracting only the URI path component before Path.HasExtension directly eliminates the false-positive that blocked force-reload for URLs with dots in query parameters or fragments. Tests are comprehensive, wired into CI, and cover the real platform origins. Findings are suggestions only.
Fix — Analysis & Comparison
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| 1 | try-fix | Parse URI and check only uri.Segments final segment for extension |
✅ PASS | 2 files | Current tests pass, but encoded-dot paths such as file%2Etxt are weaker than PR fix because Uri.Segments remains percent-encoded |
| 2 | try-fix | Parse URI, slice final AbsolutePath segment, decode with Uri.UnescapeDataString, then check extension |
✅ PASS | 2 files | Handles encoded dots, but manually reimplements behavior the PR gets from GetComponents(UriComponents.Path, UriFormat.Unescaped) |
| PR | PR #29560 | Parse URI, check unescaped path component with GetComponents(UriComponents.Path, UriFormat.Unescaped), preserve Uri.IsBaseOf, add/wire BlazorWebView unit tests |
✅ PASSED (Gate) | 12 files | Original PR; gate result supplied as passed |
Cross-Pollination
| Model | Round | New Ideas? | Details |
|---|---|---|---|
| maui-expert-reviewer | 1 | Yes | Suggested final-segment strategy; noted encoded-dot weakness |
| maui-expert-reviewer | 2 | Yes | Suggested explicit final-segment decode to address encoded dots |
| maui-expert-reviewer | 3 | No | Correct approaches converge on stripping query/fragment, decoding percent-encoding, and checking path extension; PR fix is the smallest BCL-native expression of that invariant |
Exhausted: Yes
Selected Fix: PR #29560 — It passes the supplied gate, is more robust than candidate #1, and is simpler/less manual than candidate #2. No candidate is demonstrably better than the PR fix.
Report — Final Recommendation
Comparative Report — PR #29560
Candidates compared
| Candidate | Approach | Regression result | Assessment |
|---|---|---|---|
pr |
Parse an absolute URI, check Path.HasExtension only on uri.GetComponents(UriComponents.Path, UriFormat.Unescaped), then preserve baseUri.IsBaseOf(uri). Adds and wires BlazorWebView unit tests. |
✅ Passed gate | Best balance of correctness, simplicity, and coverage. |
pr-plus-reviewer |
Same as pr; expert reviewer produced no actionable findings to apply. |
✅ Same as pr |
Equivalent to pr; no improvement over submitted fix. |
try-fix-1 |
Parse an absolute URI and check only the final uri.Segments entry for an extension. |
✅ Passed candidate tests | Correct for the reported query/fragment-dot bug, but weaker than pr because Uri.Segments remains percent-encoded, so encoded-dot file paths such as file%2Etxt can evade extension detection. |
try-fix-2 |
Parse an absolute URI, manually slice the final AbsolutePath segment, decode it with Uri.UnescapeDataString, and check that segment for an extension. |
✅ Passed candidate tests | Robust, but more manual and complex than pr; it reimplements behavior the PR gets from BCL URI component extraction. |
Ranking
pr— The submitted fix wins. It passed the supplied gate, fixes the root cause by checking only the unescaped path component, preserves existingIsBaseOfsemantics, and includes CI-wired unit coverage for the relevant platform origins.pr-plus-reviewer— Equivalent toprbecause the expert reviewer found no actionable inline issues. It ranks just belowpronly because it is not a distinct improvement.try-fix-2— Also passes tests and handles encoded dots, but it is more verbose and manually slices/decodes URI segments whereGetComponents(UriComponents.Path, UriFormat.Unescaped)is clearer and less error-prone.try-fix-1— Passes the candidate tests but is least robust among passing candidates because it checks percent-encoded segments without decoding them.
No candidate failed regression tests, so ranking is based on correctness margin, implementation simplicity, and maintainability.
Winning candidate
Winner: pr
The raw PR fix is the best candidate. It uses the most direct BCL-native expression of the desired invariant: ignore query and fragment data for file-extension detection while preserving URI base checks. The expert review did not identify any actionable changes, so pr-plus-reviewer does not improve on it.
Future Action — review latest findings
No alternative fix was selected for this run. Review the session findings and CI results before merging.
|
/review rerun |
…parameters (#29560) <!-- 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! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Description of Change This PR fixes a bug in `BlazorWebView` where URLs containing dots (`.`) in **query parameters** (e.g., `?weight=62.5`) could not be force reloaded. The issue was caused by using `Path.HasExtension(uriString)`, which mistakenly treated dots in query strings as if they were part of a file extension. --- #### ❌ Before The original logic: ```csharp if (Path.HasExtension(uriString)) return false; ``` This evaluates the entire URI string — including query parameters — which incorrectly caused `?value=62.5` to be treated as a file reference, breaking reload behavior. --- #### ✅ After This PR introduces a safer and more accurate approach: ```csharp if (Path.HasExtension(uri.AbsolutePath)) return false; ``` Along with additional improvements: * Validates input with `string.IsNullOrWhiteSpace` * Uses `Uri.TryCreate` with `UriKind.Absolute` to safely parse the input and reject relative or malformed URIs * Scheme/host matching is preserved through `Uri.IsBaseOf`, so URIs whose scheme or host does not match the configured base URI are still rejected as before This ensures that only the actual path is evaluated for file extensions, allowing query strings to contain dots without affecting navigation or reload logic. --- ### Issues Fixed Fixes #25689 Cover test result <img width="477" alt="Screenshot 2025-05-16 at 22 54 41" src="https://github.com/user-attachments/assets/55e5948b-17e6-4abd-9fad-d01172855c43" /> --- **Note:** @mattleibow The previous PR might have been truly cursed 😅 — I created a new branch, rewrote the unit test project from scratch, and everything worked like a charm this time. No issues so far, and I'm optimistic GitHub Actions will behave too! 🧙♂️✨ Also, big thanks to @mattleibow for the support and guidance — your insights helped me see things more clearly! 🙏
…parameters (#29560) <!-- 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! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Description of Change This PR fixes a bug in `BlazorWebView` where URLs containing dots (`.`) in **query parameters** (e.g., `?weight=62.5`) could not be force reloaded. The issue was caused by using `Path.HasExtension(uriString)`, which mistakenly treated dots in query strings as if they were part of a file extension. --- #### ❌ Before The original logic: ```csharp if (Path.HasExtension(uriString)) return false; ``` This evaluates the entire URI string — including query parameters — which incorrectly caused `?value=62.5` to be treated as a file reference, breaking reload behavior. --- #### ✅ After This PR introduces a safer and more accurate approach: ```csharp if (Path.HasExtension(uri.AbsolutePath)) return false; ``` Along with additional improvements: * Validates input with `string.IsNullOrWhiteSpace` * Uses `Uri.TryCreate` with `UriKind.Absolute` to safely parse the input and reject relative or malformed URIs * Scheme/host matching is preserved through `Uri.IsBaseOf`, so URIs whose scheme or host does not match the configured base URI are still rejected as before This ensures that only the actual path is evaluated for file extensions, allowing query strings to contain dots without affecting navigation or reload logic. --- ### Issues Fixed Fixes #25689 Cover test result <img width="477" alt="Screenshot 2025-05-16 at 22 54 41" src="https://github.com/user-attachments/assets/55e5948b-17e6-4abd-9fad-d01172855c43" /> --- **Note:** @mattleibow The previous PR might have been truly cursed 😅 — I created a new branch, rewrote the unit test project from scratch, and everything worked like a charm this time. No issues so far, and I'm optimistic GitHub Actions will behave too! 🧙♂️✨ Also, big thanks to @mattleibow for the support and guidance — your insights helped me see things more clearly! 🙏
…parameters (#29560) <!-- 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! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Description of Change This PR fixes a bug in `BlazorWebView` where URLs containing dots (`.`) in **query parameters** (e.g., `?weight=62.5`) could not be force reloaded. The issue was caused by using `Path.HasExtension(uriString)`, which mistakenly treated dots in query strings as if they were part of a file extension. --- #### ❌ Before The original logic: ```csharp if (Path.HasExtension(uriString)) return false; ``` This evaluates the entire URI string — including query parameters — which incorrectly caused `?value=62.5` to be treated as a file reference, breaking reload behavior. --- #### ✅ After This PR introduces a safer and more accurate approach: ```csharp if (Path.HasExtension(uri.AbsolutePath)) return false; ``` Along with additional improvements: * Validates input with `string.IsNullOrWhiteSpace` * Uses `Uri.TryCreate` with `UriKind.Absolute` to safely parse the input and reject relative or malformed URIs * Scheme/host matching is preserved through `Uri.IsBaseOf`, so URIs whose scheme or host does not match the configured base URI are still rejected as before This ensures that only the actual path is evaluated for file extensions, allowing query strings to contain dots without affecting navigation or reload logic. --- ### Issues Fixed Fixes #25689 Cover test result <img width="477" alt="Screenshot 2025-05-16 at 22 54 41" src="https://github.com/user-attachments/assets/55e5948b-17e6-4abd-9fad-d01172855c43" /> --- **Note:** @mattleibow The previous PR might have been truly cursed 😅 — I created a new branch, rewrote the unit test project from scratch, and everything worked like a charm this time. No issues so far, and I'm optimistic GitHub Actions will behave too! 🧙♂️✨ Also, big thanks to @mattleibow for the support and guidance — your insights helped me see things more clearly! 🙏
…parameters (#29560) <!-- 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! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Description of Change This PR fixes a bug in `BlazorWebView` where URLs containing dots (`.`) in **query parameters** (e.g., `?weight=62.5`) could not be force reloaded. The issue was caused by using `Path.HasExtension(uriString)`, which mistakenly treated dots in query strings as if they were part of a file extension. --- #### ❌ Before The original logic: ```csharp if (Path.HasExtension(uriString)) return false; ``` This evaluates the entire URI string — including query parameters — which incorrectly caused `?value=62.5` to be treated as a file reference, breaking reload behavior. --- #### ✅ After This PR introduces a safer and more accurate approach: ```csharp if (Path.HasExtension(uri.AbsolutePath)) return false; ``` Along with additional improvements: * Validates input with `string.IsNullOrWhiteSpace` * Uses `Uri.TryCreate` with `UriKind.Absolute` to safely parse the input and reject relative or malformed URIs * Scheme/host matching is preserved through `Uri.IsBaseOf`, so URIs whose scheme or host does not match the configured base URI are still rejected as before This ensures that only the actual path is evaluated for file extensions, allowing query strings to contain dots without affecting navigation or reload logic. --- ### Issues Fixed Fixes #25689 Cover test result <img width="477" alt="Screenshot 2025-05-16 at 22 54 41" src="https://github.com/user-attachments/assets/55e5948b-17e6-4abd-9fad-d01172855c43" /> --- **Note:** @mattleibow The previous PR might have been truly cursed 😅 — I created a new branch, rewrote the unit test project from scratch, and everything worked like a charm this time. No issues so far, and I'm optimistic GitHub Actions will behave too! 🧙♂️✨ Also, big thanks to @mattleibow for the support and guidance — your insights helped me see things more clearly! 🙏
…parameters (#29560) <!-- 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! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Description of Change This PR fixes a bug in `BlazorWebView` where URLs containing dots (`.`) in **query parameters** (e.g., `?weight=62.5`) could not be force reloaded. The issue was caused by using `Path.HasExtension(uriString)`, which mistakenly treated dots in query strings as if they were part of a file extension. --- #### ❌ Before The original logic: ```csharp if (Path.HasExtension(uriString)) return false; ``` This evaluates the entire URI string — including query parameters — which incorrectly caused `?value=62.5` to be treated as a file reference, breaking reload behavior. --- #### ✅ After This PR introduces a safer and more accurate approach: ```csharp if (Path.HasExtension(uri.AbsolutePath)) return false; ``` Along with additional improvements: * Validates input with `string.IsNullOrWhiteSpace` * Uses `Uri.TryCreate` with `UriKind.Absolute` to safely parse the input and reject relative or malformed URIs * Scheme/host matching is preserved through `Uri.IsBaseOf`, so URIs whose scheme or host does not match the configured base URI are still rejected as before This ensures that only the actual path is evaluated for file extensions, allowing query strings to contain dots without affecting navigation or reload logic. --- ### Issues Fixed Fixes #25689 Cover test result <img width="477" alt="Screenshot 2025-05-16 at 22 54 41" src="https://github.com/user-attachments/assets/55e5948b-17e6-4abd-9fad-d01172855c43" /> --- **Note:** @mattleibow The previous PR might have been truly cursed 😅 — I created a new branch, rewrote the unit test project from scratch, and everything worked like a charm this time. No issues so far, and I'm optimistic GitHub Actions will behave too! 🧙♂️✨ Also, big thanks to @mattleibow for the support and guidance — your insights helped me see things more clearly! 🙏
…parameters (#29560) <!-- 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! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Description of Change This PR fixes a bug in `BlazorWebView` where URLs containing dots (`.`) in **query parameters** (e.g., `?weight=62.5`) could not be force reloaded. The issue was caused by using `Path.HasExtension(uriString)`, which mistakenly treated dots in query strings as if they were part of a file extension. --- #### ❌ Before The original logic: ```csharp if (Path.HasExtension(uriString)) return false; ``` This evaluates the entire URI string — including query parameters — which incorrectly caused `?value=62.5` to be treated as a file reference, breaking reload behavior. --- #### ✅ After This PR introduces a safer and more accurate approach: ```csharp if (Path.HasExtension(uri.AbsolutePath)) return false; ``` Along with additional improvements: * Validates input with `string.IsNullOrWhiteSpace` * Uses `Uri.TryCreate` with `UriKind.Absolute` to safely parse the input and reject relative or malformed URIs * Scheme/host matching is preserved through `Uri.IsBaseOf`, so URIs whose scheme or host does not match the configured base URI are still rejected as before This ensures that only the actual path is evaluated for file extensions, allowing query strings to contain dots without affecting navigation or reload logic. --- ### Issues Fixed Fixes #25689 Cover test result <img width="477" alt="Screenshot 2025-05-16 at 22 54 41" src="https://github.com/user-attachments/assets/55e5948b-17e6-4abd-9fad-d01172855c43" /> --- **Note:** @mattleibow The previous PR might have been truly cursed 😅 — I created a new branch, rewrote the unit test project from scratch, and everything worked like a charm this time. No issues so far, and I'm optimistic GitHub Actions will behave too! 🧙♂️✨ Also, big thanks to @mattleibow for the support and guidance — your insights helped me see things more clearly! 🙏
…parameters (#29560) <!-- 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! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Description of Change This PR fixes a bug in `BlazorWebView` where URLs containing dots (`.`) in **query parameters** (e.g., `?weight=62.5`) could not be force reloaded. The issue was caused by using `Path.HasExtension(uriString)`, which mistakenly treated dots in query strings as if they were part of a file extension. --- #### ❌ Before The original logic: ```csharp if (Path.HasExtension(uriString)) return false; ``` This evaluates the entire URI string — including query parameters — which incorrectly caused `?value=62.5` to be treated as a file reference, breaking reload behavior. --- #### ✅ After This PR introduces a safer and more accurate approach: ```csharp if (Path.HasExtension(uri.AbsolutePath)) return false; ``` Along with additional improvements: * Validates input with `string.IsNullOrWhiteSpace` * Uses `Uri.TryCreate` with `UriKind.Absolute` to safely parse the input and reject relative or malformed URIs * Scheme/host matching is preserved through `Uri.IsBaseOf`, so URIs whose scheme or host does not match the configured base URI are still rejected as before This ensures that only the actual path is evaluated for file extensions, allowing query strings to contain dots without affecting navigation or reload logic. --- ### Issues Fixed Fixes #25689 Cover test result <img width="477" alt="Screenshot 2025-05-16 at 22 54 41" src="https://github.com/user-attachments/assets/55e5948b-17e6-4abd-9fad-d01172855c43" /> --- **Note:** @mattleibow The previous PR might have been truly cursed 😅 — I created a new branch, rewrote the unit test project from scratch, and everything worked like a charm this time. No issues so far, and I'm optimistic GitHub Actions will behave too! 🧙♂️✨ Also, big thanks to @mattleibow for the support and guidance — your insights helped me see things more clearly! 🙏
…parameters (#29560) <!-- 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! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Description of Change This PR fixes a bug in `BlazorWebView` where URLs containing dots (`.`) in **query parameters** (e.g., `?weight=62.5`) could not be force reloaded. The issue was caused by using `Path.HasExtension(uriString)`, which mistakenly treated dots in query strings as if they were part of a file extension. --- #### ❌ Before The original logic: ```csharp if (Path.HasExtension(uriString)) return false; ``` This evaluates the entire URI string — including query parameters — which incorrectly caused `?value=62.5` to be treated as a file reference, breaking reload behavior. --- #### ✅ After This PR introduces a safer and more accurate approach: ```csharp if (Path.HasExtension(uri.AbsolutePath)) return false; ``` Along with additional improvements: * Validates input with `string.IsNullOrWhiteSpace` * Uses `Uri.TryCreate` with `UriKind.Absolute` to safely parse the input and reject relative or malformed URIs * Scheme/host matching is preserved through `Uri.IsBaseOf`, so URIs whose scheme or host does not match the configured base URI are still rejected as before This ensures that only the actual path is evaluated for file extensions, allowing query strings to contain dots without affecting navigation or reload logic. --- ### Issues Fixed Fixes #25689 Cover test result <img width="477" alt="Screenshot 2025-05-16 at 22 54 41" src="https://github.com/user-attachments/assets/55e5948b-17e6-4abd-9fad-d01172855c43" /> --- **Note:** @mattleibow The previous PR might have been truly cursed 😅 — I created a new branch, rewrote the unit test project from scratch, and everything worked like a charm this time. No issues so far, and I'm optimistic GitHub Actions will behave too! 🧙♂️✨ Also, big thanks to @mattleibow for the support and guidance — your insights helped me see things more clearly! 🙏
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
This PR fixes a bug in
BlazorWebViewwhere URLs containing dots (.) in query parameters (e.g.,?weight=62.5) could not be force reloaded. The issue was caused by usingPath.HasExtension(uriString), which mistakenly treated dots in query strings as if they were part of a file extension.❌ Before
The original logic:
This evaluates the entire URI string — including query parameters — which incorrectly caused
?value=62.5to be treated as a file reference, breaking reload behavior.✅ After
This PR introduces a safer and more accurate approach:
Along with additional improvements:
string.IsNullOrWhiteSpaceUri.TryCreatewithUriKind.Absoluteto safely parse the input and reject relative or malformed URIsUri.IsBaseOf, so URIs whose scheme or host does not match the configured base URI are still rejected as beforeThis ensures that only the actual path is evaluated for file extensions, allowing query strings to contain dots without affecting navigation or reload logic.
Issues Fixed
Fixes #25689
Cover test result

Note: @mattleibow
The previous PR might have been truly cursed 😅 — I created a new branch, rewrote the unit test project from scratch, and everything worked like a charm this time.
No issues so far, and I'm optimistic GitHub Actions will behave too! 🧙♂️✨
Also, big thanks to @mattleibow for the support and guidance — your insights helped me see things more clearly! 🙏