Передать массив двойников из C # в JavaScript через Нэнси - PullRequest
0 голосов
/ 27 февраля 2019

Начну с того, что я очень опытный в C #, но в основном новичок в JS & Nancy.Я пытаюсь передать двумерный массив значений типа double из консольного приложения C # .Net Framework в пакет Graph3d по адресу http://visjs.org/docs/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 # через Нэнси вJS, картина не выглядит так же.Массив данных правильный, что подтверждается окном консоли в Firefox.Вот ошибочная картинка: enter image description here

Вот код C #, который использует Nancy для запуска веб-сервера и передачи массива в JS:

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];
            };
        }
    }
}

И, наконец,Вот код JS, который получает модель поверхности из C #:

<!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.Когда я пытаюсь передать его как массив значений типа double, полученное изображение будет пустым.Если решение может быть найдено с использованием строкового представления, фантастика.Но было бы намного чище избежать этого промежуточного шага и передать массив двойников непосредственно в JS.

Спасибо за любой совет.

Ответы [ 2 ]

0 голосов
/ 06 июля 2019

Вы можете указать путь к сценарию или путь к CSS

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

Здесь вы можете сделать что угодно для создания контента.

0 голосов
/ 27 февраля 2019

Я смог заставить это работать, используя сериализатор 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++]}]);
    }
  }
...