Using WebView2 call C# methods (async and sync) with complex parameters and return values from TS/JS!
There currently is no NuGet and npm packages, instead copy the WebView2BetterBridge\BetterBridge.cs
to your C# project and web-ui\src\betterBridge.ts
to your frontend project.
Note: For this solution to work with async methods you need to be on WebView2 1.0.1293.44 or later.
The documentation here is just a very light overview, for full details check the sample projects.
-
Create a regular class that contains all the methods you can call from TS/JS (see
SampleBridge.cs
for an example). Both async and sync methods with complex object parameters and return values will work. -
Register it by calling:
webView2.CoreWebView2.AddHostObjectToScript("bridge", new BetterBridge(new MyBridge(), webView2));
Notice how BetterBridge wraps your own bridge class.
Note: The TS/JS method on the bridge should use camelCase.
// TypeScript
import { createBridge } from "./betterBridge";
const bridge = createBridge("bridge");
const result = await bridge.helloWorldAsync(99, "abc", {
text: "hello from JS!",
sent: new Date(),
});
// C#
public async Task<Message> HelloWorldAsync(int someData, string moreData, Message message)
{
var msg = new Message()
{
Text = $"Hi from C#! Thank you for the data: {message.Text} {message.Sent} {someData} and {moreData}.",
Sent = DateTime.Now
};
await Task.Delay(500);
return msg;
}
Note: The TS/JS method on the bridge should use camelCase.
Note: Even though the C# method is sync it's still resolved to a Promise that we have to await. This is the recommended way since we do not want to lock up the UI.
// TypeScript
import { createBridge } from "./betterBridge";
const bridge = createBridge("bridge");
const result = await bridge.helloWorld(99, "abc", {
text: "hello from JS!",
sent: new Date(),
});
// C#
public Message HelloWorld(int someData, string moreData, Message message)
{
return new Message()
{
Text = $"Hi from C#! Thank you for the data: {message.Text} {message.Sent} {someData} and {moreData}.",
Sent = DateTime.Now
};
}
Makes it a bit easier to send messages from C# to TS/JS instead of using webView2.CoreWebView2.PostWebMessageAsJson
directly.
// C#
var messageSender = new BetterBridgeMessageSender(webView2);
messageSender.SendMessage("message", new Message() { Text = "I want to report something", Sent = DateTime.Now });
// TypeScript
import { createBridge } from "./betterBridge";
const bridge = createBridge("bridge");
bridge.addMessageHandler((type, data) => {
console.log("Got message", type, data);
});
Uses some reflection under the hood but when testing I saw very small performance differences often in the range of 0.1-0.5 ms. But your results may vary 😊.