maui: BlazorWinFormsApp and BlazorWpfApp throw NullReferenceException when using ExampleJsInterop in .NET 6 Preview 3

Describe the bug

If ExampleJsInterop is called from WinForms or from WPF it throws a NullReferenceException

To Reproduce

In WinForms:

  • open https://github.com/dotnet/aspnetcore/tree/main/src/Components/WebView/Samples/BlazorWinFormsApp

  • Form1.cs, add WebviewAppShared.ExampleJsInterop exampleJsInterop; to class Form1

  • add exampleJsInterop.Prompt("Hello world!"); to button1_Click

  • add serviceCollection.AddScoped<WebviewAppShared.ExampleJsInterop>(); below var serviceCollection = new ServiceCollection();

  • replace blazorWebView1.Services = serviceCollection.BuildServiceProvider(); with

      IServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
      blazorWebView1.Services = serviceProvider;
      exampleJsInterop = serviceProvider.GetRequiredService<WebviewAppShared.ExampleJsInterop>();
    
  • run app

  • click on Click to see counter value

In WPF:

  • open https://github.com/dotnet/aspnetcore/tree/main/src/Components/WebView/Samples/BlazorWpfApp

  • MainWindow.xaml.cs, add WebviewAppShared.ExampleJsInterop exampleJsInterop; to class MainWindow

  • add exampleJsInterop.Prompt("Hello world!"); to Button_Click

  • add serviceCollection.AddScoped<WebviewAppShared.ExampleJsInterop>(); below var serviceCollection = new ServiceCollection();

  • replace Resources.Add("services", serviceCollection.BuildServiceProvider()); with

      IServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
      Resources.Add("services", serviceProvider);
      exampleJsInterop = serviceProvider.GetRequiredService<WebviewAppShared.ExampleJsInterop>();
    
  • run app

  • click on Check counter

Exceptions (if any)

System.NullReferenceException: 'Object reference not set to an instance of an object.'

Further technical details

  • ASP.NET Core version: 16.10.127.22515
  • The IDE (VS / VS Code/ VS4Mac) you’re running on, and its version: Visual Studio 2019 - Version 16.10.0 Preview 1.0
  • Include the output of dotnet --info
.NET SDK (reflecting any global.json):
 Version:   6.0.100-preview.3.21202.5
 Commit:    aee38a6dd4

Runtime Environment:
 OS Name:     Windows
 OS Version:  6.3.9600
 OS Platform: Windows
 RID:         win81-x64
 Base Path:   C:\Program Files\dotnet\sdk\6.0.100-preview.3.21202.5\

Host (useful for support):
  Version: 6.0.0-preview.3.21201.4
  Commit:  236cb21e3c

.NET SDKs installed:
  3.1.406 [C:\Program Files\dotnet\sdk]
  5.0.200-preview.21077.7 [C:\Program Files\dotnet\sdk]
  5.0.201 [C:\Program Files\dotnet\sdk]
  6.0.100-preview.3.21202.5 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 3.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNe
tCore.App]
  Microsoft.AspNetCore.App 3.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNe
tCore.App]
  Microsoft.AspNetCore.App 3.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspN
etCore.App]
  Microsoft.AspNetCore.App 3.1.13 [C:\Program Files\dotnet\shared\Microsoft.AspN
etCore.App]
  Microsoft.AspNetCore.App 5.0.2 [C:\Program Files\dotnet\shared\Microsoft.AspNe
tCore.App]
  Microsoft.AspNetCore.App 5.0.4 [C:\Program Files\dotnet\shared\Microsoft.AspNe
tCore.App]
  Microsoft.AspNetCore.App 6.0.0-preview.3.21201.13 [C:\Program Files\dotnet\sha
red\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 3.1.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.
App]
  Microsoft.NETCore.App 3.1.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.
App]
  Microsoft.NETCore.App 3.1.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore
.App]
  Microsoft.NETCore.App 3.1.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore
.App]
  Microsoft.NETCore.App 5.0.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.
App]
  Microsoft.NETCore.App 5.0.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.
App]
  Microsoft.NETCore.App 6.0.0-preview.3.21201.4 [C:\Program Files\dotnet\shared\
Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.1.9 [C:\Program Files\dotnet\shared\Microsoft.W
indowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.12 [C:\Program Files\dotnet\shared\Microsoft.
WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.13 [C:\Program Files\dotnet\shared\Microsoft.
WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.2 [C:\Program Files\dotnet\shared\Microsoft.W
indowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.4 [C:\Program Files\dotnet\shared\Microsoft.W
indowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.0-preview.3.21201.3 [C:\Program Files\dotnet\
shared\Microsoft.WindowsDesktop.App]

To install additional .NET runtimes or SDKs:
  https://aka.ms/dotnet-download

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 16 (12 by maintainers)

Most upvoted comments

@Eilon The slightly awkward thing is that, each time the page inside the BlazorWebView reloads, we set up a new scope. We have to do that because (for example) you have a new JS context with no pre-existing state so we have to reset everything to do with it. It’s like reloading the page with WebAssembly or Server - those create new DI contexts too.

So given this, if some code outside that system asks for a scope, which scope does it get? One that might become obsolete later if the page is reloaded? Kind of dangerous, but represents the truth about what’s going on.

We could address this simply by exposing some IServiceProvider? CurrentPageServices { get; set; } property from WebViewManager whose value may be null (if no page has yet loaded) or may change (if the page navigates) and then trust the developer to understand this and not store a reference to the instance anywhere. TBH this is probably not too bad really.

Alternatively we could have some kind of RunAsync(Func<IServiceProvider, Task>) method on WebViewManager that’s some kind of combo of “dispatch” and “give me the current service provider” to encourage people to treat it as a transient thing. Not sure people will follow the reasoning though.

What do you think?

I noticed we aren’t providing the appropriate JS/Dotnet object reference json converters during IPC sending/receiving. Currently working on a fix for that.

Turned out to be a non-issue, so this issue doesn’t seem to be related to my changes in JS Interop.