通过Nancy将双打数组从C#传递到JavaScript

时间:2019-02-26 21:54:51

标签: javascript c# nancy

首先,我会说我非常精通C#,但是在JS&Nancy中几乎是一个新手。我试图将二维数组从C#.Net Framework控制台应用程序传递到位于http://visjs.org/docs/graph3d/的Graph3d包中。 Graph3d示例代码可以正常工作。我可以修改其JS来做一个简单的5x5数组,将所有数组值设置为2,但数组中间(2,2)的值是22。它按预期绘制图形: enter image description here

以下是绘制以上图片的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中的“控制台”窗口验证。这是错误的图片: enter image description here

这是使用Nancy运行Web服务器并将数组传递给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#中,双精度数组在发送给JS之前已转换为字符串表示形式。当我尝试将其作为双精度数组传递时,生成的图片为空白。如果可以使用字符串表示形式找到解决方案,那就太好了。但是,能够避免中间步骤并将双精度数组直接传递给JS会更加清洁。

谢谢您的建议。

2 个答案:

答案 0 :(得分:0)

使用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++]}]);
    }
  }

答案 1 :(得分:0)

您可以提供脚本路径或CSS路径

Get("/api/scripts/scripts.js", _ => return (Response)File.ReadAllText(scriptPath);

您基本上可以在此处进行任何操作来产生内容。