通过 Nancy 将双精度数组从 C# 传递到 JavaScript
Pass array of doubles from C# to JavaScript via Nancy
首先我会说我非常精通 C#,但在 JS 和 Nancy 方面几乎是个新手。我正在尝试将二维双精度数组从 C#.Net Framework 控制台应用程序传递到 http://visjs.org/docs/graph3d/ 处的 Graph3d 包。 Graph3d 示例代码工作正常。我可以修改他们的 JS 来做一个简单的 5x5 数组,所有数组值都设置为 2,除了数组 (2,2) 的中间值为 22。它按预期绘制图形:
绘制上图的JS代码如下:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Graph 3D demo</title>
<style>
html, body {
font: 10pt arial;
padding: 0;
margin: 0;
width: 100%;
height: 100%;
}
#mygraph {
position: absolute;
width: 100%;
height: 100%;
}
</style>
<!-- for mobile devices like android and iphone -->
<meta name="viewport" content="target-densitydpi=device-dpi, width=device-width" />
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.js"></script>
<script type="text/javascript">
var data = null;
var graph = null;
var request = new XMLHttpRequest();
request.open('GET', 'http://192.168.1.153:1234/', true);
request.onload = function () {
// Begin accessing JSON data here
//var data = JSON.parse(this.response);
console.log(this.response);
}
request.send();
// Called when the Visualization API is loaded.
function drawVisualization() {
// Create and populate a data table.
data = new vis.DataSet();
data.add([{x:0,y:0,z:2}]);
data.add([{x:0,y:1,z:2}]);
data.add([{x:0,y:2,z:2}]);
data.add([{x:0,y:3,z:2}]);
data.add([{x:0,y:4,z:2}]);
data.add([{x:1,y:0,z:2}]);
data.add([{x:1,y:1,z:2}]);
data.add([{x:1,y:2,z:2}]);
data.add([{x:1,y:3,z:2}]);
data.add([{x:1,y:4,z:2}]);
data.add([{x:2,y:0,z:2}]);
data.add([{x:2,y:1,z:2}]);
data.add([{x:2,y:2,z:22}]);
data.add([{x:2,y:3,z:2}]);
data.add([{x:2,y:4,z:2}]);
data.add([{x:3,y:0,z:2}]);
data.add([{x:3,y:1,z:2}]);
data.add([{x:3,y:2,z:2}]);
data.add([{x:3,y:3,z:2}]);
data.add([{x:3,y:4,z:2}]);
data.add([{x:4,y:0,z:2}]);
data.add([{x:4,y:1,z:2}]);
data.add([{x:4,y:2,z:2}]);
data.add([{x:4,y:3,z:2}]);
data.add([{x:4,y:4,z:2}]);
// specify options
var options = {
width: '100%',
height: '100%',
style: 'surface',
showPerspective: true,
showGrid: true,
showShadow: false,
keepAspectRatio: true,
verticalRatio: 0.5,
backgroundColor: {
strokeWidth: 0
}
};
// create our graph
var container = document.getElementById('mygraph');
graph = new vis.Graph3d(container, data, options);
}
</script>
</head>
<body onresize="graph.redraw();" onload="drawVisualization()">
<div id="mygraph"></div>
</body>
</html>
非常简单。
但是,当我尝试将相同的 5x5 数组从 C# 通过 Nancy 发送到 JS 时,图片看起来不一样了。数据数组是正确的,由 Firefox 中的控制台 window 验证。这是错误的图片:
这是使用 Nancy 运行 网络服务器并将数组传递给 JS 的 C# 代码:
using System;
using System.IO;
using System.Reflection;
using System.Text;
using Nancy;
using Nancy.ModelBinding;
using Nancy.Conventions;
using Nancy.Hosting.Self;
namespace test3x3graph
{
class Program
{
static void Main(string[] args)
{
//Start Nancy web server
Nancy.Json.JsonSettings.MaxJsonLength = int.MaxValue;
string nancyUri = "http://localhost:4143/";
NancyHost host = new NancyHost(new Uri(nancyUri));
host.Start();
Console.WriteLine("NancyFx is running on " + nancyUri);
Console.WriteLine("\nPress any key to exit");
Console.ReadKey();
}
}
public class CustomRootPathProvider : IRootPathProvider
{
public string GetRootPath()
{
return Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
}
}
public class CustomBootstrapper : DefaultNancyBootstrapper
{
protected override IRootPathProvider RootPathProvider
{
get { return new CustomRootPathProvider(); }
}
protected override void ConfigureConventions(NancyConventions conventions)
{
base.ConfigureConventions(conventions);
conventions.StaticContentsConventions.Add(
StaticContentConventionBuilder.AddDirectory("public", @"public")
);
}
}
public class SurfaceModel
{
public static string SurfaceData = string.Empty;
//public static double[,] SurfaceData;
//static constructor to generate sample data
static SurfaceModel()
{
const int size = 5;
double[,] data = new double[size, size];
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
data[i, j] = 2;
}
}
data[2, 2] = 22;
//SurfaceData = data;
//convert to string representation
StringBuilder sb = new StringBuilder();
sb.Append("[");
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
sb.Append("[");
sb.Append(i.ToString());
sb.Append(",");
sb.Append(j.ToString());
sb.Append(",");
sb.Append(data[i, j].ToString());
sb.Append("]");
if (j < size - 1)
sb.Append(",");
}
if (i < size - 1)
sb.Append(",");
}
sb.Append("]");
SurfaceData = sb.ToString();
}
}
public class TestModule : Nancy.NancyModule
{
public TestModule()
{
Get["/"] = args =>
{
SurfaceModel model = this.Bind<SurfaceModel>();
return View["surface", model];
};
}
}
}
最后,这是从 C# 接收表面模型的 JS 代码:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Graph3D test</title>
<style>
html, body {
font: 10pt arial;
padding: 0;
margin: 0;
width: 100%;
height: 100%;
}
#mygraph {
position: absolute;
width: 100%;
height: 100%;
}
</style>
<!-- for mobile devices like android and iphone -->
<meta name="viewport" content="target-densitydpi=device-dpi, width=device-width" />
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.js"></script>
<script type="text/javascript">
var data = null;
var graph = null;
// inject surface model here...
var surfaceData = @Model.SurfaceData;
// Called when the Visualization API is loaded.
function drawVisualization() {
console.log(surfaceData);
// Create and populate a data table.
data = new vis.DataSet();
for(var x = 0; x < surfaceData.length; x++) {
for(var y = 0; y < surfaceData[x].length; y++) {
data.add([
{
x: x,
y: y,
z: surfaceData[x][y]
}
]);
}
}
// specify options
var options = {
width: '100%',
height: '100%',
style: 'surface',
showPerspective: true,
showGrid: true,
showShadow: false,
keepAspectRatio: true,
verticalRatio: 0.5,
backgroundColor: {
strokeWidth: 0
}
};
// create our graph
var container = document.getElementById('mygraph');
graph = new vis.Graph3d(container, data, options);
}
</script>
</head>
<body onresize="graph.redraw();" onload="drawVisualization()">
<div id="mygraph"></div>
</body>
</html>
该 JS 与有效的 JS 几乎相同;只有数据部分不同。所有的 Graph3d 选项都是相同的,所以我很困惑,图片渲染不一样。
另请注意,在 C# 中,double 数组在发送到 JS 之前已转换为字符串表示形式。当我尝试将它作为双打数组传递时,生成的图片是空白的。如果可以使用字符串表示找到解决方案,那就太棒了。但是如果能够避免中间步骤并将双精度数组直接传递给 JS,那就更干净了。
感谢任何建议。
我能够使用 Json.NET 序列化程序来实现它。令我非常惊讶的是 JsonConvert.SerializeObject 没有添加允许 JSON.Parse 反序列化字符串而不会出错的单引号。
无论如何,这里是相关的 C# 代码:
//create a 1-dimensional array to send to Javascript.
//the first item is the number of rows; the 2nd item is the number of columns;
//the remaining items are the values from the 2-d array in row-major order
double[] data1d = new double[size*size + 2];
data1d[0] = data1d[1] = size;
int k = 2;
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
data1d[k++] = data[i, j];
}
}
SurfaceData = "'" + JsonConvert.SerializeObject(data1d) + "'";
这里是相关的 Javascript 代码:
// inject surface model here.
// Model.Surface data is a 2-dimensional array stored in a 1-dimensional array as follows:
// Array item [0] is the number of rows. Array item [1] is the number of columns.
// The remaining array items are the values from the 2-d array in row-major order
var surfaceData = JSON.parse(@Model.SurfaceData);
// Called when the Visualization API is loaded.
function drawVisualization() {
console.log(surfaceData);
// Create and populate a data table.
data = new vis.DataSet();
var k = 2;
for(var x = 0; x < surfaceData[0]; x++) {
for(var y = 0; y < surfaceData[1]; y++) {
data.add([{x: x, y: y, z: surfaceData[k++]}]);
}
}
您可以提供脚本路径或css路径
Get("/api/scripts/scripts.js", _ => return (Response)File.ReadAllText(scriptPath);
您基本上可以在这里做任何事情来制作内容。
首先我会说我非常精通 C#,但在 JS 和 Nancy 方面几乎是个新手。我正在尝试将二维双精度数组从 C#.Net Framework 控制台应用程序传递到 http://visjs.org/docs/graph3d/ 处的 Graph3d 包。 Graph3d 示例代码工作正常。我可以修改他们的 JS 来做一个简单的 5x5 数组,所有数组值都设置为 2,除了数组 (2,2) 的中间值为 22。它按预期绘制图形:
绘制上图的JS代码如下:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Graph 3D demo</title>
<style>
html, body {
font: 10pt arial;
padding: 0;
margin: 0;
width: 100%;
height: 100%;
}
#mygraph {
position: absolute;
width: 100%;
height: 100%;
}
</style>
<!-- for mobile devices like android and iphone -->
<meta name="viewport" content="target-densitydpi=device-dpi, width=device-width" />
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.js"></script>
<script type="text/javascript">
var data = null;
var graph = null;
var request = new XMLHttpRequest();
request.open('GET', 'http://192.168.1.153:1234/', true);
request.onload = function () {
// Begin accessing JSON data here
//var data = JSON.parse(this.response);
console.log(this.response);
}
request.send();
// Called when the Visualization API is loaded.
function drawVisualization() {
// Create and populate a data table.
data = new vis.DataSet();
data.add([{x:0,y:0,z:2}]);
data.add([{x:0,y:1,z:2}]);
data.add([{x:0,y:2,z:2}]);
data.add([{x:0,y:3,z:2}]);
data.add([{x:0,y:4,z:2}]);
data.add([{x:1,y:0,z:2}]);
data.add([{x:1,y:1,z:2}]);
data.add([{x:1,y:2,z:2}]);
data.add([{x:1,y:3,z:2}]);
data.add([{x:1,y:4,z:2}]);
data.add([{x:2,y:0,z:2}]);
data.add([{x:2,y:1,z:2}]);
data.add([{x:2,y:2,z:22}]);
data.add([{x:2,y:3,z:2}]);
data.add([{x:2,y:4,z:2}]);
data.add([{x:3,y:0,z:2}]);
data.add([{x:3,y:1,z:2}]);
data.add([{x:3,y:2,z:2}]);
data.add([{x:3,y:3,z:2}]);
data.add([{x:3,y:4,z:2}]);
data.add([{x:4,y:0,z:2}]);
data.add([{x:4,y:1,z:2}]);
data.add([{x:4,y:2,z:2}]);
data.add([{x:4,y:3,z:2}]);
data.add([{x:4,y:4,z:2}]);
// specify options
var options = {
width: '100%',
height: '100%',
style: 'surface',
showPerspective: true,
showGrid: true,
showShadow: false,
keepAspectRatio: true,
verticalRatio: 0.5,
backgroundColor: {
strokeWidth: 0
}
};
// create our graph
var container = document.getElementById('mygraph');
graph = new vis.Graph3d(container, data, options);
}
</script>
</head>
<body onresize="graph.redraw();" onload="drawVisualization()">
<div id="mygraph"></div>
</body>
</html>
非常简单。
但是,当我尝试将相同的 5x5 数组从 C# 通过 Nancy 发送到 JS 时,图片看起来不一样了。数据数组是正确的,由 Firefox 中的控制台 window 验证。这是错误的图片:
这是使用 Nancy 运行 网络服务器并将数组传递给 JS 的 C# 代码:
using System;
using System.IO;
using System.Reflection;
using System.Text;
using Nancy;
using Nancy.ModelBinding;
using Nancy.Conventions;
using Nancy.Hosting.Self;
namespace test3x3graph
{
class Program
{
static void Main(string[] args)
{
//Start Nancy web server
Nancy.Json.JsonSettings.MaxJsonLength = int.MaxValue;
string nancyUri = "http://localhost:4143/";
NancyHost host = new NancyHost(new Uri(nancyUri));
host.Start();
Console.WriteLine("NancyFx is running on " + nancyUri);
Console.WriteLine("\nPress any key to exit");
Console.ReadKey();
}
}
public class CustomRootPathProvider : IRootPathProvider
{
public string GetRootPath()
{
return Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
}
}
public class CustomBootstrapper : DefaultNancyBootstrapper
{
protected override IRootPathProvider RootPathProvider
{
get { return new CustomRootPathProvider(); }
}
protected override void ConfigureConventions(NancyConventions conventions)
{
base.ConfigureConventions(conventions);
conventions.StaticContentsConventions.Add(
StaticContentConventionBuilder.AddDirectory("public", @"public")
);
}
}
public class SurfaceModel
{
public static string SurfaceData = string.Empty;
//public static double[,] SurfaceData;
//static constructor to generate sample data
static SurfaceModel()
{
const int size = 5;
double[,] data = new double[size, size];
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
data[i, j] = 2;
}
}
data[2, 2] = 22;
//SurfaceData = data;
//convert to string representation
StringBuilder sb = new StringBuilder();
sb.Append("[");
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
sb.Append("[");
sb.Append(i.ToString());
sb.Append(",");
sb.Append(j.ToString());
sb.Append(",");
sb.Append(data[i, j].ToString());
sb.Append("]");
if (j < size - 1)
sb.Append(",");
}
if (i < size - 1)
sb.Append(",");
}
sb.Append("]");
SurfaceData = sb.ToString();
}
}
public class TestModule : Nancy.NancyModule
{
public TestModule()
{
Get["/"] = args =>
{
SurfaceModel model = this.Bind<SurfaceModel>();
return View["surface", model];
};
}
}
}
最后,这是从 C# 接收表面模型的 JS 代码:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Graph3D test</title>
<style>
html, body {
font: 10pt arial;
padding: 0;
margin: 0;
width: 100%;
height: 100%;
}
#mygraph {
position: absolute;
width: 100%;
height: 100%;
}
</style>
<!-- for mobile devices like android and iphone -->
<meta name="viewport" content="target-densitydpi=device-dpi, width=device-width" />
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.js"></script>
<script type="text/javascript">
var data = null;
var graph = null;
// inject surface model here...
var surfaceData = @Model.SurfaceData;
// Called when the Visualization API is loaded.
function drawVisualization() {
console.log(surfaceData);
// Create and populate a data table.
data = new vis.DataSet();
for(var x = 0; x < surfaceData.length; x++) {
for(var y = 0; y < surfaceData[x].length; y++) {
data.add([
{
x: x,
y: y,
z: surfaceData[x][y]
}
]);
}
}
// specify options
var options = {
width: '100%',
height: '100%',
style: 'surface',
showPerspective: true,
showGrid: true,
showShadow: false,
keepAspectRatio: true,
verticalRatio: 0.5,
backgroundColor: {
strokeWidth: 0
}
};
// create our graph
var container = document.getElementById('mygraph');
graph = new vis.Graph3d(container, data, options);
}
</script>
</head>
<body onresize="graph.redraw();" onload="drawVisualization()">
<div id="mygraph"></div>
</body>
</html>
该 JS 与有效的 JS 几乎相同;只有数据部分不同。所有的 Graph3d 选项都是相同的,所以我很困惑,图片渲染不一样。
另请注意,在 C# 中,double 数组在发送到 JS 之前已转换为字符串表示形式。当我尝试将它作为双打数组传递时,生成的图片是空白的。如果可以使用字符串表示找到解决方案,那就太棒了。但是如果能够避免中间步骤并将双精度数组直接传递给 JS,那就更干净了。
感谢任何建议。
我能够使用 Json.NET 序列化程序来实现它。令我非常惊讶的是 JsonConvert.SerializeObject 没有添加允许 JSON.Parse 反序列化字符串而不会出错的单引号。
无论如何,这里是相关的 C# 代码:
//create a 1-dimensional array to send to Javascript.
//the first item is the number of rows; the 2nd item is the number of columns;
//the remaining items are the values from the 2-d array in row-major order
double[] data1d = new double[size*size + 2];
data1d[0] = data1d[1] = size;
int k = 2;
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
data1d[k++] = data[i, j];
}
}
SurfaceData = "'" + JsonConvert.SerializeObject(data1d) + "'";
这里是相关的 Javascript 代码:
// inject surface model here.
// Model.Surface data is a 2-dimensional array stored in a 1-dimensional array as follows:
// Array item [0] is the number of rows. Array item [1] is the number of columns.
// The remaining array items are the values from the 2-d array in row-major order
var surfaceData = JSON.parse(@Model.SurfaceData);
// Called when the Visualization API is loaded.
function drawVisualization() {
console.log(surfaceData);
// Create and populate a data table.
data = new vis.DataSet();
var k = 2;
for(var x = 0; x < surfaceData[0]; x++) {
for(var y = 0; y < surfaceData[1]; y++) {
data.add([{x: x, y: y, z: surfaceData[k++]}]);
}
}
您可以提供脚本路径或css路径
Get("/api/scripts/scripts.js", _ => return (Response)File.ReadAllText(scriptPath);
您基本上可以在这里做任何事情来制作内容。