MVC5 实时刷新 Chart.js
MVC5 Live refresh Chart.js
我目前正在创建一个仪表板来显示通过 Chart.js 从 Google Analytics 获得的信息。目标是允许用户选择指标、日期和时间间隔来绘制图表,仪表板将调用 Google 并在单击按钮时更新图表。仪表板是在 Visual Studio 2013 年在 MVC 应用程序中创建的。仪表板当前如下所示:
右边画得不好的方框是我打算放按钮的地方。我遇到的问题是为按钮创建功能。我对 MVC 非常陌生,而且我比较确定我已经打破了逻辑,因为我没有视图。这个app基本上变成了Controller to View。 (这是几十个 MVC 教程之后发生的事情。
控制器目前看起来是这样的:
public enum Metrics{users, newUsers, percentNewSessions, sessionsPerUser, sessions, bounces, bounceRate, sessionDuration, hits}
public enum Interval{Today, Yesterday, LastWeek, LastTwoWeeks, Daily, Weekly, Monthly, Yearly}
public class HomeController : Controller
{
public ActionResult Index()
{
string accountEmailAddress = "email@thing.com";
string keyPath = Server.MapPath("path");
var certificate = new X509Certificate2(keyPath, "blah", X509KeyStorageFlags.Exportable);//Creates certificate
var credentials = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(accountEmailAddress)
{
Scopes = new[] { AnalyticsService.Scope.AnalyticsReadonly }
}.FromCertificate(certificate));//Creates credentials ot GA server
AnalyticsService service = new AnalyticsService(new BaseClientService.Initializer()
{
HttpClientInitializer = credentials,
ApplicationName = "Dash"
});//Starts the service up.
string profileId = "ga:59346790";
string startDate = "2012-06-07";
string endDate = "2015-02-17";
string timing = "Yearly";
string metrics = "ga:users";
string[] dates = DateList(startDate, endDate, timing);
List<string> ColumnName = new List<string>();
List<double> values = new List<double>();
if (timing.Equals("Daily"))
{
for (int i = 0; i < dates.Length - 1; i++)
{
DataResource.GaResource.GetRequest request = service.Data.Ga.Get(profileId, dates[i], dates[i], metrics);
GaData data = request.Execute();
ColumnName.Add(DateLabel(dates[i]));
if (data.Rows == null)
{
values.Add(0);
}
else
{
foreach (var row in data.Rows)
{
foreach (var item in row)
{
values.Add(Convert.ToDouble(item));
}
}
}
}
}
else
{
for (int i = 0; i < dates.Length - 2; i+=2)
{
DataResource.GaResource.GetRequest request = service.Data.Ga.Get(profileId, dates[i], dates[i + 1], metrics);
GaData data = request.Execute();
ColumnName.Add(DateLabel(dates[i]));
if (data.Rows == null)
{
values.Add(0);
}
else
{
foreach (var row in data.Rows)
{
foreach (var item in row)
{
values.Add(Convert.ToDouble(item));
}
}
}
}
}
List<Metrics> metricList = Enum.GetValues(typeof(Metrics)).Cast<Metrics>().ToList();
List<Interval> intervalList = Enum.GetValues(typeof(Interval)).Cast<Interval>().ToList();
ViewBag.Metrics = new SelectList(metricList);
ViewBag.Intervals = new SelectList(intervalList);
values.OrderByDescending(m => values.Min());
ViewBag.ColumnName = ColumnName.ToArray();
ViewBag.Values = values.ToArray();
int[] test = { 3, 5, 6, 7, 3, 8, 9 };
ViewBag.intArray = test;
string[] testLabel = { "This", "Is", "A", "Test", "You", "Got", "It?" };
ViewBag.strArray = testLabel;
return View();
}
private static string DateLabel(string date){ ....code}
private static string[] DateList(string startDate, string endDate, string timing){...code}
}
这是我的观点:
@{
ViewBag.Title = "Home Page";
double[] result = ViewBag.Values;
string[] labels = ViewBag.ColumnName;
string test = "";
string label = "";
for(int i =0; i<= result.Length - 1; ++i)
{
if(i==0)
{
test = test + result[i].ToString();
}
else
{
test = test + "," + result[i].ToString();
}
}
for (int i = 0; i <= labels.Length - 1; ++i)
{
if (i == 0)
{
label = label + labels[i].ToString();
}
else
{
label = label + "," + labels[i].ToString();
}
}
}
<label for="myChart">
Google Analytics<br />
<canvas id="myChart" width="800" height="400"></canvas>
</label>
<div>
<label for="Metrics">
Metrics <br />
@Html.DropDownList("Metrics", (SelectList)ViewBag.Metrics, new { @class = "form-control" })
</label>
<label for="Intervals">
Interval<br />
@Html.DropDownList("Intervals", (SelectList)ViewBag.Intervals, new { @class = "form-control" })
</label>
<label for="StartDate">
Start Date<br />
@Html.TextBox("StartDate")
</label>
<label for="EndDate">
End Date<br />
@Html.TextBox("EndDate")
</label>
</div>
<script>
var result = "@test";
var resultsArray = result.split(',');
var newLabels = "@label";
var labelsArray = newLabels.split(',');
var context = $("#myChart").get(0).getContext("2d");
var data = {
labels: labelsArray,
datasets: [{
label: "My First dataset",
fillColor: "rgba(220,220,220,0,2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: resultsArray
}]
}
var options = {
///Boolean - Whether grid lines are shown across the chart
scaleShowGridLines: true,
//String - Colour of the grid lines
scaleGridLineColor: "rgba(0,0,0,.05)",
//Number - Width of the grid lines
scaleGridLineWidth: 1,
//Boolean - Whether the line is curved between points
bezierCurve: true,
//Number - Tension of the bezier curve between points
bezierCurveTension: 0.4,
//Boolean - Whether to show a dot for each point
pointDot: true,
//Number - Radius of each point dot in pixels
pointDotRadius: 4,
//Number - Pixel width of point dot stroke
pointDotStrokeWidth: 1,
//Number - amount extra to add to the radius to cater for hit detection outside the drawn point
pointHitDetectionRadius: 20,
//Boolean - Whether to show a stroke for datasets
datasetStroke: true,
//Number - Pixel width of dataset stroke
datasetStrokeWidth: 2,
//Boolean - Whether to fill the dataset with a colour
datasetFill: true,
}
var myLineChart = new Chart(context).Line(data, options)
$(document).ready(function () {
$('#StartDate').datepicker();
$('#EndDate').datepicker();
});
</script>
如果有人可以告诉我如何使用我当前的代码创建一个按钮来实时刷新仪表板,那就太好了,尽管就 MVC 标准而言,代码有点 FUBAR。我愿意接受温和的(或不那么)推动他正确的方向。
不要在 Controller 的 Index 方法中填充图表数据或在加载视图时绘制图表数据。创建一个单独的方法(甚至可以查看 WebAPI),仅 returns JSON 您将用于填充图表的数据。调用该方法并在单击按钮时刷新图表。用于填充图表的 JavaScript 也应该在一个单独的文件中,而不是包含在视图的文本中。图表将刷新,而无需重新加载整个页面。
Google for AJAX
如果您想了解更多关于这是如何完成的。
我也会考虑使用 SignalR 这样您就不需要按钮,服务器可以在图表可用时将新数据发送到图表,但这可能是一种高级技术。
我目前正在创建一个仪表板来显示通过 Chart.js 从 Google Analytics 获得的信息。目标是允许用户选择指标、日期和时间间隔来绘制图表,仪表板将调用 Google 并在单击按钮时更新图表。仪表板是在 Visual Studio 2013 年在 MVC 应用程序中创建的。仪表板当前如下所示:
控制器目前看起来是这样的:
public enum Metrics{users, newUsers, percentNewSessions, sessionsPerUser, sessions, bounces, bounceRate, sessionDuration, hits}
public enum Interval{Today, Yesterday, LastWeek, LastTwoWeeks, Daily, Weekly, Monthly, Yearly}
public class HomeController : Controller
{
public ActionResult Index()
{
string accountEmailAddress = "email@thing.com";
string keyPath = Server.MapPath("path");
var certificate = new X509Certificate2(keyPath, "blah", X509KeyStorageFlags.Exportable);//Creates certificate
var credentials = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(accountEmailAddress)
{
Scopes = new[] { AnalyticsService.Scope.AnalyticsReadonly }
}.FromCertificate(certificate));//Creates credentials ot GA server
AnalyticsService service = new AnalyticsService(new BaseClientService.Initializer()
{
HttpClientInitializer = credentials,
ApplicationName = "Dash"
});//Starts the service up.
string profileId = "ga:59346790";
string startDate = "2012-06-07";
string endDate = "2015-02-17";
string timing = "Yearly";
string metrics = "ga:users";
string[] dates = DateList(startDate, endDate, timing);
List<string> ColumnName = new List<string>();
List<double> values = new List<double>();
if (timing.Equals("Daily"))
{
for (int i = 0; i < dates.Length - 1; i++)
{
DataResource.GaResource.GetRequest request = service.Data.Ga.Get(profileId, dates[i], dates[i], metrics);
GaData data = request.Execute();
ColumnName.Add(DateLabel(dates[i]));
if (data.Rows == null)
{
values.Add(0);
}
else
{
foreach (var row in data.Rows)
{
foreach (var item in row)
{
values.Add(Convert.ToDouble(item));
}
}
}
}
}
else
{
for (int i = 0; i < dates.Length - 2; i+=2)
{
DataResource.GaResource.GetRequest request = service.Data.Ga.Get(profileId, dates[i], dates[i + 1], metrics);
GaData data = request.Execute();
ColumnName.Add(DateLabel(dates[i]));
if (data.Rows == null)
{
values.Add(0);
}
else
{
foreach (var row in data.Rows)
{
foreach (var item in row)
{
values.Add(Convert.ToDouble(item));
}
}
}
}
}
List<Metrics> metricList = Enum.GetValues(typeof(Metrics)).Cast<Metrics>().ToList();
List<Interval> intervalList = Enum.GetValues(typeof(Interval)).Cast<Interval>().ToList();
ViewBag.Metrics = new SelectList(metricList);
ViewBag.Intervals = new SelectList(intervalList);
values.OrderByDescending(m => values.Min());
ViewBag.ColumnName = ColumnName.ToArray();
ViewBag.Values = values.ToArray();
int[] test = { 3, 5, 6, 7, 3, 8, 9 };
ViewBag.intArray = test;
string[] testLabel = { "This", "Is", "A", "Test", "You", "Got", "It?" };
ViewBag.strArray = testLabel;
return View();
}
private static string DateLabel(string date){ ....code}
private static string[] DateList(string startDate, string endDate, string timing){...code}
}
这是我的观点: @{ ViewBag.Title = "Home Page";
double[] result = ViewBag.Values;
string[] labels = ViewBag.ColumnName;
string test = "";
string label = "";
for(int i =0; i<= result.Length - 1; ++i)
{
if(i==0)
{
test = test + result[i].ToString();
}
else
{
test = test + "," + result[i].ToString();
}
}
for (int i = 0; i <= labels.Length - 1; ++i)
{
if (i == 0)
{
label = label + labels[i].ToString();
}
else
{
label = label + "," + labels[i].ToString();
}
}
}
<label for="myChart">
Google Analytics<br />
<canvas id="myChart" width="800" height="400"></canvas>
</label>
<div>
<label for="Metrics">
Metrics <br />
@Html.DropDownList("Metrics", (SelectList)ViewBag.Metrics, new { @class = "form-control" })
</label>
<label for="Intervals">
Interval<br />
@Html.DropDownList("Intervals", (SelectList)ViewBag.Intervals, new { @class = "form-control" })
</label>
<label for="StartDate">
Start Date<br />
@Html.TextBox("StartDate")
</label>
<label for="EndDate">
End Date<br />
@Html.TextBox("EndDate")
</label>
</div>
<script>
var result = "@test";
var resultsArray = result.split(',');
var newLabels = "@label";
var labelsArray = newLabels.split(',');
var context = $("#myChart").get(0).getContext("2d");
var data = {
labels: labelsArray,
datasets: [{
label: "My First dataset",
fillColor: "rgba(220,220,220,0,2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: resultsArray
}]
}
var options = {
///Boolean - Whether grid lines are shown across the chart
scaleShowGridLines: true,
//String - Colour of the grid lines
scaleGridLineColor: "rgba(0,0,0,.05)",
//Number - Width of the grid lines
scaleGridLineWidth: 1,
//Boolean - Whether the line is curved between points
bezierCurve: true,
//Number - Tension of the bezier curve between points
bezierCurveTension: 0.4,
//Boolean - Whether to show a dot for each point
pointDot: true,
//Number - Radius of each point dot in pixels
pointDotRadius: 4,
//Number - Pixel width of point dot stroke
pointDotStrokeWidth: 1,
//Number - amount extra to add to the radius to cater for hit detection outside the drawn point
pointHitDetectionRadius: 20,
//Boolean - Whether to show a stroke for datasets
datasetStroke: true,
//Number - Pixel width of dataset stroke
datasetStrokeWidth: 2,
//Boolean - Whether to fill the dataset with a colour
datasetFill: true,
}
var myLineChart = new Chart(context).Line(data, options)
$(document).ready(function () {
$('#StartDate').datepicker();
$('#EndDate').datepicker();
});
</script>
如果有人可以告诉我如何使用我当前的代码创建一个按钮来实时刷新仪表板,那就太好了,尽管就 MVC 标准而言,代码有点 FUBAR。我愿意接受温和的(或不那么)推动他正确的方向。
不要在 Controller 的 Index 方法中填充图表数据或在加载视图时绘制图表数据。创建一个单独的方法(甚至可以查看 WebAPI),仅 returns JSON 您将用于填充图表的数据。调用该方法并在单击按钮时刷新图表。用于填充图表的 JavaScript 也应该在一个单独的文件中,而不是包含在视图的文本中。图表将刷新,而无需重新加载整个页面。
Google for AJAX
如果您想了解更多关于这是如何完成的。
我也会考虑使用 SignalR 这样您就不需要按钮,服务器可以在图表可用时将新数据发送到图表,但这可能是一种高级技术。