I'm creating an application in C# that hosts custom web pages for most of the GUI. As the host, I'd like to provide a javascript API so that the embedded web pages can access some of the services provided by the host application.
I've been able to get the simple case for this working using the WebBrowser.ObjectForScripting property and implementing a scripting class. This works great for synchronous javascript calls. However, some of the operations that the host provides are long running and I'd like to provide the ability for the javascript to be called back when the operation completes. And this is where I'm running into trouble.
Javascript:
function onComplete( result )
{
alert( result );
}
function start()
{
window.external.LongRunningProcess( 'data', onComplete );
}
C#:
[ComVisible(true)]
public class ScriptObject
{
public void LongRunningProcess( string data, <???> callback )
{
// do work, call the callback
}
}
The 'start' function in javascript kicks this whole process off. The problem I'm having is, What is the type for the callback? And how should I call it from C#?
If I use the string type for callback, it compiles and runs, but from within the LongRunningProcess method callback actually contains the full contents of the onComplete function ( i.e. 'function onComplete( result ) { alert( result ) }' )
If I use the object type, it comes back as a COM object. Using the Microsoft.VisualBasic.Information.TypeName method, it returns 'JScriptTypeInfo'. But as far as I can tell, that's not a real type, nor is there any real mention of it through all of MSDN.
If I use the IReflect interface, it runs without error, but there are no members, fields, or properties on the object that I can find.
A work around would be to pass the string name of the callback function instead of the function itself ( i.e. window.external.LongRunningProcess( 'data', 'onComplete' ); ). I do know how to execute the javascript function by name, but I'd rather not have that syntax be required in the web pages, it also would not work with inline callback definitions in the javascript.
Any Ideas?
For what it's worth, I've already got this system working with the Chromium Embedded framework, but I'm working to port the code over to the WebBrowser control to avoid the hefty size of redistributing Chromium. However, the HTML pages being developed will eventually be run on Linux/Mac OSX where Chromium will probably still be used.
You can use Reflection for that:
You could also try
dynamic
approach. It'd be more elegant if it works, but I haven't verified it:[UPDATE] The
dynamic
method indeed works great, and probably is the easiest way of calling back JavaScript from C#, when you have a JavaScript function object. Both Reflection anddynamic
allow to call an anonymous JavaScript function, as well. Example:C#:
JavaScript:
As
@Frogmouth
noted here already you can pass callback function name to theLongRunningProcedure
:and when
LongRunningProcedure
completes use.InvokeScript
as the following: