Skip to content

Commit 63a0376

Browse files
RedthCopilot
andcommitted
[BlazorWebView] Public API for external BlazorWebView backends
Third-party BlazorWebView handlers can already be registered through the public IBlazorWebViewHandler + UsePlatformHandler contract, but three pieces of the handler contract were still internal, forcing external backends to either skip functionality or duplicate MAUI source. Adds the smallest additive, backward-compatible seams for each: - BlazorWebViewInitializedEventArgs.NativeWebView: a platform-neutral object property so a handler on a target framework without a built-in MAUI backend can surface its native control. On target frameworks where the strongly typed WebView property exists, both are backed by the same value (WebView now reads through NativeWebView with an 'as' conversion, so it returns null rather than throwing on a mismatch). Existing app code reading e.WebView is unaffected. - RootComponent.AddToWebViewManagerAsync / RemoveFromWebViewManagerAsync are now public, so external handlers reuse MAUI's validation and ordering instead of reimplementing them. Both now null-check the manager argument. - BlazorWebViewStaticContentHotReload: a public seam over the internal StaticContentHotReloadManager exposing AttachToWebViewManagerIfEnabled and TryReplaceResponseContent, so external handlers can participate in MAUI Blazor static content hot reload with identical behavior. Adds src/BlazorWebView/tests/MauiBlazorWebView.ExternalHandler.UnitTests, an assembly that is deliberately not granted InternalsVisibleTo. It hosts a fake external handler and WebViewManager and proves all three seams are usable without privileged access or copied source, including a test that fails if InternalsVisibleTo is ever added. Also documents the contract in docs/design/BlazorWebViewExternalBackends.md. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent bedd1b1 commit 63a0376

26 files changed

Lines changed: 975 additions & 7 deletions

