3

I'm using a webview2-control in a winforms application. I use messages to communicate between c# and Javascript

  • window.chrome.webview.addEventListener / window.chrome.webview.postMessage in Javascript
  • event .CoreWebView2.WebMessageReceived and method CoreWebView2.PostWebMessageAsString in C#

The communication works BUT only after the page in webview2 has been somehow refreshed. The first message sent by c# is always ignored/not received by JS. The messages after that are correcly received and processed.

My UI code:

public GUI()
{
    InitializeComponent();
    browser.Source = new Uri(System.IO.Path.GetFullPath("HTML/ui.html"));
    InitializeAsync();
}
async void InitializeAsync()
{
    await browser.EnsureCoreWebView2Async(null);
    browser.CoreWebView2.WebMessageReceived += MessageReceived;
    }
void MessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs args)
{
    String content = args.TryGetWebMessageAsString();
    if (content.StartsWith("getData"))
    {
        ReadDataFromCATIA();
        var serializerSettings = new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects };
        string jsonRootNode = JsonConvert.SerializeObject(this.RootNode, Formatting.Indented, serializerSettings); //here I've got the message I want to post
        //String input = args.TryGetWebMessageAsString();
        //MessageBox.Show("string from JS: " + input);
        browser.CoreWebView2.PostWebMessageAsString(jsonRootNode);
    }
    else //object received
    {
        ProductNode received = JsonConvert.DeserializeObject<ProductNode>(content);
        MessageBox.Show(received.PartNumber + " received");
    }
}

and my JS in ui.html

window.chrome.webview.addEventListener('message', event => {
    alert(event.data);
    WriteDataFromCsharp(event.data);
});
function WriteDataFromCsharp(data) {
    var target = document.getElementById('target');
    if (target === null) { alert('target not found') };
    //alert(target.id);
    //target.textContent = event.data;

    rootNode = JSON.parse(data);
    target.innerHTML = addTable(rootNode); //addTable create an HTML table from the deserialized object rootNode
}
function RequestData() {
    //function triggered by a button on the html page
    //alert('post to c#');
    window.chrome.webview.postMessage('getData');
}

So far, i've tried to:

  • ensure the javascript is as late as possible in the page (defer, at the end of body). No changes.
  • inject the javascript to the page after it has been loaded using .CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(jsCode). Same behavior.
  • inject the javascript after once the event NavigationCompleted has fired. same behavior.

What do I miss ?

Florent Cauwe
  • 76
  • 1
  • 4
  • I suggest to initialize in `OnLoad()` or the `Load` handler (making them `async`) and subscribe to `CoreWebView2InitializationCompleted`. Some examples here: [e.NewWindow = (CoreWebView2)sender still results in a separate instance](https://stackoverflow.com/a/68790332/7444103) and here: [Which WebView2 event/function can be use to replace ScriptNotify Webview event?](https://stackoverflow.com/a/68278278/7444103) (slightly different language, same thing) – Jimi Feb 17 '22 at 09:19
  • I've tried these two points: - move the initialization to the onload method, add the MessageREceived event in InitializationCompleted (Js still in html) --> same behavior - add the JS code with AddScriptToExecuteOnDocumentCreatedAsync in the event NavigationCompleted --> same behavior – Florent Cauwe Feb 17 '22 at 09:47
  • It looks like you're posting to the Document only when you receive a message from the Document, but I don't see any call to `window.chrome.webview.postMessage()`. The JavaScript only adds an event listener that waits for messages sent by the host. – Jimi Feb 17 '22 at 10:37
  • sorry, i've omitted this part of my code. I've got a button on my html page triggering the request. I've edited my question. – Florent Cauwe Feb 17 '22 at 10:42
  • So, are you saying that clicking this Button doesn't raise `WebMessageReceived`? Or the event is raised, but the Document doesn't receive the post-back message from your App, so the listener of `message` doesn't trigger? -- `ReadDataFromCATIA();` doesn't do anything here, but I assume you're calling that for a reason. After that, you're calling again `args.TryGetWebMessageAsString();`, but that's supposed to contain `getData`. There's something else missing here. -- Remove the MessageBoxes, write to the Output Pane of VS instead. – Jimi Feb 17 '22 at 10:51
  • the idea is to click on a button in JS, Js send a message containing GetData to c#, C# read some Infomation in CATIA (method ReadDataFromCATIA() and send an answer. the first time, c# get the request from JS, read the data and send the response. However, JS does not seem to process it. It seems that the chrome.webview.addEventListener does not fire. – Florent Cauwe Feb 17 '22 at 11:23
  • I suggest you test this in a simplified *environment*, without any other calls to anything, just post back a message when you receive one from the Document. Use those example as a guideline. -- As a *proof of concept* (so to speak), `BeginInvoke()` the call to `.CoreWebView2.PostWebMessageAsString(...)` – Jimi Feb 17 '22 at 11:55

1 Answers1

1

Finally found the culprit: in my HTML-page, i've used a "submit" instead of "button". With

<input type="button" value="Load data from V5" onclick="RequestData()" />

The page behavior is as expected.

Florent Cauwe
  • 76
  • 1
  • 4
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Feb 17 '22 at 14:00
  • I will give the extra info: A `submit` button will refresh the page doing a `post`. – Poul Bak Feb 17 '22 at 23:41