Wes Doyle Wes Doyle - 3 months ago 26
JSON Question

Passing correctly formatted JSON from .NET MVC Controller to View

I'm using vis.js to create a timeline, and am trying to understand where I'm going wrong when trying to pass JSON from my model to the view. The timeline accepts data in JSON format, for example:

var data = [
{"content": "item 1", "start": "2016-08-20"},
{"content": "item 2", "start": "2016-08-21"},
{"content": "item 3", "start": "2016-08-21"}];


I have a model the looks like the following:

public class MyModel
{
public ModelData Data { get; set; }
public IEnumerable<TimeLineEntry> Timeline { get; set; }
public string ChartData { get; set; }
}


In my controller, I'm passing this model to the view as an ActionResult:

public ActionResult Summary(FilterModel filter)
{
var modelData = GetModelData(filter);

var timeline = BuildTimeLine(modelData);

var chartData = BuildChartData(timeline);

MyModel model = new MyModel
{
ModelData = modelData,
Timeline = timeline,
ChartData = chartData
};

return View(model); //setting a breakpoint here, ChartData JSON looks
}

private string BuildChartData(List<TimelineEntry> data)
{
var timeline = data.Select(a => new
{
content = a.Description,
start = a.CreatedOn
});

var jsonSerializer = new JavaScriptSerializer();
return jsonSerializer.Serialize(timeline);
}


In the view, I'm attempting to create a variable to store the JSON for use in the javascript application, like the following:

<script type="text/javascript">
// DOM element for the timeline
var container = document.getElementById('visualization');

var data = @Model.ChartData; //I have a feeling I can't define data like this due to the way it is compiled.

var chartData = JSON.parse(data);
var items = new vis.DataSet(chartData); //this takes JSON

var options = {};

var timeline = new vis.Timeline(container, items, options);
</script>


When the page is compiled, I'm getting a javascript error:
Uncaught SyntaxError: Unexpected token &

This happens when I try to store
@Model.ChartData
as a variable; it looks like this when compiled:
[{&quot;content&quot;:&quot;&quot;,&quot;start&quot;:&quot;\/Date(1471890279333)\/&quot;},{ ..
..

I feel like this is a simple problem, but I'm currently at a loss as to how to properly pass the JSON from model into the view.

Answer

In the script you can use

var data = @Html.Raw(Json.Encode(Model.ChartData))

however, your wanting an array of objects in the client, which you already have in the controller, so there is little point serializing your collection to a string in the controller and then converting it back to a collection on the client.

Your controller can simply be

public ActionResult Summary(FilterModel filter)
{
    var modelData = GetModelData(filter);
    var timeline = BuildTimeLine(modelData);
    var chartData = BuildChartData(timeline);

    MyModel model = new MyModel
    {
        ModelData = modelData,
        Timeline = timeline,
        ChartData = chartData.Select(a => new ChartDataVM
        {
            content = a.Description,
            start = a.CreatedOn
        })
    };
    return View(model); 
}

where property ChartData is public IEnumerable<ChartDataVM> ChartData { get; set; }, andChartDataVM` is

public class ChartDataVM
{
    public string content { get; set; }
    public DateTime start { get; set; }
}

Then in the view, its

var data = @Html.Raw(Json.Encode(Model.ChartData));
// var chartData = JSON.parse(data); Not required
var items = new vis.DataSet(data);

However, based on the format you have indicated that the plugin requires, you may need to change property start to typeof string and in the query use

start = a.CreatedOn.Tostring("yyyy-MM-dd")
Comments