数组应该如何从 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 problemArray
是 unknown
,不可能遍历它的字段。
尝试将所有项目连接成一个以 ; 分隔的字符串或 |例如,然后在 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 数组