How to send messages from JavaScript to C# and vice versa?

Sending messages from JavaScript to C#

3D WebView has a built-in window.vuplex.postMessage() JavaScript API that you can use to send messages from JavaScript to C#. Since it's built into the browser, you don't need to include any 3rd party scripts in the page in order to utilize it. The following example illustrates how to use this JavaScript API in a page script or in a script executed via ExecuteJavaScript():

// The window.vuplex object gets created when the page starts loading,
// so we double-check that it exists before using it here.
// You can skip this step if you're sending a message after the page has loaded.
if (window.vuplex) {
    // The window.vuplex object already exists, so go ahead and send the message.
    sendMessageToCSharp();
} else {
    // The window.vuplex object hasn't been initialized yet because the page is still
    // loading, so add an event listener to send the message once it's initialized.
    window.addEventListener('vuplexready', sendMessageToCSharp);
}

function sendMessageToCSharp() {
    // This object passed to postMessage() automatically gets serialized as JSON
    // and is emitted via the C# MessageEmitted event. This API mimics the window.postMessage API.
    window.vuplex.postMessage({ type: 'greeting', message: 'Hello from JavaScript!' });
}

The following C# demonstrates how to receive that message in Unity using the MessageEmitted event:

async void Start() {
    // This assumes that there's a WebViewPrefab already in the scene.
    var webViewPrefab = GameObject.Find("WebViewPrefab").GetComponent<WebViewPrefab>();
    // Wait for the WebViewPrefab to initialize, because the WebViewPrefab.WebView property
    // is null until the prefab has initialized.
    await webViewPrefab.WaitUntilInitialized();
    webViewPrefab.WebView.MessageEmitted += (sender, eventArgs) => {
        // > JSON received: { "type": "greeting", "message": "Hello from JavaScript!" }
        Debug.Log("JSON received: " + eventArgs.Value);
    };
}

Sending messages from C# to JavaScript

The process for sending messages from C# to JavaScript is very similar. Here's a C# script that uses PostMessage() to send a message to JavaScript:

async void Start() {

    var webViewPrefab = GameObject.Find("WebViewPrefab").GetComponent<WebViewPrefab>();
    // Wait for the WebViewPrefab to initialize, because the WebViewPrefab.WebView property
    // is null until the prefab has initialized.
    await webViewPrefab.WaitUntilInitialized();
    // Send a message after the page has loaded.
    await webViewPrefab.WebView.WaitForNextPageLoadToFinish();
    webViewPrefab.WebView.PostMessage("{\"type\": \"greeting\", \"message\": \"Hello from C#!\"}");
}

And here's some JavaScript that listens for a message through the window.vuplex object's message event:

if (window.vuplex) {
    addMessageListener();
} else {
    window.addEventListener('vuplexready', addMessageListener);
}

function addMessageListener() {
    window.vuplex.addEventListener('message', function(event) {
        let json = event.data;
        // > JSON received: { "type": "greeting", "message": "Hello from C#!" }
        console.log('JSON received: ' + json);
    });
}

An alternative to passing messages from C# to JavaScript is to instead use ExecuteJavaScript() to execute JavaScript directly.

Other examples

Here are other examples that demonstrate passing messages from JavaScript to C# and vice versa:

Limitations

2D WebView for WebGL has a limitation where it's unable to automatically add the window.vuplex JavaScript API to a web page if the page is from a different domain than the Unity app. Please see this page for details and the solution.

Troubleshooting

If messages aren't being sent or received as expected, please check the following:

  • Verify that your JavaScript is checking if window.vuplex exists and uses the vuplexready event like shown in this section. It may be that your script is trying to use window.vuplex before it is set.
  • Use remote debugging to verify that your JavaScript is successfully attaching its message handler and calling vuplex.postMessage() as expected.
  • Verify that your C# script is using WebViewPrefab.WaitUntilInitialized() to wait until the prefab has initialized before setting its MessageEmitted event handler, like shown in this section. Otherwise, WebViewPrefab.WebView may be null, which would trigger a NullReferenceException.
  • If your C# script sends a message to your JavaScript directly after the page finishes loading, it should wait until the JavaScript indicates that it has attached a message handler, otherwise the JavaScript may miss the message. For an example of this pattern, please see AdvancedWebViewDemo.cs from 3D WebView's AdvancedWebViewDemo scene.