Reigo Hein
Reigo Hein

Reputation: 751

Implementing MS Charts in ASP.NET MVC3 project

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

Answers (1)

Johan Danforth
Johan Danforth

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

Related Questions