Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[Problem/Bug]: Class not registered when invoking host object event #5145

Closed
parzivail opened this issue Mar 7, 2025 · 1 comment
Closed
Labels
bug Something isn't working

Comments

@parzivail
Copy link

parzivail commented Mar 7, 2025

What happened?

Unable to subscribe to events from within JavaScript.

The docs state,

addEventListener | This method only exists on proxies for .NET objects. Bind the JavaScript handler to the C# event, so that the JavaScript handler can be called through the C# event. For example, chrome.webview.hostObjects.sample.addEventListener('TestEvent', () => { alert('Invoked from remote');}); bind an anonymous JavaScript function to a C# event called 'TestEvent'.

however, I cannot get this functionality to work.

Removing the event handler attachment within JS prevents the exception from occurring. I assume this is because there is, then, nothing subscribed to the event from the C# side, and the event invocation is a no-op. Luckily, this proves that the event registration works as intended from the JS side.

Importance

Important. My app's user experience is significantly compromised.

Runtime Channel

Stable release (WebView2 Runtime)

Runtime Version

128.0.2739.54

SDK Version

1.0.3065.39

Framework

WPF

Operating System

Windows 10

OS Version

19045.4842

Repro steps

Registering a host object:

[ComVisible(true)]
public class AppState
{
	private int _testProp = 0;

	public int TestProp
	{
		get
		{
			Console.WriteLine($"Get TestProp ({_testProp})");
			return _testProp;
		}
		set
		{
			Console.WriteLine($"Set TestProp to {value}");
			SetField(ref _testProp, value);
		}
	}


	public event Action? PropertyChanged;

	protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
	{
		PropertyChanged?.Invoke();
	}

	protected bool SetField<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
	{
		if (EqualityComparer<T>.Default.Equals(field, value)) return false;
		field = value;
		OnPropertyChanged(propertyName);
		return true;
	}
}

as such

// obtain an instance of AppState, I have mine as a field within my WPF window's backing class
AppState state = ...
// assuming a WPF element named myWebView, and invoking this method in the CoreWebView2InitializationCompleted callback:
myWebView.CoreWebView2.AddHostObjectToScript("state", state);

with the following JS having run inside the browser:

chrome.webview.hostObjects.state.addEventListener('PropertyChanged', () => { console.log('fired'); });

then, firing the PropertyChanged event by setting a property:

AppState state = ...
state.TestProp = 1;

will cause the following exception:

System.Runtime.InteropServices.COMException (0x8007046B): Class not registered

   at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode)
   at Microsoft.Web.WebView2.Core.JSHandlerWrapper.Invoke(Object[] args)
   at DelegateHandler(JSHandlerWrapper)
   at WebviewTest2.AppState.OnPropertyChanged(String propertyName) in C:\Users\cnewman\RiderProjects\WebviewTest2\WebviewTest2\MainWindow.xaml.cs:line 37
   at WebviewTest2.AppState.SetField[T](T& field, T value, String propertyName) in C:\Users\cnewman\RiderProjects\WebviewTest2\WebviewTest2\MainWindow.xaml.cs:line 44
   at WebviewTest2.AppState.set_TestProp(Int32 value) in C:\Users\cnewman\RiderProjects\WebviewTest2\WebviewTest2\MainWindow.xaml.cs:line 28

Repros in Edge Browser

Don't know

Regression

Don't know

Last working version (if regression)

No response

@parzivail parzivail added the bug Something isn't working label Mar 7, 2025
@parzivail
Copy link
Author

I was able to solve this issue by forcing the event handler to be invoked on the dispatcher:

	protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
	{
		_ = Application.Current?.Dispatcher.InvokeAsync(() =>
		{
			PropertyChanged?.Invoke();
		});
	}

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant