Click here to Skip to main content
15,896,111 members
Articles / Web Development / HTML

Using ASP.Net Charting with Image Maps in MVC

Rate me:
Please Sign up or sign in to vote.
4.73/5 (10 votes)
13 Dec 2011CPOL10 min read 80.5K   2.9K   40  
This article presents an example to create interactive charts on the browsers using the "ASP.Net charting" tool with "Image Maps". It also demonstrates how to add the same charts in "Pdf" documents by re-using the same code.
This is an old version of the currently published article.

Download MVCChart.zip - 1.17 MB

Introduction

This article presents an example to create interactive charts on the browsers using the "ASP.Net charting" tool with "Image Maps". It also demonstrates how to add the same charts in "Pdf" documents by re-using the same code.

Background

When developing web applications, you can easily find many tools that help to add charts to your applications. Most of these tools use client side JavaScript. Among these tools, you should easily notice the "jQuery based charting libraries" and the "Telerik Charting Library". They either base the charts on "HTML5 canvases" or "SVG Graphics". These charting libraries can bring highly advanced and interactive charts to the web browsers. But sometimes common requirements in your projects may include:

  • Creating interactive charts on the web browsers;
  • Displaying the same charts in other places, such as in Microsoft Word or "Pdf" documents.

It is not an easy task to re-use the same client side JavaScript code to meet the both requirements. In this article, I will try to meet the both requirements using the "ASP.Net Charting" tool with "Image Maps" in "MVC". Different from the previously mentioned charting libraries, the charts generated by the "ASP.Net charting" tool are images. These image charts can be as beautiful as the charts created by other libraries, but they have limited ability to support user interactions on the browsers. The example application in this article is to demonstrate you the following:

  • When used with "Image Maps", the charts created by the "ASP.Net charting" tool should provide some reasonable user interaction capabilities. The "ASP.Net charting" tool enables us to easily generate the "Image Maps" associated with the charting images. You will find out how to generate the "Image Maps" and associate them with the charting images from the example application.
  • Besides showing the charts on the browsers, the example application will also show you how to use the exactly same code to create the charts to be embedded in "Pdf" documents.

The attached simple "MVC 2" web application is developed in Visual Studio 2010. Since it is developed as an MVC application, I will assume the readers to have some basic knowledge on how to use MVC.

SolutionExplorer.jpg

As shown in the solution explorer, the main building blocks of this web application are the following:

  • The "Models\BrowserShareModel.cs" file is the application's data model. We will be using the data in this data model to generate the charts using the "ASP.Net charting" tool.
  • The two files "MyChartBase.cs" and "BrowserShareChart.cs" in the "Utilities\ChartUtilities" folder implement the classes that will be used to generate the charts. The "MyChartBase.cs" defines the basic look and feel of the charts, while the "BrowserShareChart.cs" inherits from the "MyChartBase" class and overrides some methods to insert the data to the charts.
  • The "Utilities\PdfUtility.cs" file implements a simple class to generate a "Pdf" document using the chart images created by the above two classes.
  • The "Controllers\HomeController.cs" file is this simple MVC application's controller and the "Views\Home\Index.aspx" file is the application's view.

In this article, I will first introduce you the application's data model. I will then introduce you the utility classes and show you how to use these classes in the MVC application.

The Data Model

The application's data model is implemented in the "Models\BrowserShareModel.cs" file:

C#
using System.Collections.Generic;
using System.IO;
using MVCChart.Utilities.ChartUtilities;
 
 
namespace MVCChart.Models
{
    public class BrowserInformation
    {
        public string Name { get; set; }
        public double Share { get; set; }
        public string Url { get; set; }
        public string ToolTip
        {
            get
            {
                return Name + " " + Share.ToString("#0.##%");
            }
        }
    }
 
    public class BrowserShareChartData
    {
        public string Title { get; set; }
        public int Width { get; set; }
        public int Height { get; set; }
        public List<BrowserInformation> ShareData { get; set; }
 
        public MemoryStream ChartImageStream()
        {
 
            var chart = new BrowserShareChart(this);
            return chart.GetChartImage(Width, Height);
        }
 
        public string ChartImageMap(string name)
        {
            var chart = new BrowserShareChart(this);
            return chart.GetChartImageMap(Width, Height, name);
        }
    }
 
    public class BrowserShareRepository
    {
        public static BrowserShareChartData GetBrowserShares()
        {
            var chartData = new BrowserShareChartData()
                                {
                                    Title = "Browser usage on Wikipedia October 2011",
                                    Width = 450,
                                    Height = 300,
                                    ShareData = new List<BrowserInformation>()
                                };
 
            // The following data is the true data from Wikipedia
            chartData.ShareData.Add(new BrowserInformation()
                           {
                               Name = "IE",
                               Share = 0.342,
                               Url = "http://en.wikipedia.org/wiki/Internet_Explorer"
                           });
 
            chartData.ShareData.Add(new BrowserInformation()
                           {
                               Name = "Firefox",
                               Share = 0.236,
                               Url = "http://en.wikipedia.org/wiki/Firefox"
                           });
 
            chartData.ShareData.Add(new BrowserInformation()
                           {
                               Name = "Chrome",
                               Share = 0.206,
                               Url = "http://en.wikipedia.org/wiki/Google_Chrome"
                           });
 
            chartData.ShareData.Add(new BrowserInformation()
                           {
                               Name = "Safari",
                               Share = 0.112,
                               Url = "http://en.wikipedia.org/wiki/Safari_(web_browser)"
                           });
 
            chartData.ShareData.Add(new BrowserInformation()
                           {
                               Name = "Other",
                               Share = 0.104,
                               Url = null
                           });
 
            return chartData;
        }
    }
}

This file implements three classes:

  • The "BrowserInformation" defines a data point in the chart.
  • The "BrowserShareChartData" class defines the data for the chart. It holds a reference of a "List" of "BrowserInformation" objects to create the chart "Series". It also defines the width, height, and the title of the chart.
  • The "BrowserShareRepository" class instantiates a "BrowserShareChartData" object and assign it some real data about the browser market share in October 2011 that I got from the "Wikipedia".

In this article, I will show you how to create a chart using the "ASP.Net Charting" tool to visualize the browser market share information. The chart will be shown on the browsers and in a "Pdf" document. When shown in the browsers, I will add tooltips and hyperlinks to the chart using a "Image Map" to make the chart interactive. You should be able to create more advanced interactions using "Image Maps", but I will only show you how to add tooltips and hyperlinks to keep this article simple.

The Charting Utility Classes

The "Utilities\ChartUtilities\MyChartBase.cs" defines the basic look and feel of the charts in the example application:

C#
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Web.UI.DataVisualization.Charting;
 
namespace MVCChart.Utilities.ChartUtilities
{
    public class MyChartBase
    {
        protected List<Series> ChartSeriesData { get; set; }
        protected string ChartTitle { get; set; }
 
        // This is the method to get the chart image
        public MemoryStream GetChartImage(int width, int height)
        {
            var chart = InitiateChart(width, height);
            chart.RenderType = RenderType.BinaryStreaming;
 
            var ms = new MemoryStream();
            chart.SaveImage(ms, ChartImageFormat.Png);
 
            return ms;
        }
 
        // This is the method to get the chart image map
        public string GetChartImageMap(int width, int height, string mapName)
        {
            var chart = InitiateChart(width, height);
            chart.RenderType = RenderType.ImageMap;
            chart.SaveImage(Stream.Null);
 
            return chart.GetHtmlImageMap(mapName);
        }
 
        // Override this method to add title to the chart
        protected virtual void AddChartTitle()
        {
            ChartTitle = null;
        }
 
        // Override this method to add data to the chart
        protected virtual void AddChartSeries()
        {
            ChartSeriesData = new List<Series>();
        }
 
        // Initiate the chart to be rendered
        private Chart InitiateChart(int width, int height)
        {
            var chart = new Chart();
            chart.Width = width;
            chart.Height = height;
            chart.BorderSkin.BackColor = System.Drawing.Color.Transparent;
            chart.BorderSkin.PageColor = System.Drawing.Color.Transparent;
            chart.BackColor = System.Drawing.Color.FromArgb(211, 223, 240);
            chart.BorderlineDashStyle = ChartDashStyle.Solid;
            chart.BackSecondaryColor = System.Drawing.Color.White;
            chart.BackGradientStyle = GradientStyle.TopBottom;
            chart.BorderlineWidth = 1;
            chart.Palette = ChartColorPalette.BrightPastel;
            chart.BorderlineColor = System.Drawing.Color.FromArgb(26, 59, 105);
            chart.BorderSkin.SkinStyle = BorderSkinStyle.Emboss;
            chart.AntiAliasing = AntiAliasingStyles.All;
            chart.TextAntiAliasingQuality = TextAntiAliasingQuality.Normal;
 
            AddChartTitle();
            if (ChartTitle != null)
            {
                chart.Titles.Add(CreateTitle());
            }
            chart.Legends.Add(CreateLegend());
 
            AddChartSeries();
            foreach (var series in ChartSeriesData)
            {
                chart.Series.Add(series);
            }
             
            chart.ChartAreas.Add(CreateChartArea());
            return chart;
        }
 
        // Create chart title
        private Title CreateTitle()
        {
            return new Title()
                       {
                           Text = ChartTitle,
                           ShadowColor = System.Drawing.Color.FromArgb(32, 0, 0, 0),
                           Font = new System.Drawing.Font("Trebuchet MS", 10, FontStyle.Bold),
                           ShadowOffset = 3,
                           ForeColor = System.Drawing.Color.FromArgb(26, 59, 105)
                       };
        }
 
        // configure chart Legend
        private Legend CreateLegend()
        {
            return new Legend()
            {
                Docking = Docking.Bottom,
                Alignment = StringAlignment.Center,
                BackColor = System.Drawing.Color.Transparent,
                Font = new System.Drawing.Font(new System.Drawing.FontFamily("Trebuchet MS"), 8),
                LegendStyle = LegendStyle.Row
            };
        }
 
        // Configure the chart area - the chart frame x/y axes
        private ChartArea CreateChartArea()
        {
            var area = new ChartArea()
                           {
                               Name = ChartTitle,
                               BackColor = System.Drawing.Color.Transparent,
                           };
 
            area.AxisX.IsLabelAutoFit = true;
            area.AxisX.LabelStyle.Font =
                new System.Drawing.Font("Verdana,Arial,Helvetica,sans-serif",
                                        8F, FontStyle.Regular);
            area.AxisX.LineColor = System.Drawing.Color.FromArgb(64, 64, 64, 64);
            area.AxisX.MajorGrid.LineColor = System.Drawing.Color.FromArgb(64, 64, 64, 64);
            area.AxisX.Interval = 1;
 
 
            area.AxisY.LabelStyle.Font =
                new System.Drawing.Font("Verdana,Arial,Helvetica,sans-serif",
                                        8F, FontStyle.Regular);
            area.AxisY.LineColor = System.Drawing.Color.FromArgb(64, 64, 64, 64);
            area.AxisY.MajorGrid.LineColor = System.Drawing.Color.FromArgb(64, 64, 64, 64);
            
            return area;
        }
    }
}

If you create an object of this class and call the "GetChartImage" method, you will get the "MemoryStream" of an empty chart image. If you call the "GetChartImageMap" method you will get the empty html string of the "Image Map" associated with the chart image, I will not go to a great detail on how to use the "Asp.Net Charting" tool here. But if you are interested, you can take a look at the article "ASP.NET MVC Chart Control". It is the place where I got started to use the "Asp.Net Charting" tool in the MVC environment.

To visualize your data in a meaningful chart, we need to create a new class that inherits from the "MyChartBase" class and override the "AddChartSeries" and the "AddChartTitle" methods to add the data to the chart. The following is the class to create the browser market share chart in this article.

C#
using System.Collections.Generic;
using System.Web.UI.DataVisualization.Charting;
using MVCChart.Models;
 
namespace MVCChart.Utilities.ChartUtilities
{
    // This class built the browser share chart using the "ChartBase" class
    public class BrowserShareChart : MyChartBase
    {
        private BrowserShareChartData chartData;
 
        public BrowserShareChart(BrowserShareChartData chartData)
        {
            this.chartData = chartData;
        }
 
        // Add Chart Title
        protected override void AddChartTitle()
        {
            ChartTitle = chartData.Title;
        }
 
