OutSystems / WebView

Avalonia/WPF control that wraps CefGlue webview control
Apache License 2.0
358 stars 40 forks source link

Issue with EvaluateScriptFunction : C# exception thrown when using non integer function parameters #335

Closed electronicbits closed 6 months ago

electronicbits commented 6 months ago

I reviewed the code and unit tests, but I haven't found any way to execute a line like this (with strings as parameters), in order to send test data from C# to js:

var result = await webviewChart.EvaluateScriptFunction("hostToGuestSystemInterface.sendDataToGuest", "testdata");

This however, does work :

var result = await webviewChart.EvaluateScriptFunction("hostToGuestSystemInterface.sendDataToGuest", "1");

ie. sending numbers is fine, but anything else aside from numbers, I get a C# exception as follow: WebViewControl.WebView.JavascriptException: 'ReferenceError: testdata is not defined'

The unit tests in the code base only use numbers as test cases as mentioned.

Any idea how to send string data ? I need to JSON serialize probably large amounts of data from C# to js

The function in typescript is implemented as follow:

export class HostToGuestSystemInterface implements IHostToGuestSystemInterface { sendDataToGuest(data) { console.log('data received from host: ' + data); return data; } }

Thanks image

electronicbits commented 6 months ago

I think I've found a workaround for this.

The EvaluateScriptFunction still doesn't work for me if I want to pass non integer data

However, using the function EvaluateScript I managed to create a script where I do the actual call of the function.

I ran this from C#: (Note: see the sendDataToGuest('testdata'); fuction call)

string script = @" console.log(before); var result = hostToGuestSystemInterface.sendDataToGuest('testdata'); console.log(after); return result`; ".Replace(Environment.NewLine, ""); var result = await webviewChart.EvaluateScript(script);

This works... the plan is to pass in json serialized object to that function to pass relatively large amounts of data.

Either way, would be good to know if this is the optimal way to pass data to js.

Thanks in advance

joaompneves commented 6 months ago

Hi,

Its up to you to serialize the params passed in EvaluateScriptFunction. There's a EvaluateScriptFunctionWithSerializedParams but its protected. If you want to use it you may create an inherited Webview class.

As for passing large amounts of data from c# to js, I recommend following another approach, which is call a JS method that then requests the information to c#. That's probably more efficient when you have large amounts of data, check this test: https://github.com/OutSystems/WebView/blob/3fa63d262fa2447b971f951506cd4c9b5cd9b83a/tests/Tests.WebView/IsolatedJavascriptEvaluation.cs#L86

electronicbits commented 6 months ago

Ok got it !

I wrote this based on the unit test you gave me, on my own code and javascript is receiving the data.

var testObject = new TestObject() { Age = 33, Kind = Kind.B, Name = "John", Parent = new TestObject() { Name = "John Parent", Age = 66, Kind = Kind.C } };

Func functionToCall = () => { return testObject; };
webviewChart.RegisterJavascriptObject("functionToCall", functionToCall); var scriptAux = $"functionToCall.invoke().then(result=>console.log(result));"; var xresult = await webviewChart.EvaluateScript(scriptAux);

Thanks !

electronicbits commented 6 months ago

Just to wrap up, I was doing some performance tests on the above code I posted, and I was having relatively bad performance for what we wanted.

So re-read again your comment, and had a different perspective the second time around.

I am now calling a pre-registered function in javascript from C# called executeFunctionInQueue. This function in js will then call a function in C# which would request the next function to be executed in the queue (which is simply json data with the name of the function and a lot of test random data) Javascript would receive the data , deserialize and execute the respective function with the embedded data.

Performance wise, the last post I was having around 30 to 40 ms, no less than that per execution.

I am now getting 1 to 3 ms average.

It is quite the convoluted way of calling functions and passing data around, but at least got a good performance

joaompneves commented 6 months ago

Since there's no issue on the WebView side I'll close this