0

Problem: HostObjectToScript throws exception when trying to execute a passed-in function

Scenario: WPF application has a WebView2 tab embedded and exposes an object for scripting using CoreWebView2.AddHostObjectToScript(). I'm able to access this object using Javascript:

window.blah = chrome.webview.hostObjects.sync.blah_blah_external;

and call functions without issue. Everything works just fine until I call a function that creates a class and passes in a function as parameter to that class. The parameters pass in just fine, but when the code tries to call the functions it throws the System.NotImplementedException exception. This worked just fine before replacing the IE-based browser control with WebView2, so I'm hoping it's something simple I'm missing.

Environment:

The Host object is exposed with this:

variablename.CoreWebView2.AddHostObjectToScript("blah_blah_external", new MYTABExternal(_tabHost));

The Host Object looks like this:

namespace MYTAB
{
    [ClassInterface(ClassInterfaceType.AutoDual)]
    [ComVisibleAttribute(true)]
    public class MYTABExternal
    {
        public void createTHING(String user, dynamic onError)
        {
            CLASSNAME currentCLASSNAME = new CLASSNAME(user, onError);
            currentCLASSNAME.create();
        }
    }
}

The class that throws the error is setup as such:

namespace MYTAB
{
    public class CLASSNAME
    {
       
        protected String user;
        protected dynamic onError;

        public CLASSNAME(String user, dynamic onError)
        {
            this.user= user;
            this.onError = onError;
        }

        public void create()
        {            
            BackgroundWorker backgroundWorker = new BackgroundWorker();
            backgroundWorker.WorkerSupportsCancellation = true;
            backgroundWorker.WorkerReportsProgress = true;
            backgroundWorker.DoWork -= backgroundWorker_DoWork;
            backgroundWorker.DoWork += backgroundWorker_DoWork;
            backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;  //Tell the user how the process went
            RequestContext requestContext = EXTERNALLIBRARY.SharedContext.Instance;
            backgroundWorker.RunWorkerAsync(requestContext);
           
        }

        /// <summary>
        /// Fires when the background task is complete
        /// </summary>
        private void backgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                this.onError("The creation process was cancelled"); // HERE'S THE EXCEPTION
            }
        }
...

The javascript to call the function is:

window.setTimeout(function () {
  window.blah.createTHING(btn.attr('data-requestor-user-id'), function (onErrorResponse) {
                                  dialog.$modal.addClass('type-danger');
                                  dialog.setMessage('<p>' + onErrorResponse + '</p>');
                                  spinner.stop();
  });
}, 1000);

Exception stack trace is:

Exception thrown: 'System.NotImplementedException' in System.Dynamic.dll
Exception thrown: 'System.NotImplementedException' in System.Dynamic.dll
System.Transactions Critical: 0 : <TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Critical"><TraceIdentifier>http://msdn.microsoft.com/TraceCodes/System/ActivityTracing/2004/07/Reliability/Exception/Unhandled</TraceIdentifier><Description>Unhandled exception</Description><AppDomain>BLAH</AppDomain><Exception><ExceptionType>System.NotImplementedException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>The method or operation is not implemented.</Message><StackTrace>   at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
   at System.Dynamic.ComRuntimeHelpers.GetITypeInfoFromIDispatch(IDispatch dispatch, Boolean throwIfMissingExpectedTypeInfo)
   at System.Dynamic.IDispatchComObject.EnsureScanDefinedMethods()
   at System.Dynamic.IDispatchComObject.System.Dynamic.IDynamicMetaObjectProvider.GetMetaObject(Expression parameter)
   at System.Dynamic.DynamicMetaObject.Create(Object value, Expression expression)
   at System.Dynamic.DynamicMetaObjectBinder.Bind(Object[] args, ReadOnlyCollection`1 parameters, LabelTarget returnLabel)
   at System.Runtime.CompilerServices.CallSiteBinder.BindCore[T](CallSite`1 site, Object[] args)
   at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
   at CallSite.Target(Closure , CallSite , Object , String )
   at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid2[T0,T1](CallSite site, T0 arg0, T1 arg1)
   at MyTab.CLASSNAME.backgroundWorker_RunWorkerCompleted(Object sender, RunWorkerCompletedEventArgs e) in C:\CLASSNAME.cs:line 145
   at System.ComponentModel.BackgroundWorker.OnRunWorkerCompleted(RunWorkerCompletedEventArgs e)
   at System.ComponentModel.BackgroundWorker.AsyncOperationCompleted(Object arg)
   at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()</StackTrace><ExceptionString>System.NotImplementedException: The method or operation is not implemented.
   at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
   at System.Dynamic.ComRuntimeHelpers.GetITypeInfoFromIDispatch(IDispatch dispatch, Boolean throwIfMissingExpectedTypeInfo)
   at System.Dynamic.IDispatchComObject.EnsureScanDefinedMethods()
   at System.Dynamic.IDispatchComObject.System.Dynamic.IDynamicMetaObjectProvider.GetMetaObject(Expression parameter)
   at System.Dynamic.DynamicMetaObject.Create(Object value, Expression expression)
   at System.Dynamic.DynamicMetaObjectBinder.Bind(Object[] args, ReadOnlyCollection`1 parameters, LabelTarget returnLabel)
   at System.Runtime.CompilerServices.CallSiteBinder.BindCore[T](CallSite`1 site, Object[] args)
   at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
   at CallSite.Target(Closure , CallSite , Object , String )
   at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid2[T0,T1](CallSite site, T0 arg0, T1 arg1)
   at MyTab.CLASSNAME.backgroundWorker_RunWorkerCompleted(Object sender, RunWorkerCompletedEventArgs e) in C:\\CLASSNAME.cs:line 145
   at System.ComponentModel.BackgroundWorker.OnRunWorkerCompleted(RunWorkerCompletedEventArgs e)
   at System.ComponentModel.BackgroundWorker.AsyncOperationCompleted(Object arg)
   at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()</ExceptionString><DataItems><Data><Key>ApplicationName</Key><Value>BLAH</Value></Data></DataItems></Exception></TraceRecord>
  • 2
    Interactions with the WebView2 should all happen on its UI thread. Do you get the same error if you call onError from the UI thread? Otherwise this could be a bug in WebView2 and you can file the bug here: https://github.com/MicrosoftEdge/WebView2Feedback/issues – David Risney Feb 05 '21 at 19:36
  • Thanks for the feedback and the tip! I checked the thread detail in the debugger and tried putting the function call into the code outside the background worker. I didn't see an exception when I did this, but it also didn't work and ultimately doesn't fit into the flow. I'm going to post this to the WebView2 feedback section also. Thanks again – ProcessTruster Feb 09 '21 at 18:09

0 Answers0