However, my nose is talking about the smell of code.
Oh yes, it stinks, I feel it.
Is there a better way to write this?
Sure. Never create JSON manually, as you did, mixing 2 languages ββand writing loops and stuff. Use the JSON serializer:
@model IEnumerable<Tuple<DateTime,int,int>> <div id="chart_div_2" style="width: 900px; height: 500px;"></div> <script type="text/javascript" src="https://www.google.com/jsapi"></script> <script type="text/javascript"> google.load("visualization", "1", { packages: ["corechart"] }); google.setOnLoadCallback(drawChart); function drawChart() { var arr = @Html.Raw( Json.Encode( new object[] { new[] { "Year", "Sales", "Expenses" } } .Concat( Model.Select(x => new object[] { x.Item1.ToString("MMM d"), x.Item2, x.Item3 }) ) ) ); var data = google.visualization.arrayToDataTable(arr); var chart = new google.visualization.LineChart(document.getElementById('chart_div_2')); chart.draw(data); } </script>
This will create equivalent code markup like yours, but all the manipulations and coding of the model are done on the server. You can also write your own HTML helper to simplify the code:
public static class ChartExtensions { public static IHtmlString ToChartData( this IEnumerable<Tuple<DateTime, int, int>> model, params string[] titles ) { return new HtmlString( Json.Encode( new object[] { titles } .Concat( model.Select(x => new object[] { x.Item1.ToString("MMM d"), x.Item2, x.Item3 }) ) ) ); } }
and then, in your opinion:
@model IEnumerable<Tuple<DateTime,int,int>> <div id="chart_div_2" style="width: 900px; height: 500px;"></div> <script type="text/javascript" src="https://www.google.com/jsapi"></script> <script type="text/javascript"> google.load("visualization", "1", { packages: ["corechart"] }); google.setOnLoadCallback(drawChart); function drawChart() { var arr = @Model.ToChartData("Year", "Sales", "Expenses"); var data = google.visualization.arrayToDataTable(arr); var chart = new google.visualization.LineChart(document.getElementById('chart_div_2')); chart.draw(data); } </script>