Konrad Viltersten
Konrad Viltersten

Reputation: 39190

Creating an array of JSON objects in JavaScript on a Razor page from custom viewmodel in MVC?

I'm trying to populate the array in my script (it's going to be used for charting with D3.JS later on). According to this post, I'm supposed to use the syntax below. However, it doesn't work, bacause I get the error on the pushy line saying Uncaught ReferenceError: WebSite is not defined, where WebSite is the name of the namespace of the data (I'm guessing that, as it's the name of my project).

<script>
  var data = new Array();
  @foreach (var piece in @Model.DataPieces)
  {
    @:data.push(@piece);
  }
</script>

I'm pretty sure it has to do with the data type of piece, because the following change makes it work (at least not producing a bunch of errors). I'm picking out the individual fields from piece object and push those into the array, as a new object.

<script>
  var data = new Array();
  @foreach (var piece in @Model.DataPieces)
  {
    @:data.push({'cat': '@piece.Category', 'key': '@piece.Key', 'val': '@piece.Value'});
  }
</script>

It's inconvenient, prone to mistakes and requires a refactoring of the assignment each time the model changes. How can I avoid this approach and be able to automagically create JSON objects upon assignment, as shown in the first sample?

The viewmodel for the Razor page is declared as folows.

namespace WebSite.Models
{
  public class DrillDataViewModel
  {
    public List<DataPiece> DataPieces { get; set; }

    public class DataPiece
    {
      public string Category { get; set; }
      public string Key { get; set; }
      public int Value { get; set; }
    }
  }
}

Upvotes: 0

Views: 3008

Answers (3)

georgeouma
georgeouma

Reputation: 123

Try var [email protected](Json.Encode(YouModel));

Upvotes: 0

Steve Ruble
Steve Ruble

Reputation: 3895

The line @:data.push(@piece); will be written to the output HTML as

data.push(<the result of calling ToString() on @piece>);

You need to replace @piece with something that will be evaluated to the JSON you want. This should work:

@:data.push(@Html.Raw(Json.Encode(piece)));

Or you can just output the whole array at once:

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

Upvotes: 1

user1675891
user1675891

Reputation:

Try to pass this from Razor page to JavaScript.

@Html.Raw(@JsonConvert.SerializeObject(Model.DataPieces)
  .Replace("{\"", "{")
  .Replace(",\"", ",")
  .Replace("\":", ":"))

The replaces serve to get rid of the invalid characters produced by default in the converter without you needing to play with streams or applying other libraries. Ugly but working.

Sometimes, I also add one more replace: .Replace("\"","'") to get a more JS like look. The outer method is needed so you don't get problems with & in the "e;.

This is a hand-on solution so if anybody knows a better way, I'd love to get some feedback.

Upvotes: 0

Related Questions