Skip to content

JavaScript calling .NET Async Method with Return Value on HostObject fail to return correct Value #822

@RickStrahl

Description

@RickStrahl

I'm trying to call back from JavaScript into .NET using a Host object registered into the document. In experimenting I'm finding inonsistent behavior with the object registered.

For my test class I have:

  [ClassInterface(ClassInterfaceType.AutoDual)]
    [ComVisible(true)]
    public class DotnetInterop
    {

        // asyn just because
        public async Task<string> HelloWorld(string name)
        {
                   await Task.Delay(200);
                   var res = $"Hello World, {name}! - Message: 'This text was retrieved from .NET and shown here in JavaScript.'\n" +
                      "Button click in .NET -> JavaScript Function calls Hello World in .NET -> Returns message to JavaScript";
            return res;
        }
        ...
}

Then during init:

webView.CoreWebView2.AddHostObjectToScript("mm", Interop);

Now when I call this from JavaScript like this:

async function callHelloWorldDotnet(name) {
    // .NET object reference (async)
    var msg = await window.chrome.webview.hostObjects.mm.HelloWorld(name);
    alert(msg);
}

I get a 'null' result. Also tried a promise directly. The .NET method gets called and returns a result, but the client is not picking it up as an async function or via a promise. If I return a promise the promise says pending.

Now I can get this to work by changing the method to a non-async method:

public string HelloWorld(string name)
{
    var res = $"Hello World, {name}! - Message: 'This text was retrieved from .NET and shown here in JavaScript.'\n" +
              "Button click in .NET -> JavaScript Function calls Hello World in .NET -> Returns message to JavaScript";
    return res;
}

Now using that same client side code works. It also works with sync from the client. Both of these work (in their respective async/non-async function contexts):

// sync
var msg = window.chrome.webview.hostObjects.mm.sync.HelloWorld(name);

// async
var msg = await window.chrome.webview.hostObjects.mm.HelloWorld(name);

Summary:

  • I can call the method both sync and async from JavaScript if .NET Method is not async
  • I can call the method both sync and async from JavaScript if the .NET is async and no value is returned (fire and forget)
  • I cannot call the method either async or sync from JavaScript if .NET method is async and returns a value

Question: When do we need Async .NET Host Methods?

My question is when the client is calling the host using the async instance shouldn't the method calls on the host object be async as well or at least be supported as async?

All of this feels very inconsistent, but it's not clear if this is by design or a pre-release bug...

In my actual application for now I've been avoiding async calls for results that return values, because I needed it to work both with WV2 and WebBrowser so I use sync. However, in my test form which is green field I can use aysnc through all of it and expected the called methods also to be async.

Note it looks to me that the methods fired are getting invoked as async methods - meaning the code in the async methods executes as it should with async semantics. But the results are not picked up as TASK based async values and returned as is rather than fixing up the async call.

Either way a clear answer on how this is supposed to work would be helpful.

Desired/Expected behavior:

  • If using the .sync object from JS call with sync semantics
  • If not use the .sync object from JS call with async/await semantics both on client and host

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions