Reputation: 751
I have a MVC application, which creates a Chart in the business logic like this:
StatisticsModel.Chart.Width = 150
StatisticsModel.Chart.Height = 300
StatisticsModel.Chart.Attributes.Add("align", "left")
StatisticsModel.Chart.Titles.Add("Statistics for: " + StatisticsModel.ProductNumbers)
StatisticsModel.Chart.ChartAreas.Add(New ChartArea)
StatisticsModel.Chart.Series.Add(New Series)
StatisticsModel.Chart.Series(0).ChartType = SeriesChartType.Column
StatisticsModel.Chart.Series(0).Points.DataBindXY(StatisticsModel.FailedTPDescriptionList, "key", StatisticsModel.FailedTPDescriptionList, "value")
Now, I am trying to implement it in the View, but I have read many articles, and they suggest me to put the chart in a different controller. But that would mean I have to send the Chart object there, as I have many functions, that require a chart, and I thought the easiest way is to implement it in the Model, and then rendering it from there.
I tried using: http://code-inside.de/blog-in/2008/11/27/howto-use-the-new-aspnet-chart-controls-with-aspnet-mvc/
But the:
@Code
Dim writer As New HtmlTextWriter(Page.Response.Output)
End Code
Didn't work for me. I am using VB.NET
Can anyone help me? Suggestions are very welcome.
Upvotes: 0
Views: 994
Reputation: 4579
There are many, many ways of creating and showing charts in MVC, and the link you referred to is pretty good IMHO. I'm using c#, but the way I'm doing it is to use an img-tag in the view and point the src-attribute to a Controller action:
<img id="diagram" src="<%=Url.Action("DrawChartImage", "Home") %>" alt="Chart Diagram" />
The controller action returns a FileContentResult:
public ActionResult DrawChartImage()
{
using (var chartHelper = new ChartHelper())
{
//get data
var data = GetSomeDataForTheChart();
//draw chart
chartHelper.Draw(data);
//return chart as png image
return File(chartHelper.Image, "image/png");
}
}
The ChartHelper class implements IDisposable and has a helper property (Image) which returns the chart as a file, NOTE this is just sample/snippet code to show what I mean:
public class ChartHelper : IDisposable
{
private readonly Chart _chart;
public Chart Chart
{
get
{
return _chart;
}
}
public byte[] Image
{
get
{
using (var ms = new MemoryStream())
{
_chart.SaveImage(ms);
return ms.GetBuffer();
}
}
}
public ChartHelper()
{
_chart = new Chart();
_chart.Height = 300;
_chart.Width = 800;
_chart.ImageType = ChartImageType.Png;
_chart.Titles.Add("some title");
_chart.Legends.Add("some legend");
_chart.ChartAreas.Add("some chart area");
}
public void Draw(List<Data> data)
{
var dataArrays = GetDataArrays(data); //another helper method...
var series = new Series(tag);
series.Name = tag;
series.Legend = "tags";
series.ChartType = SeriesChartType.Spline;
series.BorderWidth = 4;
//sample way to add data below...
series.Points.DataBindXY(dataArrays.Item1, dataArrays.Item2);
_chart.Series.Add(series);
}
public void Dispose()
{
_chart.Dispose();
}
}
Works pretty well for me, hope it helps even if it's in C#.
EDIT If you want to create the image/chart in business logic called from your "main" Controller action, maybe you can do something like this where you generate the image/chart and then save it to disk, cache or database and pick it up from the image rendering controller action:
public ActionResult Index()
{
//this is call to your business logic or similar which generates the chart
byte[] image = GenerateImage();
//save image to cache, disk or from database
HttpContext.Cache["image"] = image;
return View();
}
public ActionResult Image()
{
//get image from cache, disk or from database
var image = HttpContext.Cache["image"] as byte[];
return File(image, "image/png");
}
//some sample/dummy code to generate image from a template
private byte[] GenerateImage()
{
using (var ms = new MemoryStream())
{
using (var image = System.Drawing.Image.FromFile(@"c:/temp/template.png"))
using (var brush = new SolidBrush(System.Drawing.Color.Black))
using (var bmp = new System.Drawing.Bitmap(image, image.Width, image.Height))
using (var g = System.Drawing.Graphics.FromImage(bmp))
{
g.DrawString(DateTime.Now.ToLongTimeString(), new Font("Consolas", 10), brush, 10, 10);
bmp.Save(ms, ImageFormat.Png);
}
return ms.ToArray();
}
}
And the view would be:
<img src="@Url.Action("Image")"/>
Upvotes: 2