Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling javascript object method using WebBrowser.Document.InvokeScript

In my WinForms application I need to call javascript function from my WebBrowser control. I used Document.InvokeScript and it works perfect with functions alone e.g

Document.InvokeScript("function").

But when i want to call javascript object method e.g.

Document.InvokeScript("obj.method")

it doesn't work. Is there a way to make it work? Or different solution to this problem? Without changing anything in the javascript code!

Thanks in advance :)

like image 366
Brazol Avatar asked Sep 06 '11 15:09

Brazol


2 Answers

Unfortunately you can't call object methods out of the box using WebBrowser.Document.InvokeScript.

The solution is to provide a global function on the JavaScript side which can redirect your call. In the most simplistic form this would look like:

function invoke(method, args) {

    // The root context is assumed to be the window object. The last part of the method parameter is the actual function name.
    var context = window;
    var namespace = method.split('.');
    var func = namespace.pop();

    // Resolve the context
    for (var i = 0; i < namespace.length; i++) {
        context = context[namespace[i]];
    }

    // Invoke the target function.
    result = context[func].apply(context, args);
}

In your .NET code you would use this as follows:

var parameters = new object[] { "obj.method", yourArgument };
var resultJson = WebBrowser.Document.InvokeScript("invoke", parameters);

As you mention that you cannot change anything to your existing JavaScript code, you'll have to inject the above JavaScript method in some how. Fortunately the WebBrowser control can also do for you by calling the eval() method:

WebBrowser.Document.InvokeScript("eval", javaScriptString);

For a more robust and complete implementation see the WebBrowser tools I wrote and the article explaining the ScriptingBridge which specifically aims to solve the problem you describe.

like image 199
Christ A Avatar answered Oct 20 '22 07:10

Christ A


The example in the documentation does NOT include the parenthesis.

private void InvokeScript()
{
    if (webBrowser1.Document != null)
    {
        HtmlDocument doc = webBrowser1.Document;
        String str = doc.InvokeScript("test").ToString() ;
        Object jscriptObj = doc.InvokeScript("testJScriptObject");
        Object domOb = doc.InvokeScript("testElement");
    }
}

Try

Document.InvokeMethod("obj.method");

Note that you can pass arguments if you use HtmlDocument.InvokeScript Method (String, Object[]).

Edit

Looks like you aren't the only one with this issue: HtmlDocument.InvokeScript - Calling a method of an object . You can make a "Proxy function" like the poster of that link suggests. Basically you have a function that invokes your object's function. It's not an ideal solution, but it'll definitely work. I'll continue looking to see if this is possible.

Another post on same issue: Using WebBrowser.Document.InvokeScript() to mess around with foreign JavaScript . Interesting solution proposed by C. Groß on CodeProject:

private string sendJS(string JScript) {
    object[] args = {JScript};
    return webBrowser1.Document.InvokeScript("eval",args).ToString();
}

You could make that an extension method on HtmlDocument and call that to run your function, only using this new function you WOULD include parenthesis, arguments, the whole nine yards in the string you pass in (since it is just passed along to an eval).

Looks like HtmlDocument does not have support for calling methods on existing objects. Only global functions. :(

like image 9
Sam Avatar answered Oct 20 '22 07:10

Sam