How should an array be passed to a Javascript function from C#?

我的梦境 提交于 2019-12-20 09:59:05

问题


I use a WebBrowser object from WPF and I'm calling some Javascript code in the page loaded in the browser like this:

myWebBrowser.InvokeScript("myJsFunc", new object[] { foo.Text, bar.ToArray<string>()});

Now, the js function is supposed to iterate over the elements of the second parameter (an array of strings) and do stuff accordingly. The only issue is that the parameter seems not to be passed as a js array.

For example,

alert(typeof theArray);

alerts "Unknown".

What is the proper way to pass an array as a parameter when invoking a js function from CSharp?


回答1:


Maybe pass it as a json string instead and parse it in the js function

var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var json = serializer.Serialize(bar.ToArray<string>());

myWebBrowser.InvokeScript("myJsFunc", new object[] { foo.Text, json });

js:

function myJsFunc(json) {
   var data = JSON.parse(json);
   // do something with it.
}

http://blogs.microsoft.co.il/blogs/pini_dayan/archive/2009/03/12/convert-objects-to-json-in-c-using-javascriptserializer.aspx




回答2:


It's not solving the issue itself but it solves the problem if you have only one array to pass: you can send an arbitrary number of parameters to a JavaScript function, and access them through the arguments special variable. It becomes analogous to a function accepting a variable number of arguments, with the same advantages and problems (for instance, you have to pass the array last, and as mentioned earlier you can only pass one).

Here's an example JavaScript function:

function foo()
{
    var stringArgs = [];
    for (var i = 0; i < arguments.length; i++)
        stringArgs.push(arguments[i]);

    // do stuff with stringArgs
}

And you'd call it from C# like this:

List<string> arguments = new List<string>();
arguments.Add("foo");
arguments.Add("bar");
webBrowser.InvokeScript("foo", arguments.ToArray());



回答3:


In case you really want to squeeze every bit of performance out of the code you can avoid the deserialization by means of eval inside javascript. The concept is to structure the call like this:

((IHTMLWindow2)webBrowserControl.Document.Window.DomWindow).execScript("var returnValue = someFunction([ 'abc', 'xyz', '1', '2', '3' ], { foo: 'xyz', bar: 1 });"

Notice that we use .execScript which makes all the difference in the world. This is because contrary to .InvokeScript which would forcefeed the javascript method with string based arguments (which is what forces you to use eval on the javascript side), .execScript() gives us the ability to write arbitrary javascript code including what you see above (notice that the arguments are an explicit javascript array and a bag of properties). Now we can directly code arrays and objects and write them as arguments. In order to do that we just use Newtonsoft.Json to serialize arrays and objects:

class Test {
     public string foo;
     public int bar;
}
((IHTMLWindow2)webBrowserControl.Document.Window.DomWindow).execScript("var returnValue = someFunction(" +
JsonConvert.SerializeObject((new List<object>(2) { "abc", "xyz", 1, 2, 3 }).ToArray()) + ", " + JsonConvert.SerializeObject(new Test() { foo = "xyz", bar = 1 }) + ");");

Another thing is retrieving the resulting returned value:

string result = (string)webBrowserControl.Document.InvokeScript("eval", new object[] { @"returnValue;" }));

For your convenience you might want to write a utility method which iterates over the given parameters and serializes them properly, invokes the function and then retrieves the returned value.




回答4:


You need to convert the array to a JS array first, something that looks like this:

["John", "Bob", "Sue"] // literal array

Two examples follow:

StringBuilder sb = new StringBuilder();
string[] stringArray = bar.ToArray<string>();

//Build the JS array.
sb.Append( "[");
for (int i = 0; i < stringArray.Length; i++)
{
    sb.AppendFormat( "'{0}', ", stringArray[i] );

}
sb.Append( "]");


// Now send the array to the JS function.
myWebBrowser.InvokeScript("myJsFunc", new object[] { foo.Text, sb.ToString() });

You may want to remove the trailing , as well. Don't forget to import the appropriate libraries for StringBuilder, which I think is System.Text.StringBuilder;

or use, example two:

string[] stringArray = bar.ToArray<string>();

// or simpler to use string join.
string jsArray = "[" + String.Join( ",", stringArray ) + "]";
//
myWebBrowser.InvokeScript("myJsFunc", new object[] { foo.Text, jsArray });


来源:https://stackoverflow.com/questions/6619931/how-should-an-array-be-passed-to-a-javascript-function-from-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!