        // Override the AddChartSeries method to provide the chart data
        protected override void AddChartSeries()
        {
            ChartSeriesData = new List<Series>();
            var series = new Series()
            {
                ChartType = SeriesChartType.Pie,
                BorderWidth = 1
            };
 
            var shares = chartData.ShareData;
            foreach (var share in shares)
            {
                var point = new DataPoint();
                point.IsValueShownAsLabel = true;
                point.AxisLabel = share.Name;
                point.ToolTip = share.Name + " " + share.Share.ToString("#0.##%");
                if (share.Url != null)
                {
                    point.MapAreaAttributes = "href=\"" + share.Url + "\"";
                }
                point.YValues = new double[] { share.Share };
                point.LabelFormat = "P1";
                series.Points.Add(point);
            }
 
            ChartSeriesData.Add(series);
        }
 
    }
}

By inheriting from the "MyChartBase" class, The "BrowserShareChart" class inherits the styles defined in the "MyChartBase". To add the data for visualization,

  • It overrides the "AddChartTitle" method to add a title to the chart.
  • It also overrides the "AddChartSeries" method to add the "Series" data to the chart.

You should pay some attention to the "AddChartSeries" method. Besides adding the chart data, it also adds the tooltips and the hyperlinks to the chart "Series". If an object of the "BrowserShareChart" is properly initiated with the correct data, you can call the "GetChartImage" method inherited from the base class to obtain the chart image in the form of a "MemoryStream". You can also call the "GetChartImageMap" in the base class to obtain the "Image Map" that adds the tooltips and hyperlinks to your chart in the browsers. I will show you how to use this "Image Map" in the later part of this article.

The "Pdf" Utility Class

In order to show you how to add the chart in "Pdf" documents, I created a small class in the "Utilities\PdfUtility.cs" file:

C#
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
 
namespace MVCChart.Utilities
{
    public class PdfUtility
    {
        // Create a simple Pdf document and add an image to it.
        public static MemoryStream GetSimplePdf(MemoryStream chartImage)
        {
            const int documentMargin = 10;
 
            var pdfStream = new MemoryStream();
            var pdfDocument = new Document(PageSize.LETTER);
            pdfDocument.SetMargins(documentMargin, documentMargin, documentMargin, documentMargin);
            PdfWriter pdfWriter = PdfWriter.GetInstance(pdfDocument, pdfStream);
 
            Image image = Image.GetInstance(chartImage.GetBuffer());
            image.SetAbsolutePosition(documentMargin
                , pdfDocument.PageSize.Height - documentMargin - image.ScaledHeight);
 
            pdfDocument.Open();
            pdfDocument.Add(image);
            pdfDocument.Close();
            pdfWriter.Flush();
 
            return pdfStream;
        }
    }
}

This small class is used to generate a very simple "Pdf" document. If you pass the "MemoryStream" for the chart generated by the "BrowserShareChart" class to the "GetSimplePdf" method, it will return you a "MemoryStream" of a "Pdf" document with the chart in it. This class uses the "iTextSharp" to create the "Pdf" document. You can download "iTextSharp" from its web site. I am not going to a great detail on how to use "iTextSharp" here. If you are interested, you can take a look at the article "Export Tabular Data in PDF Format through the Web". It has more detailed introduction on how to use "iTextSharp".

Now we complete the data model and the utility classes, let us take a look at how we can use them in our MVC application.

The MVC Controller

The MVC application's controller is implemented in the "Controllers\HomeController.cs" file:

C#
using System.Web.Mvc;
using MVCChart.Models;
using MVCChart.Utilities;
 
namespace MVCChart.Controllers
{
    [HandleError]
    public class HomeController : Controller
    {
        [HttpGet]
        public ActionResult Index()
        {
            var chartData = BrowserShareRepository.GetBrowserShares();
            return View(chartData);
        }
 
        [HttpGet]
        public FileResult GetChart()
        {
            var chartData = BrowserShareRepository.GetBrowserShares();
            return File(chartData.ChartImageStream().GetBuffer()
                , @"image/png", "BrowserShareChart.png");
        }
 
        [HttpGet]
        public FileResult GetPdf()
        {
            var chartData = BrowserShareRepository.GetBrowserShares();
            var chartStream = chartData.ChartImageStream();
 
            return File(PdfUtility.GetSimplePdf(chartStream).GetBuffer()
                , @"application/pdf", "BrowserShareChart.pdf");
        }
    }
}

