'Replacing System.Windows.Forms.WebBrowser with Microsoft.Web.WebView2.WinForms.WebView2 in WinForms apps

I am upgrading a WinForms C# .NET 4.8 Framework application and replacing the embedded browser System.Windows.Forms.WebBrowser with Microsoft.Web.WebView2.WinForms.WebView2. I’m invoking some browser-hosted JavaScript functions from my C# code, and also my JavaScript functions do invoke some C# methods. I’ve made it working (one of the information sources was the article https://weblog.west-wind.com/posts/2021/Jan/14/Taking-the-new-Chromium-WebView2-Control-for-a-Spin-in-NET-Part-1#do-you-need-the-webview2), however, I’m not feeling comfortable with the serialization/deserialization in my code. What bothers me is that the exchange is based on serialized strings; that approach appears somewhat primitive to me. To invoke a JavaScript function, I’m composing a source statement. Other way around, when my browser script is invoking a C# method, the argument is a serialized string (for which I know is JSON formatted) with all quote characters escaped.

My question is: should I have realized the interaction between C# and JavaScript in a different way?

Here are two C# code fragments with JavaScript invocation from a WinForms test program I’ve produced to cope with the migration:

public struct ConfigGraph3D
{
    public bool showServices { get; set; }
    public string viewStyle { get; set; }
    public bool enforceNodeLabels { get; set; }
    public bool enforceServiceLabels { get; set; }
    public bool planesVisible { get; set; }
    public bool embedded { get; set; }
}
// retrieving a JavaScript structure into a C# structure
//var CONFIG = { showServices: true, viewStyle: "O", enforceNodeLabels: false, 
//               enforceServiceLabels: false, planesVisible: true, embedded: false};
//
string invocation = "getConfig()";
string response = await browser.ExecuteScriptAsync(invocation);
// Notice here that I’m deserializing the data twice: first removing backslash escapes
// then converting it into the structure ConfigGraph3D.
string configStr = JsonSerializer.Deserialize<string>(response);
ConfigGraph3D config = JsonSerializer.Deserialize<ConfigGraph3D>(configStr);
textConfig.Text = response;
//
// sending a graph structure to JavaScript. 
// The properly formatted JSON structure is read from a file by yet it needs to be serialized 
// in order to add escape characters (backslash).
//
string invocation = getJsonFile (graphFilePath) ;
string response = await browser.ExecuteScriptAsync(invocation);
//
//
string getJsonFile (string graphFilePath)
{
    string contents = File.ReadAllText(graphFilePath);
    JsonSerializerOptions jso = new JsonSerializerOptions();
    jso.Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
    string contents2 = JsonSerializer.Serialize(contents, jso);
    string invocation = "replaceModelList(" + contents2 + ")";
    return invocation;
}

Invoking C# from JavaScript example:


    public struct ItemSelectedInfo
    {
        public int id { get; set; }
        public string type { get; set; }
    }
    //
    // invoked from JavaScript 
    // var jsonObj = "{ \"id\": " + mesh._id2 + ", \"type\":\"" + mesh._type + "\"}";   
    // window.chrome.webview.hostObjects.sync.dotnet.SelectedinGraphic(jsonObj);
    //
    [ComVisible(true)]
    public class GraphInterface
    {
        public void SelectedinGraphic(string jsonInfo)
        {
            ItemSelectedInfo selectedNodeKey = JsonSerializer.Deserialize<ItemSelectedInfo>(jsonInfo);
            Debug.WriteLine("SelectedinGraphic: " + jsonInfo);
        }
    }




Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source