Skip to content

Commit f09180f

Browse files
authored
Add WebViewManager.TryDispatchAsync() method (#46644)
This enables callers to invoke methods with access to the scoped services used in BlazorWebView controls.
1 parent 05b6233 commit f09180f

File tree

3 files changed

+38
-5
lines changed

3 files changed

+38
-5
lines changed

src/Components/WebView/WebView/src/PageContext.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ internal sealed class PageContext : IAsyncDisposable
2525
public WebViewNavigationManager NavigationManager { get; }
2626
public WebViewJSRuntime JSRuntime { get; }
2727
public WebViewRenderer Renderer { get; }
28+
public IServiceProvider ServiceProvider => _serviceScope.ServiceProvider;
2829

2930
public PageContext(
3031
Dispatcher dispatcher,
@@ -35,17 +36,16 @@ public PageContext(
3536
string startUrl)
3637
{
3738
_serviceScope = serviceScope;
38-
var services = serviceScope.ServiceProvider;
3939

40-
NavigationManager = (WebViewNavigationManager)services.GetRequiredService<NavigationManager>();
40+
NavigationManager = (WebViewNavigationManager)ServiceProvider.GetRequiredService<NavigationManager>();
4141
NavigationManager.AttachToWebView(ipcSender, baseUrl, startUrl);
4242

43-
JSRuntime = (WebViewJSRuntime)services.GetRequiredService<IJSRuntime>();
43+
JSRuntime = (WebViewJSRuntime)ServiceProvider.GetRequiredService<IJSRuntime>();
4444
JSRuntime.AttachToWebView(ipcSender);
4545

46-
var loggerFactory = services.GetRequiredService<ILoggerFactory>();
46+
var loggerFactory = ServiceProvider.GetRequiredService<ILoggerFactory>();
4747
var jsComponents = new JSComponentInterop(jsComponentsConfiguration);
48-
Renderer = new WebViewRenderer(services, dispatcher, ipcSender, loggerFactory, JSRuntime, jsComponents);
48+
Renderer = new WebViewRenderer(ServiceProvider, dispatcher, ipcSender, loggerFactory, JSRuntime, jsComponents);
4949
}
5050

5151
public async ValueTask DisposeAsync()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
#nullable enable
2+
Microsoft.AspNetCore.Components.WebView.WebViewManager.TryDispatchAsync(System.Action<System.IServiceProvider!>! workItem) -> System.Threading.Tasks.Task<bool>!

src/Components/WebView/WebView/src/WebViewManager.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,38 @@ protected void MessageReceived(Uri sourceUri, string message)
166166
});
167167
}
168168

169+
/// <summary>
170+
/// Calls the specified <paramref name="workItem"/> asynchronously and passes in the scoped services available to Razor components.
171+
/// This method will not throw any exceptions if it is unable to call the specified <paramref name="workItem"/>, but if it does call it, then exceptions may still be thrown by the <paramref name="workItem"/> itself.
172+
/// </summary>
173+
/// <param name="workItem">The action to call.</param>
174+
/// <returns>Returns a <see cref="Task"/> representing <c>true</c> if the <paramref name="workItem"/> was called, or <c>false</c> if it was not called because Blazor is not currently running.</returns>
175+
/// <exception cref="ArgumentNullException">Thrown if <paramref name="workItem"/> is <c>null</c>.</exception>
176+
public async Task<bool> TryDispatchAsync(Action<IServiceProvider> workItem)
177+
{
178+
ArgumentNullException.ThrowIfNull(workItem);
179+
180+
var capturedCurrentPageContext = _currentPageContext;
181+
182+
if (capturedCurrentPageContext is null)
183+
{
184+
return false;
185+
}
186+
187+
return await capturedCurrentPageContext.Renderer.Dispatcher.InvokeAsync(() =>
188+
{
189+
if (capturedCurrentPageContext != _currentPageContext)
190+
{
191+
// If the captured context doesn't match the current context, that means that there was something like
192+
// a navigation event that caused the original page to be detached and a new one attached. Thus, we
193+
// cancel out of the operation and return failure.
194+
return false;
195+
}
196+
workItem(_currentPageContext.ServiceProvider);
197+
return true;
198+
});
199+
}
200+
169201
/// <summary>
170202
/// Tries to provide the response content for a given network request.
171203
/// </summary>

0 commit comments

Comments
 (0)