数组应该如何从 C# 传递给 Javascript 函数?

Posted

技术标签:

【中文标题】数组应该如何从 C# 传递给 Javascript 函数?【英文标题】:How should an array be passed to a Javascript function from C#? 【发布时间】:2011-09-30 23:40:56 【问题描述】:

我使用 WPF 中的 WebBrowser 对象,并在浏览器中加载的页面中调用一些 javascript 代码,如下所示:

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

现在,js 函数应该遍历第二个参数(字符串数组)的元素并做相应的事情。唯一的问题是参数好像不是作为js数组传递的。

例如,

alert(typeof theArray);

警报“未知”。

从 CSharp 调用 js 函数时,将数组作为参数传递的正确方法是什么?

【问题讨论】:

请记住,typeof [] == 'object'. 我很难从这样的物体中取出任何有用的东西。 typeof problemArrayunknown,不可能遍历它的字段。 尝试将所有项目连接成一个以 ; 分隔的字符串或 |例如,然后在 javascript 中,将其拆分回数组 【参考方案1】:

也许将它作为json字符串传递并在js函数中解析它

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】:

它本身并不能解决问题,但如果您只有一个数组要传递,它就可以解决问题:您可以向 JavaScript 函数发送任意数量的参数,并通过 arguments 特殊变量访问它们。它变得类似于接受可变数量参数的函数,具有相同的优点和问题(例如,您必须最后传递数组,如前所述,您只能传递一个)。

这是一个示例 JavaScript 函数:

function foo()

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

    // do stuff with stringArgs

你可以像这样从 C# 中调用它:

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

【讨论】:

【参考方案3】:

如果你真的想从代码中榨取每一点性能,你可以通过 javascript 中的 eval 来避免反序列化。这个概念是像这样构造调用:

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

请注意,我们使用的 .execScript 让世界变得与众不同。这是因为 .InvokeScript 会强制使用基于 string 的参数(这会迫使您在 javascript 端使用 eval)来强制输入 javascript 方法,而 .execScript() 使我们能够编写任意javascript 代码,包括您在上面看到的内容(请注意,参数是一个显式的 javascript 数组和一组属性)。现在我们可以直接编码数组和对象并将它们写为参数。为此,我们只需使用 Newtonsoft.Json 来序列化数组和对象:

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 ) + ");");

另一件事是检索结果返回值:

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

为方便起见,您可能需要编写一个实用方法,该方法迭代给定参数并正确序列化它们,调用函数,然后检索返回值。

【讨论】:

execScript 在 IE11 之前是一个不错的选择。从IE11开始不支持,所以msdn suggests using eval as a replacement @anikiforov 你是绝对正确的。 execScript 被标记为已弃用很长时间。然后在 IE11 的一些更新中突然杀死了它,没有任何事先警告代表 MS。然后许多开发人员抱怨 COM 的功能丢失。然后 MS 发布了另一个更新,允许再次在 COM 上使用 .execScript(但该方法在 javascript 中不再可用 - 您可以使用完全更新的 IE11+ 中的开发工具验证它)。真是一团糟。【参考方案4】:

你需要先将数组转换成JS数组,如下所示:

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

以下两个例子:

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() );

您可能还想删除尾随。不要忘记为StringBuilder导入相应的库,我认为是System.Text.StringBuilder;

或使用,示例二:

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

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

【讨论】:

传递这个字符串结构,在JavaScript端自动得到一个数组,还是需要eval呢? 它应该自动被视为一个字符串是JavaScript,所以你只需在JavaScript函数中处理它。见这里JS Arrays 如果要显示为字符串,那么人们不妨使用 JavaScriptSerializer 类来支持各种对象。

以上是关于数组应该如何从 C# 传递给 Javascript 函数?的主要内容,如果未能解决你的问题,请参考以下文章

我应该如何使用 P/Invoke 将字符串数组传递给 C 库?

如何将在我的 Javascript 中创建的字符串数组传递给 C# 代码隐藏文件?

将 C# ASP.NET 数组传递给 Javascript 数组

将 C# ASP.NET 数组传递给 Javascript 数组

将 javascript 数组传递给 c# 方法

将日期时间从 javascript 传递给 c# (Controller)