Microsoft.Maui-dev.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiBlazorWebView.DeviceTes
139139
EndProject
140140
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiBlazorWebView.UnitTests", "src\BlazorWebView\tests\MauiBlazorWebView.UnitTests\MauiBlazorWebView.UnitTests.csproj", "{00E708AA-402D-4BB5-AD88-348274F8E1DF}"
141141
EndProject
142+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiBlazorWebView.ExternalHandler.UnitTests", "src\BlazorWebView\tests\MauiBlazorWebView.ExternalHandler.UnitTests\MauiBlazorWebView.ExternalHandler.UnitTests.csproj", "{536778E4-FAAA-4A16-A961-388AA91EA813}"
143+
EndProject
142144
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SharedSource", "SharedSource", "{4F2926C8-43AB-4328-A735-D9EAD699F81D}"
143145
ProjectSection(SolutionItems) = preProject
144146
src\BlazorWebView\src\SharedSource\AutoCloseOnReadCompleteStream.cs = src\BlazorWebView\src\SharedSource\AutoCloseOnReadCompleteStream.cs
@@ -461,6 +463,10 @@ Global
461463
{00E708AA-402D-4BB5-AD88-348274F8E1DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
462464
{00E708AA-402D-4BB5-AD88-348274F8E1DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
463465
{00E708AA-402D-4BB5-AD88-348274F8E1DF}.Release|Any CPU.Build.0 = Release|Any CPU
466+
{536778E4-FAAA-4A16-A961-388AA91EA813}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
467+
{536778E4-FAAA-4A16-A961-388AA91EA813}.Debug|Any CPU.Build.0 = Debug|Any CPU
468+
{536778E4-FAAA-4A16-A961-388AA91EA813}.Release|Any CPU.ActiveCfg = Release|Any CPU
469+
{536778E4-FAAA-4A16-A961-388AA91EA813}.Release|Any CPU.Build.0 = Release|Any CPU
464470
{5B56A734-D53C-4635-A53E-F889FCFCDD66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
465471
{5B56A734-D53C-4635-A53E-F889FCFCDD66}.Debug|Any CPU.Build.0 = Debug|Any CPU
466472
{5B56A734-D53C-4635-A53E-F889FCFCDD66}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
@@ -727,6 +733,7 @@ Global
727733
{A9C514B9-1EE2-4A12-8E8A-CE16D87545C3} = {1614D1A4-5C3D-4D5B-8C89-426E37A564EF}
728734
{5FEA7500-0ACE-4C26-9A7B-2EB3958CBBC6} = {A9C514B9-1EE2-4A12-8E8A-CE16D87545C3}
729735
{00E708AA-402D-4BB5-AD88-348274F8E1DF} = {A9C514B9-1EE2-4A12-8E8A-CE16D87545C3}
736+
{536778E4-FAAA-4A16-A961-388AA91EA813} = {A9C514B9-1EE2-4A12-8E8A-CE16D87545C3}
730737
{4F2926C8-43AB-4328-A735-D9EAD699F81D} = {ED7F28E0-D0AF-417D-983D-3D874EEE8554}
731738
{5B56A734-D53C-4635-A53E-F889FCFCDD66} = {C564DDD6-DE79-45CD-88EA-3F690481572A}
732739
{E8728693-3537-4007-A4DB-9F9634548755} = {E8AD265B-3C67-4640-AC58-A522F9FB3361}

Microsoft.Maui-mac.slnf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"src\\BlazorWebView\\samples\\WebViewAppShared\\WebViewAppShared.csproj",
77
"src\\BlazorWebView\\src\\Maui\\Microsoft.AspNetCore.Components.WebView.Maui.csproj",
88
"src\\BlazorWebView\\tests\\DeviceTests\\MauiBlazorWebView.DeviceTests.csproj",
9+
"src\\BlazorWebView\\tests\\MauiBlazorWebView.ExternalHandler.UnitTests\\MauiBlazorWebView.ExternalHandler.UnitTests.csproj",
910
"src\\BlazorWebView\\tests\\MauiBlazorWebView.UnitTests\\MauiBlazorWebView.UnitTests.csproj",
1011
"src\\Controls\\Foldable\\src\\Controls.Foldable.csproj",
1112
"src\\Controls\\Maps\\src\\Controls.Maps.csproj",

Microsoft.Maui-vscode.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiBlazorWebView.DeviceTes
129129
EndProject
130130
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiBlazorWebView.UnitTests", "src\BlazorWebView\tests\MauiBlazorWebView.UnitTests\MauiBlazorWebView.UnitTests.csproj", "{00E708AA-402D-4BB5-AD88-348274F8E1DF}"
131131
EndProject
132+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiBlazorWebView.ExternalHandler.UnitTests", "src\BlazorWebView\tests\MauiBlazorWebView.ExternalHandler.UnitTests\MauiBlazorWebView.ExternalHandler.UnitTests.csproj", "{536778E4-FAAA-4A16-A961-388AA91EA813}"
133+
EndProject
132134
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SharedSource", "SharedSource", "{4F2926C8-43AB-4328-A735-D9EAD699F81D}"
133135
ProjectSection(SolutionItems) = preProject
134136
src\BlazorWebView\src\SharedSource\AutoCloseOnReadCompleteStream.cs = src\BlazorWebView\src\SharedSource\AutoCloseOnReadCompleteStream.cs
@@ -408,6 +410,10 @@ Global
408410
{00E708AA-402D-4BB5-AD88-348274F8E1DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
409411
{00E708AA-402D-4BB5-AD88-348274F8E1DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
410412
{00E708AA-402D-4BB5-AD88-348274F8E1DF}.Release|Any CPU.Build.0 = Release|Any CPU
413+
{536778E4-FAAA-4A16-A961-388AA91EA813}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
414+
{536778E4-FAAA-4A16-A961-388AA91EA813}.Debug|Any CPU.Build.0 = Debug|Any CPU
415+
{536778E4-FAAA-4A16-A961-388AA91EA813}.Release|Any CPU.ActiveCfg = Release|Any CPU
416+
{536778E4-FAAA-4A16-A961-388AA91EA813}.Release|Any CPU.Build.0 = Release|Any CPU
411417
{5B56A734-D53C-4635-A53E-F889FCFCDD66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
412418
{5B56A734-D53C-4635-A53E-F889FCFCDD66}.Debug|Any CPU.Build.0 = Debug|Any CPU
413419
{5B56A734-D53C-4635-A53E-F889FCFCDD66}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
@@ -635,6 +641,7 @@ Global
635641
{A9C514B9-1EE2-4A12-8E8A-CE16D87545C3} = {1614D1A4-5C3D-4D5B-8C89-426E37A564EF}
636642
{5FEA7500-0ACE-4C26-9A7B-2EB3958CBBC6} = {A9C514B9-1EE2-4A12-8E8A-CE16D87545C3}
637643
{00E708AA-402D-4BB5-AD88-348274F8E1DF} = {A9C514B9-1EE2-4A12-8E8A-CE16D87545C3}
644+
{536778E4-FAAA-4A16-A961-388AA91EA813} = {A9C514B9-1EE2-4A12-8E8A-CE16D87545C3}
638645
{4F2926C8-43AB-4328-A735-D9EAD699F81D} = {ED7F28E0-D0AF-417D-983D-3D874EEE8554}
639646
{5B56A734-D53C-4635-A53E-F889FCFCDD66} = {C564DDD6-DE79-45CD-88EA-3F690481572A}
640647
{E8728693-3537-4007-A4DB-9F9634548755} = {E8AD265B-3C67-4640-AC58-A522F9FB3361}

Microsoft.Maui-windows.slnf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"src\\BlazorWebView\\src\\WindowsForms\\Microsoft.AspNetCore.Components.WebView.WindowsForms.csproj",
1111
"src\\BlazorWebView\\src\\Wpf\\Microsoft.AspNetCore.Components.WebView.Wpf.csproj",
1212
"src\\BlazorWebView\\tests\\DeviceTests\\MauiBlazorWebView.DeviceTests.csproj",
13+
"src\\BlazorWebView\\tests\\MauiBlazorWebView.ExternalHandler.UnitTests\\MauiBlazorWebView.ExternalHandler.UnitTests.csproj",
1314
"src\\BlazorWebView\\tests\\MauiBlazorWebView.UnitTests\\MauiBlazorWebView.UnitTests.csproj",
1415
"src\\Controls\\Foldable\\src\\Controls.Foldable.csproj",
1516
"src\\Controls\\Maps\\src\\Controls.Maps.csproj",

Microsoft.Maui.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiBlazorWebView.DeviceTes
139139
EndProject
140140
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiBlazorWebView.UnitTests", "src\BlazorWebView\tests\MauiBlazorWebView.UnitTests\MauiBlazorWebView.UnitTests.csproj", "{00E708AA-402D-4BB5-AD88-348274F8E1DF}"
141141
EndProject
142+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiBlazorWebView.ExternalHandler.UnitTests", "src\BlazorWebView\tests\MauiBlazorWebView.ExternalHandler.UnitTests\MauiBlazorWebView.ExternalHandler.UnitTests.csproj", "{536778E4-FAAA-4A16-A961-388AA91EA813}"
143+
EndProject
142144
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SharedSource", "SharedSource", "{4F2926C8-43AB-4328-A735-D9EAD699F81D}"
143145
ProjectSection(SolutionItems) = preProject
144146
src\BlazorWebView\src\SharedSource\AutoCloseOnReadCompleteStream.cs = src\BlazorWebView\src\SharedSource\AutoCloseOnReadCompleteStream.cs
@@ -450,6 +452,10 @@ Global
450452
{00E708AA-402D-4BB5-AD88-348274F8E1DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
451453
{00E708AA-402D-4BB5-AD88-348274F8E1DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
452454
{00E708AA-402D-4BB5-AD88-348274F8E1DF}.Release|Any CPU.Build.0 = Release|Any CPU
455+
{536778E4-FAAA-4A16-A961-388AA91EA813}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
456+
{536778E4-FAAA-4A16-A961-388AA91EA813}.Debug|Any CPU.Build.0 = Debug|Any CPU
457+
{536778E4-FAAA-4A16-A961-388AA91EA813}.Release|Any CPU.ActiveCfg = Release|Any CPU
458+
{536778E4-FAAA-4A16-A961-388AA91EA813}.Release|Any CPU.Build.0 = Release|Any CPU
453459
{5B56A734-D53C-4635-A53E-F889FCFCDD66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
454460
{5B56A734-D53C-4635-A53E-F889FCFCDD66}.Debug|Any CPU.Build.0 = Debug|Any CPU
455461
{5B56A734-D53C-4635-A53E-F889FCFCDD66}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
@@ -708,6 +714,7 @@ Global
708714
{A9C514B9-1EE2-4A12-8E8A-CE16D87545C3} = {1614D1A4-5C3D-4D5B-8C89-426E37A564EF}
709715
{5FEA7500-0ACE-4C26-9A7B-2EB3958CBBC6} = {A9C514B9-1EE2-4A12-8E8A-CE16D87545C3}
710716
{00E708AA-402D-4BB5-AD88-348274F8E1DF} = {A9C514B9-1EE2-4A12-8E8A-CE16D87545C3}
717+
{536778E4-FAAA-4A16-A961-388AA91EA813} = {A9C514B9-1EE2-4A12-8E8A-CE16D87545C3}
711718
{4F2926C8-43AB-4328-A735-D9EAD699F81D} = {ED7F28E0-D0AF-417D-983D-3D874EEE8554}
712719
{5B56A734-D53C-4635-A53E-F889FCFCDD66} = {C564DDD6-DE79-45CD-88EA-3F690481572A}
713720
{E8728693-3537-4007-A4DB-9F9634548755} = {E8AD265B-3C67-4640-AC58-A522F9FB3361}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# External BlazorWebView backends
2+
3+
`BlazorWebView` ships built-in handlers for Android, iOS, MacCatalyst and Windows. A third-party
4+
package can supply a handler for any other platform by implementing
5+
`Microsoft.AspNetCore.Components.WebView.Maui.IBlazorWebViewHandler` and registering it with
6+
`IMauiBlazorWebViewBuilder.UsePlatformHandler`.
7+
8+
This document describes the public seams such a backend needs. Everything here is usable from a
9+
package that only references the shipped MAUI NuGet packages — no `InternalsVisibleTo`, no
10+
reflection, and no copied source. `src/BlazorWebView/tests/MauiBlazorWebView.ExternalHandler.UnitTests`
11+
is an in-repo assembly that is deliberately *not* granted `InternalsVisibleTo` and exercises each of
12+
these seams the way an external backend would.
13+
14+
## Registration
15+
16+
```csharp
17+
builder.Services
18+
.AddMauiBlazorWebView()
19+
.UsePlatformHandler<MyPlatformBlazorWebViewHandler>();
20+
```
21+
22+
Registration is last-registration-wins through the MAUI handler collection, so call
23+
`UsePlatformHandler` *after* `AddMauiBlazorWebView()` and after any downstream library that calls
24+
`AddMauiBlazorWebView()` again.
25+
26+
## Surfacing the native web view
27+
28+
`BlazorWebViewInitializedEventArgs` declares a strongly typed `WebView` property only for the target
29+
frameworks that MAUI has a built-in backend for. A backend for any other platform sets the
30+
platform-neutral `NativeWebView` property instead:
31+
32+
```csharp
33+
VirtualView.BlazorWebViewInitializing(new BlazorWebViewInitializingEventArgs());
34+
VirtualView.BlazorWebViewInitialized(new BlazorWebViewInitializedEventArgs
35+
{
36+
NativeWebView = PlatformView,
37+
});
38+
```
39+
40+
On target frameworks where `WebView` exists, both properties are backed by the same value: assigning
41+
`WebView` assigns `NativeWebView`, and `WebView` returns whatever `NativeWebView` holds — or `null`
42+
if the stored value is not of the platform's web view type. Existing app code that reads
43+
`e.WebView` on Android, iOS, MacCatalyst or Windows is unaffected.
44+
45+
## Root components
46+
47+
`RootComponent.AddToWebViewManagerAsync` and `RootComponent.RemoveFromWebViewManagerAsync` apply the
48+
validation that MAUI's built-in handlers rely on (a `Selector` is required for both, and a
49+
`ComponentType` is required to add). A backend should call them rather than reimplementing the
50+
validation, so that error messages and ordering stay consistent across platforms:
51+
52+
```csharp
53+
foreach (var rootComponent in VirtualView.RootComponents)
54+
{
55+
// Before the page is attached this completes synchronously.
56+
_ = rootComponent.AddToWebViewManagerAsync(_webViewManager);
57+
}
58+
```
59+
60+
Call both methods on the `WebViewManager.Dispatcher` thread, and keep handling
61+
`RootComponentsCollection.CollectionChanged` so components added or removed after startup are
62+
applied to the manager.
63+
64+
## Static content hot reload
65+
66+
Static content hot reload (serving updated `wwwroot` assets, most notably CSS, without restarting
67+
the app) is exposed through `BlazorWebViewStaticContentHotReload`. A backend participates in two
68+
places, mirroring what the built-in handlers do.
69+
70+
Once, after creating the `WebViewManager` and before navigating:
71+
72+
```csharp
73+
BlazorWebViewStaticContentHotReload.AttachToWebViewManagerIfEnabled(_webViewManager);
74+
```
75+
76+
And while resolving each static content request, before the response is handed to the web view:
77+
78+
```csharp
79+
BlazorWebViewStaticContentHotReload.TryReplaceResponseContent(
80+
_contentRootRelativeToAppRoot,
81+
requestAbsoluteUri,
82+
ref statusCode,
83+
ref content,
84+
headers);
85+
```
86+
87+
Both members are no-ops when hot reload is unavailable — that is, when
88+
`System.Reflection.Metadata.MetadataUpdater.IsSupported` is `false` — so they can be called
89+
unconditionally. Static content hot reload is distinct from Razor component hot reload, which needs
90+
no handler participation.
91+
92+
## Windows note
93+
94+
On Windows, a handler that owns a `WebView2` must either expose it directly as its `PlatformView`,
95+
so the framework can close it when the window is destroyed, or close the wrapped control from its
96+
own disconnect logic. This preserves the built-in workaround for microsoft-ui-xaml issue 6872.

eng/helix.proj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
<XUnitProject Include="$(RepoRoot)src/Essentials/test/UnitTests/Essentials.UnitTests.csproj" />
5454
<XUnitProject Include="$(RepoRoot)src/Graphics/tests/Graphics.Tests/Graphics.Tests.csproj" />
5555
<XUnitProject Include="$(RepoRoot)src/BlazorWebView/tests/MauiBlazorWebView.UnitTests/MauiBlazorWebView.UnitTests.csproj" />
56+
<XUnitProject Include="$(RepoRoot)src/BlazorWebView/tests/MauiBlazorWebView.ExternalHandler.UnitTests/MauiBlazorWebView.ExternalHandler.UnitTests.csproj" />
5657
</ItemGroup>
5758

5859
<!-- Prepare the staging directory for MSBuild test payloads - runs early during Restore -->
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
5+
namespace Microsoft.AspNetCore.Components.WebView.Maui
6+
{
7+
/// <summary>
8+
/// Provides the seam that lets a handler implementing <see cref="IBlazorWebViewHandler"/> participate in
9+
/// MAUI Blazor static content hot reload, which serves updated <c>wwwroot</c> assets (most notably CSS)
10+
/// without restarting the app.
11+
/// </summary>
12+
/// <remarks>
13+
/// A handler participates in two places, mirroring what the built-in handlers do:
14+
/// <list type="number">
15+
/// <item><description>
16+
/// Call <see cref="AttachToWebViewManagerIfEnabled(WebViewManager)"/> once, right after creating its
17+
/// <see cref="WebViewManager"/> and before navigating, so the notifier root component is registered.
18+
/// </description></item>
19+
/// <item><description>
20+
/// Call <see cref="TryReplaceResponseContent(string, string, ref int, ref Stream, IDictionary{string, string})"/>
21+
/// while resolving a static content request, so hot-reloaded content replaces the on-disk content.
22+
/// </description></item>
23+
/// </list>
24+
/// Both members are no-ops when hot reload is unavailable (that is, when
25+
/// <see cref="System.Reflection.Metadata.MetadataUpdater.IsSupported"/> is <see langword="false"/>), so
26+
/// handlers can call them unconditionally. Static content hot reload is a development-time feature and is
27+
/// independent of Razor component hot reload, which does not require any handler participation.
28+
/// </remarks>
29+
public static class BlazorWebViewStaticContentHotReload
30+
{
31+
/// <summary>
32+
/// Registers the static content hot reload notifier with the specified <see cref="WebViewManager"/>
33+
/// when hot reload is supported by the current runtime; otherwise does nothing.
34+
/// </summary>
35+
/// <param name="webViewManager">The <see cref="WebViewManager"/> to attach to.</param>
36+
/// <remarks>
37+
/// Call this once per <see cref="WebViewManager"/> instance, after construction and before navigating.
38+
/// Calling it more than once for the same manager throws, because the notifier uses a fixed root
39+
/// component selector.
40+
/// </remarks>
41+
/// <exception cref="ArgumentNullException">Thrown if <paramref name="webViewManager"/> is <see langword="null"/>.</exception>
42+
public static void AttachToWebViewManagerIfEnabled(WebViewManager webViewManager)
43+
{
44+
ArgumentNullException.ThrowIfNull(webViewManager);
45+
46+
StaticContentHotReloadManager.AttachToWebViewManagerIfEnabled(webViewManager);
47+
}
48+
49+
/// <summary>
50+
/// Replaces the response for a static content request with hot-reloaded content when an update for
51+
/// that content is available; otherwise leaves the response untouched.
52+
/// </summary>
53+
/// <param name="contentRootRelativePath">The content root of the app's static assets relative to the
54+
/// app root, as passed to the <see cref="WebViewManager"/>.</param>
55+
/// <param name="requestAbsoluteUri">The absolute URI of the request being served.</param>
56+
/// <param name="responseStatusCode">The response status code. Set to <c>200</c> when content is replaced.</param>
57+
/// <param name="responseContent">The response content. Replaced with the hot-reloaded content, and the
58+
/// original stream is closed, when content is replaced.</param>
59+
/// <param name="responseHeaders">The response headers. The <c>Content-Type</c> header is updated when the
60+
/// hot reload payload specifies one.</param>
61+
/// <returns><see langword="true"/> if the response was replaced with hot-reloaded content; otherwise <see langword="false"/>.</returns>
62+
/// <exception cref="ArgumentNullException">Thrown if <paramref name="contentRootRelativePath"/>,
63+
/// <paramref name="requestAbsoluteUri"/>, <paramref name="responseContent"/> or
64+
/// <paramref name="responseHeaders"/> is <see langword="null"/>.</exception>
65+
public static bool TryReplaceResponseContent(
66+
string contentRootRelativePath,
67+
string requestAbsoluteUri,
68+
ref int responseStatusCode,
69+
ref Stream responseContent,
70+
IDictionary<string, string> responseHeaders)
71+
{
72+
ArgumentNullException.ThrowIfNull(contentRootRelativePath);
73+
ArgumentNullException.ThrowIfNull(requestAbsoluteUri);
74+
ArgumentNullException.ThrowIfNull(responseContent);
75+
ArgumentNullException.ThrowIfNull(responseHeaders);
76+
77+
return StaticContentHotReloadManager.TryReplaceResponseContent(
78+
contentRootRelativePath,
79+
requestAbsoluteUri,
80+
ref responseStatusCode,
81+
ref responseContent,
82+
responseHeaders);
83+
}
84+
}
85+
}

src/BlazorWebView/src/Maui/PublicAPI/net-android/PublicAPI.Unshipped.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,10 @@ Microsoft.AspNetCore.Components.WebView.Maui.BlazorWebViewStaticContentRequest.B
1313
Microsoft.AspNetCore.Components.WebView.Maui.BlazorWebViewStaticContentRequest.ContentType.get -> string!
1414
Microsoft.AspNetCore.Components.WebView.Maui.BlazorWebViewStaticContentRequest.Uri.get -> System.Uri!
1515
Microsoft.AspNetCore.Components.WebView.Maui.IBlazorWebView.StaticContentCacheControlProvider.get -> System.Func<Microsoft.AspNetCore.Components.WebView.Maui.BlazorWebViewStaticContentRequest!, string?>?
16+
Microsoft.AspNetCore.Components.WebView.BlazorWebViewInitializedEventArgs.NativeWebView.get -> object?
17+
Microsoft.AspNetCore.Components.WebView.BlazorWebViewInitializedEventArgs.NativeWebView.set -> void
18+
Microsoft.AspNetCore.Components.WebView.Maui.BlazorWebViewStaticContentHotReload
19+
Microsoft.AspNetCore.Components.WebView.Maui.RootComponent.AddToWebViewManagerAsync(Microsoft.AspNetCore.Components.WebView.WebViewManager! webViewManager) -> System.Threading.Tasks.Task!
20+
Microsoft.AspNetCore.Components.WebView.Maui.RootComponent.RemoveFromWebViewManagerAsync(Microsoft.AspNetCore.Components.WebView.WebViewManager! webviewManager) -> System.Threading.Tasks.Task!
21+
static Microsoft.AspNetCore.Components.WebView.Maui.BlazorWebViewStaticContentHotReload.AttachToWebViewManagerIfEnabled(Microsoft.AspNetCore.Components.WebView.WebViewManager! webViewManager) -> void
22+
static Microsoft.AspNetCore.Components.WebView.Maui.BlazorWebViewStaticContentHotReload.TryReplaceResponseContent(string! contentRootRelativePath, string! requestAbsoluteUri, ref int responseStatusCode, ref System.IO.Stream! responseContent, System.Collections.Generic.IDictionary<string!, string!>! responseHeaders) -> bool

0 commit comments

Comments
 (0)