In this blog post I will talk about how to use ASP.NET Charting controls( which Microsoft announced last year) in a ASP.NET MVC application.
If you want to read more about ASP.NET Charting Controls here is a link to Scott Gu's Blog Post : http://weblogs.asp.net/scottgu/archive/2008/11/24/new-asp-net-charting-control-lt-asp-chart-runat-quot-server-quot-gt.aspx.
I will be using Streaming Chart Images as FileResult from MVC controller article on Code Project by Nic Roshe, to read more about the article here is a link http://www.codeproject.com/KB/aspnet/MvcChartControlFileResult.aspx?msg=2959619.
Lets get started, create a new ASP.NET MVC application and add Reference to System.Web.DataVisualization. Add a Class to your project called ChartResult(Name can be anything I am just reusing the name used by Nic Roshe in the codeproject article). This ChartResult Class should derive from a FileResult Class. This Class would map and Image to a known MIME type. Further more since this class extends from FileResult Class System.Web.Mvc we get to override a WriteFile method which takes in a HttpResponseBase object. The WriteFile method can then be used to create a Output memory stream.
Here is how the Class would look like -
| 1 | public class ChartResult : FileResult |
| 2 | { |
| 3 | private const int _bufferSize = 0x1000; |
| 4 | |
| 5 | public ChartResult(Chart chart, ChartImageFormat imageFormat) |
| 6 | : base(MapImageFormatToMimeType(imageFormat)) |
| 7 | { |
| 8 | if (null == chart) throw new ArgumentNullException("chart"); |
| 9 | |
| 10 | this.Chart = chart; |
| 11 | this.ImageFormat = imageFormat; |
| 12 | } |
| 13 | |
| 14 | public ChartResult(Chart chart) |
| 15 | : this(chart, ChartImageFormat.Png) |
| 16 | { |
| 17 | } |
| 18 | |
| 19 | public Chart Chart |
| 20 | { |
| 21 | get; |
| 22 | private set; |
| 23 | } |
| 24 | |
| 25 | public ChartImageFormat ImageFormat |
| 26 | { |
| 27 | get; |
| 28 | private set; |
| 29 | } |
| 30 | |
| 31 | private static string MapImageFormatToMimeType(ChartImageFormat imageFormat) |
| 32 | { |
| 33 | switch (imageFormat) |
| 34 | { |
| 35 | case ChartImageFormat.Png: |
| 36 | return "image/png"; |
| 37 | |
| 38 | case ChartImageFormat.Jpeg: |
| 39 | return "image/jpeg"; |
| 40 | |
| 41 | case ChartImageFormat.Gif: |
| 42 | return "image/gif"; |
| 43 | |
| 44 | case ChartImageFormat.Bmp: |
| 45 | return "image/bmp"; |
| 46 | |
| 47 | case ChartImageFormat.Tiff: |
| 48 | return "image/tiff"; |
| 49 | |
| 50 | // TODO: MIME types for EMF? |
| 51 | // case ChartImageFormat.Emf: |
| 52 | // case ChartImageFormat.EmfPlus: |
| 53 | // case ChartImageFormat.EmfDual: |
| 54 | |
| 55 | default: |
| 56 | throw new ArgumentException("Unsupported format"); |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | protected override void WriteFile(HttpResponseBase response) |
| 61 | { |
| 62 | // NB: Can't save directly to the output stream, |
| 63 | // as most image formats require a seekable stream. |
| 64 | |
| 65 | using (var imageStream = new MemoryStream()) |
| 66 | { |
| 67 | this.Chart.SaveImage(imageStream, this.ImageFormat); |
| 68 | imageStream.WriteTo(response.OutputStream); |
| 69 | } |
| 70 | } |
| 71 | } |
Please note using the ChartResult and FileResult Classes, the ASP.NET Charting Control will render as a Image file on your MVC View. Now lets see how this ChartResult can be used to render a ASP.NET Charting graph as a Image.
Lets look at how the View Page would look like -
There are two possibilities to render the image, we could create a ViewPage in MVC which just renders the Image or just use an <img> tag and specify its source to be the Action Method on the Controller.
| 1 | <a href="Home/BarChart">Bar Chart</a><br /> |
| 2 | <a href="Home/PieChart">Pie Chart</a><br /> |
| 3 | <img src="Home/LineChart" alt="Line Chart" /> |
The Home/BarChart and Home/PieChart are two MVC views which are just used for rendering purpose. If you feel that its a waste to create a view just to render an image you are right :). Hence the third line in the above snippet shows how the image tags src attribute can be used to render the image. We give the src attribute an Action Method which returns a FileResult.
Now here is how the Controller Code would look like,(please note this code need not be in a controller for sake of easy demo purposes I am putting it in a controller.)
Here is how a BarChart can be constructed.
| 1 | public ChartResult BarChart() |
| 2 | { |
| 3 | Chart chart = new Chart(); |
| 4 | chart.Width = 480; |
| 5 | chart.Height = 300; |
| 6 | chart.RenderType = RenderType.ImageTag; |
| 7 | chart.Palette = ChartColorPalette.Fire; |
| 8 | Title t = new Title("Bar Chart", Docking.Left, new Font("Trebuchet MS", 14, FontStyle.Bold), Color.Black); |
| 9 | chart.Titles.Add(t); |
| 10 | |
| 11 | |
| 12 | chart.BorderSkin.SkinStyle = BorderSkinStyle.Emboss; |
| 13 | chart.BorderlineWidth = 2; |
| 14 | chart.BorderlineColor = Color.Black; |
| 15 | chart.BorderlineDashStyle = ChartDashStyle.Solid; |
| 16 | |
| 17 | chart.ChartAreas.Add("Default"); |
| 18 | |
| 19 | chart.Legends.Add("Legend1"); |
| 20 | |
| 21 | chart.Series.Add("Series 1"); |
| 22 | chart.Series.Add("Series 2"); |
| 23 | |
| 24 | List<int> data = new List<int>(); |
| 25 | data.Add(3); |
| 26 | data.Add(9); |
| 27 | data.Add(5); |
| 28 | data.Add(2); |
| 29 | data.Add(4); |
| 30 | data.Add(7); |
| 31 | |
| 32 | //Series 1 |
| 33 | foreach (int value in data) |
| 34 | { |
| 35 | chart.Series["Series 1"].Points.AddY(value); |
| 36 | } |
| 37 | |
| 38 | //Series 2 |
| 39 | foreach (int value in data) |
| 40 | { |
| 41 | chart.Series["Series 2"].Points.AddY(value - 1); |
| 42 | } |
| 43 | |
| 44 | return new ChartResult(chart, ChartImageFormat.Png); |
| 45 | |
| 46 | |
| 47 | |
| 48 | } |
Here is how a PieChart can be constructed -
| 1 | public ChartResult PieChart() |
| 2 | { |
| 3 | Chart pieChart = new Chart(); |
| 4 | |
| 5 | pieChart.Width = 480; |
| 6 | pieChart.Height = 300; |
| 7 | pieChart.RenderType = RenderType.ImageTag; |
| 8 | pieChart.Palette = ChartColorPalette.BrightPastel; |
| 9 | Title t = new Title("Pie Chart", Docking.Left, new Font("Trebuchet MS", 14, FontStyle.Bold), Color.Black); |
| 10 | pieChart.Titles.Add(t); |
| 11 | |
| 12 | |
| 13 | pieChart.ChartAreas.Add("defaultChartArea"); |
| 14 | |
| 15 | pieChart.Legends.Add("Legend1"); |
| 16 | |
| 17 | pieChart.Series.Add("PieChartSeries"); |
| 18 | |
| 19 | // Initialize an array of doubles |
| 20 | double[] yval = { 2, 6, 4, 5, 3 }; |
| 21 | |
| 22 | // Initialize an array of strings |
| 23 | string[] xval = { "Peter", "Andrew", "Julie", "Mary", "Dave" }; |
| 24 | |
| 25 | pieChart.Series["PieChartSeries"].ChartType = SeriesChartType.Pie; |
| 26 | |
| 27 | // Set series visual attributes |
| 28 | pieChart.Series["PieChartSeries"].Color = Color.CornflowerBlue; |
| 29 | pieChart.Series["PieChartSeries"].BackSecondaryColor = Color.SkyBlue; |
| 30 | |
| 31 | |
| 32 | pieChart.Series["PieChartSeries"].BorderColor = Color.Gray; |
| 33 | pieChart.Series["PieChartSeries"].BorderWidth = 2; |
| 34 | pieChart.Series["PieChartSeries"].BorderDashStyle = ChartDashStyle.Solid; |
| 35 | |
| 36 | pieChart.Series["PieChartSeries"].ShadowOffset = 2; |
| 37 | |
| 38 | |
| 39 | //Bind the data to chart |
| 40 | pieChart.Series["PieChartSeries"].Points.DataBindXY(xval, yval); |
| 41 | //Turn on Legend |
| 42 | pieChart.Series["PieChartSeries"]["PieLabelStyle"] = "Disabled"; |
| 43 | //Turn on Labelling |
| 44 | pieChart.Series["PieChartSeries"]["PieLabelStyle"] = "Inside"; |
| 45 | |
| 46 | |
| 47 | //Make the Leged to display text and percentage |
| 48 | pieChart.Series["PieChartSeries"].LegendText = "#AXISLABEL - #PERCENT{P0}"; |
| 49 | |
| 50 | return new ChartResult(pieChart, ChartImageFormat.Png); |
| 51 | |
| 52 | |
| 53 | } |
Here is how a LineChart can be constructed -
| 1 | public ChartResult LineChart() |
| 2 | { |
| 3 | |
| 4 | Chart lineChart = new Chart(); |
| 5 | |
| 6 | lineChart.Width = 480; |
| 7 | lineChart.Height = 300; |
| 8 | lineChart.RenderType = RenderType.ImageTag; |
| 9 | lineChart.Palette = ChartColorPalette.BrightPastel; |
| 10 | Title t = new Title("Line Chart", Docking.Left, new Font("Trebuchet MS", 14, FontStyle.Bold), Color.Black); |
| 11 | lineChart.Titles.Add(t); |
| 12 | |
| 13 | |
| 14 | lineChart.ChartAreas.Add("defaultChartArea"); |
| 15 | |
| 16 | lineChart.Legends.Add("Legend1"); |
| 17 | |
| 18 | lineChart.Series.Add("LineChartSeries"); |
| 19 | |
| 20 | |
| 21 | |
| 22 | |
| 23 | lineChart.Series["LineChartSeries"].ChartType = SeriesChartType.Line; |
| 24 | |
| 25 | // Set series visual attributes |
| 26 | lineChart.Series["LineChartSeries"].Color = Color.Red; |
| 27 | lineChart.Series["LineChartSeries"].BackSecondaryColor = Color.SkyBlue; |
| 28 | |
| 29 | |
| 30 | lineChart.Series["LineChartSeries"].BorderColor = Color.Gray; |
| 31 | lineChart.Series["LineChartSeries"].BorderWidth = 2; |
| 32 | lineChart.Series["LineChartSeries"].BorderDashStyle = ChartDashStyle.Solid; |
| 33 | |
| 34 | lineChart.Series["LineChartSeries"].ShadowOffset = 2; |
| 35 | |
| 36 | |
| 37 | // Populate series with random data |
| 38 | Random random = new Random(); |
| 39 | for (int pointIndex = 0; pointIndex < 15; pointIndex++) |
| 40 | { |
| 41 | lineChart.Series["LineChartSeries"].Points.AddY(random.Next(45, 95)); |
| 42 | } |
| 43 | |
| 44 | |
| 45 | return new ChartResult(lineChart, ChartImageFormat.Png); |
| 46 | |
| 47 | } |
When you run the application you can see the two hyperlinks and an image being rendered on the Home Page

Here is a BarCart
he
Here is a PieChart -
Hope this helps,
Cheers,
Venkata