Monday, September 17, 2012

Creating Interactive Charts with ASP.net MVC

Chart Control

Problem at Hand:

Many ASP.net developers are used to creating charts using the .NET built-in Chart Controls, but how about MVC developers? Are they out of luck?

A couple weeks ago I was looking for a way to generate nice looking charts for an application I'm working on and I found out that while there are several ways to use the .NET chart controls in MVC, most of the implementations lack interactivity and therefore were useless for the application I wanted to create. I found an example from Daniel A Hill using a custom chart action result and it looked promising, but it lacked interactivity as well, so I started looking for a way to make my own Action that would do what I wanted.

If we look at the underlying HTML that is generated by chart controls, we see that it consists of a <img> and a <map>, so all we need to do is create both of these and we will have our interactive controls.

Controller Action:

public ActionResult Chart()
{
    var chart = buildChart();
    StringBuilder result = new StringBuilder();
    result.Append(getChartImage(chart));
    result.Append(chart.GetHtmlImageMap("ImageMap"));
    return Content(result.ToString());
}

Utility Functions:

private Chart buildChart()
{
    // Build Chart
    var chart = new Chart();

    // Create chart here
    chart.Titles.Add(CreateTitle());
    chart.Legends.Add(CreateLegend());
    chart.ChartAreas.Add(CreateChartArea());
    chart.Series.Add(CreateSeries());

    return chart;
}

private string getChartImage(Chart chart)
{
    using (var stream = new MemoryStream())
    {
       string img = "<img src='data:image/png;base64,{0}' alt='' usemap='#ImageMap'>";
       chart.SaveImage(stream, ChartImageFormat.Png);
       string encoded = Convert.ToBase64String(stream.ToArray());
       return String.Format(img, encoded);
    }
}

Then in your View code:

@{ Html.RenderAction("Chart"); }

Conclusion:

This is all there is to it. One caveat is that you MUST call chart.SaveImage() before calling chart.GetHtmlImageMap(), otherwise it will throw an Exception, but if you are careful in doing that, it should all just work.To see an example of the new controller in action, head over to MVC Chart. To see the whole source code, take a look at my github repository.


4 comments:

  1. This looks very cool, do you have an online example to take a look at?

    ReplyDelete
  2. My application is hosted at an intranet, so it's not accessible to the outside world.
    You can use any example from MS Chart Controls in your own MVC application by creating a controller like the one above. Just modify the buildChart function above to create the chart of your choice (i.e. from the Microsoft examples) and you will have the full power of the MS chart control in MVC.
    Let me know if you want me find you more examples of how to build these charts...

    ReplyDelete
  3. I wrote a quick demo using the same controller and I'm hosting it at MVC Chart. You can see how it works there.

    ReplyDelete
  4. You saved me tons of work Flavio. Thanks for posting this. Best solution I saw around.

    ReplyDelete