The controller of this MVC application has three "Action" methods:

  • The "Index" method is the application's entry point that brings up the view page of the web application.
  • The "GetChart" method calls the application's data model and indirectly calls the "GetChartImage" in the "BrowserShareChart" class to obtain the "MemoryStream" of the browser market share chart image. It then pass the chart image to the browser as a "FileResult".
  • The "GetPdf" method goes one step further. When it obtains the "MemoryStream" of the browser market share chart image, it passes it to the "GetSimplePdf" method in the "PdfUtility" class to obtain the "Pdf" document. It also passes the "Pdf" document to the browser as a "FileResult".  

The MVC View

The MVC application's view is implemented in the "Views\Home\Index.aspx" file:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<MVCChart.Models.BrowserShareChartData>" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Index</title>
    <link href="<%=Url.Content("~/content/Site.css") %>" rel="stylesheet" type="text/css" />
</head>
 
<body>
    <div style="display: inline-block">
        <div>
            <img usemap="#ChartImageMap" src="<%= Url.Action("GetChart", "Home") %>"
                alt="Asp.Net Charting generated image"
                style="width:450px;height:300px;border-width:0px;" />
            <%  Response.Write(Model.ChartImageMap("ChartImageMap"));%>
        </div>
        <div style="margin-right: 20px; text-align: right">
            <a href="<%= Url.Action("GetPdf", "Home") %>">Get the chart in Pdf</a>
        </div>
    </div>
</body>
</html>

In this simple view page, I added the following:

  • The chart image in an "img" tag and its "Image Map".
  • I also added a link to call the "GetPdf" method in the controller to download the "Pdf" document.

To add an "Image Map" to the chart, we can simply write the "Image Map" created by the "GetChartImageMap" method in the "BrowserShareChart" class next to the "img" tag where we put our chart image. Associating the "Image Map" with the chart image is pretty simple, but you need to make sure that the name of the "Image Map" matches the "usemap" attribute of the image.

Run the Application

We now complete this example application, we can then test run it. When the application starts, the browser market share pie-chart is shown in the web browser.

RunApp.gif

If we move the mouse over the chart, the "image map" takes effect, and we can see the tooltip that we specified in the chart.

RunAppToolTip.gif

If we click on one of the section in the chart, the corresponding web page is shown according to the hyperlink that we put in the chart.

RunAppHyperlink.gif

Click the back button on the browser to go back to our web page and click on the "Get the chart in Pdf" link, a "Pdf" document is generated with the same chart as the one shown in the browser.

RunAppPdf.gif

Points of Interest

  • This article presented an example to create interactive charts on the browsers using the "ASP.Net charting" tool with "Image Maps". It also demonstrated how to add the same charts in "Pdf" documents by re-using the same code.
  • There are many charting libraries and most of them can create more efficient and more interactive charts on the browsers than the "ASP.Net charting" tool. But they are dedicated to create charts on the browsers, so it is difficult to use the same charts on other places. Of course, if you only intention is to display your charts on the browsers, I would still recommend you to use the client side charting libraries like the "Telerik Charting Library", which can definitely provide better interactivity and possibly more efficient.
  • When used with the "Image Maps", the "ASP.Net charting" tool can create reasonably interactive charts on the browsers. In this example, I only showed you how to add tooltips and hyperlinks to the charts, but you can definitely make the charts more interactive by working on the "MapAreaAttributes" when you add the chart "Series". You can also add client side JavaScript to make your charts more interactive.
  • Besides creating charts beyond the browsers, the "ASP.Net charting" tool has some other advantages. In any foreseeable future we can safely assume that images are always supported anywhere on any operating systems, so your charts should be always supported if you create them as images.
  • Another advantages to use "ASP.Net charting" is that it is now included in the default deployment of the ".Net Framework". If ".Net" is your primary working environment, you do not need to add any extra "DLLs" in your projects to create your desired charts.
  • If you are developing a desktop application, you should also be able to use the "ASP.Net charting" tool to create charts and display them in your application.
  • Although the example is developed as an MVC application, you can easily use the same principle to add charts in more traditional ASP.Net application.
  • I hope you like my postings and I hope this article can help you one way or the other.

History

First revision - 12/13/2011.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
I have been working in the IT industry for some time. It is still exciting and I am still learning. I am a happy and honest person, and I want to be your friend.

Comments and Discussions

Discussions on this specific version of this article. Add your comments on how to improve this article here. These comments will not be visible on the final published version of this article.