To read the article online, visit http://www.4GuysFromRolla.com/articles/100610-1.aspx

Using Microsoft's Chart Controls In An ASP.NET Application: Exporting Charts

By Scott Mitchell


Introduction


The Chart Web control makes it easy to display a chart in an ASP.NET web page - simply drag the Chart control onto the page, set a few properties and either bind it to a data source control or write a few lines of code that get and bind the data of interest. When a page with a Chart control is visited by a user, the Chart control renders an <img> element on the page that displays the rendered chart.

The Chart control is great for displaying a chart on a web page, but what if a user wants to view that chart offline, or send the chart to a colleague? In an earlier installment, Programmatically Generating Chart Images, we examined a number of ways to generate the chart image programmatically. This technique is useful if you want to modify the chart image before displaying it (to, say, add a watermark) or if you want to send the chart to a recipient via email. This technique can also be used to allow the visitor to export the chart image into an alternative format.

This article shows how to let users export a chart from a web page to an alternative format. Specifically, we'll look at adding an "Export" button to the chart web page that, when clicked, exports the chart displayed in the web page to either an image file that can be downloaded or as a PDF file. Read on to learn more!

An Quick Review On Programmatically Rendering the Chart Image


As noted in the Introduction, displaying a chart in a web page is a fairly simple and straightforward process thanks to the Chart control. Thanks to the Chart control, displaying a chart in a web page is boiled down to a few simple steps: add the Chart control to the page; configure its properties; and specify the data to bind to the chart. When the page is visited, the Chart control handles the actual work of plotting the data, generating an image file that displays the plotted data, and rendering an <img> element in the web page to display that image.

While having the chart image automatically created by the Chart control is desired when displaying a standard chart in a web page, for more intricate scenarios we may need the ability to programmatically create the chart image ourselves. In Programmatically Generating Chart Images we looked at two such scenarios that warranted programmatically generating the chart's image:

  • When the chart image needs to be modified before being displayed, or
  • When the chart image needs to be displayed or provided to the user in some alternative format or medium.
Generating the chart image is easy enough thanks to the Chart class's SaveImage method, which saves the chart image to a file or a stream. To save the chart image to a file, use:

myChart.SaveImage(filePath, format)

For example, to save the chart image as a PNG image to the Images folder in your web application you would use the following code:

myChart.SaveImage(Server.MapPath("~/Images/MyChart.png"), ChartImageFormat.Png)

Alternatively, you can save the chart image to a stream. The following snippet shows how to send the contents of the chart image to a MemoryStream object:

// C#
using (var imgStream = new MemoryStream()) {
   myChart.SaveImage(imgStream, ChartImageFormat.Png);

   ... Work with stream data ...
}


' VB
Using imgStream As New MemoryStream()
   myChart.SaveImage(imgStream, ChartImageFormat.Png)

   ... Work with stream data ...
End Using

Once you have the chart image in a stream you can modify it as needed before returning it to the visitor. If you do not want to modify the chart image but just stream it directly to the client, you can save the chart image to the Response.OutputStream stream directly.

Creating an Exporting Demo


The download available at the end of this article includes two new demos. Both demos render the same user interface, namely a web page with two DropDownList controls and a Chart Web control. The visitor can choose a category and order year from the DropDownLists; doing so refreshes the page and displays a chart depicting the total sales per product in the selected category for the selected year. Beneath these two DropDownLists is an Export button that, when clicked, prompts the user to save the exported chart to their hard drive. The Export button in the first demo we'll look at exports the chart as an image file; the second demo exports the chart as a PDF file.

The screen shot below shows the first demo when viewed through a browser. Here, the visitor has opted to view the sales for Meat/Poultry in 1997. Beneath these drop-down lists is the "Export Chart to Image" button, and beneath that is the chart showing the sales figures for the specified category and year.

The export chart user interface.

Again, the idea here is that when the user clicks the Export button they are prompted whether to open or save the image (or PDF), as the dialog box below shows.

Clicking the Export button displays a file download dialog box.

Note that both demos plot the chart using K. Scott Allen's ChartBuilder class, which provides a simple API for plotting the points in a chart. This class was first examined in the Plotting Chart Data installment. The markup and code used to display the chart is not discussed in this article; refer to the download available at the end of this article for the actual code. Instead, we'll focus our attention on how to export a chart as an image and as a PDF.

Sending Content to the Client and Raising a File Download Dialog Box


When the user clicks the Export button in either demo, there is a postback - the browser submits the form, re-requesting the web page and the web server sends back some content to the browser. Typically, the web server returns HTML to the browser, which is then displayed. When the user clicks the Export button, however, we don't want to send HTML, but rather the binary contents of the chart export image or PDF file. What's more, when returning this binary data we want the browser to display a File Download dialog box rather than displaying the returned content in the browser window. We'll talk about how to return the exported image or PDF content to the browser in a moment, but first let's discuss how to prompt the browser to show the File Download dialog box.

Whenever a web server returns content to a browser - whether it's HTML or the binary contents of an image, say - the web server may include information in addition to the requested content. This additional information is supplied through HTTP headers. The web server automatically adds several HTTP headers on our behalf, but we can specify the values for these headers or add additional ones with a bit of code.

One HTTP header is the Content-Type header, which tells the browser what type of content is being returned. For example, when returning HTML, the server returns a Content-Type header with the value text/html. When returning a GIF image file, the server returns a Content-Type header with the value image/gif. These Content-Type header values are referred to as MIME Media Types and are maintained by the Internet Assigned Numbers Authority. By default, an ASP.NET page returns a Content-Type header of text/html, but you can change this header value by using the Response.ContentType property.

When the server specifies a MIME Media Type that the browser knows how to display, the content is opened within the browser. For example, if you point your browser to an image file or a PDF file that file will be loaded directly within the browser. If, instead, you want to prompt the user with a File Download dialog box to allow them to save the file to their hard drive or to open it in an external viewer, you must add a Content-Disposition HTTP header with a value that specifies the content should be treated like an attachment; you can also provide a suggested file name to save the file as.

Exporting Charts as PNG Images


When a user visits either of the export demos, a chart is displayed showing the annual sales for those products in the selected category and year. To export the chart data the user must click the Export button. From the user's perspective, clicking the Export button causes their browser to display a File Download dialog box, allowing them to save (or open) the exported image or PDF file.

As the page developer implementing this functionality, all we need to do is create a Click event handler for the Export button and write a few lines of code. In this event handler we need to do the following things:

  1. Specify the content type. When exporting the chart as a PNG image the content type is image/png; for PDF files its application/pdf.
  2. Add a Content-Disposition HTTP header so that the browser will display a File Download dialog box instead of opening the exported chart directly in the browser.
  3. Render the chart (if needed). Since my demos plot the chart's points programmatically we need to re-plot them on every postback.
  4. Generate the exported content and send it to the client by writing it to the Response.OutputStream stream.
  5. Indicate that the data to send to the client has ended by calling Response.End(). This ensures that the HTML of the web page is not also included in the export data sent to the client.
When exporting the chart as an image, step 4 is quite simple - we can call the Chart control's SaveImage method with Response.OutputStream as the first input parameter. This generates the chart image and writes it directly to the output returned to the client.

The following code implements the five steps detailed above. Here, chtSalesByCategory is the ID of the Chart control:

'STEP 1: Specify the content type
Response.ContentType = "image/png"

'STEP 2: Add a Content-Disposition header
Response.AddHeader("Content-Disposition", _
                   String.Format("attachment; filename={0}-{1}.png", _
                                 ddlCategoryNames.SelectedValue, _
                                 ddlOrderYears.SelectedValue))

'STEP 3: Render the chart
DisplayChart()

'STEP 4: Generate the exported content and send it to the client
chtSalesByCategory.SaveImage(Response.OutputStream, ChartImageFormat.Png)

'STEP 5: Indicate that the data to send to the client has ended
Response.End()

That's all there is to it! With this code in place, clicking the "Export Chart to Image" button causes a postback. On postback, the ASP.NET page generates the chart image and sends its binary contents back to the client along with a Content-Type HTTP header of image/png and a Content-Disposition header with the value attachment;filename=CategoryName-Year.png. This prompts the browser to display the File Download dialog box, allowing the user to save the image or open it with the program his computer is configured to use to view PNG files.

Exporting Charts as PDF Files


Due to their cross-platform support and free reader program, PDF files are a popular file format for exporting data. There are a variety of .NET libraries available to programmatically create PDF documents. A popular one is iTextSharp, which is the .NET version of the Java-based iText PDF library.

Part of iTextSharp's popularity stems from the fact that it's open source. However, it's important to keep in mind that starting with version 5.0, iTextSharp is released under the GNU Affero General Public License (AGPL) version 3. This license requires that any application that uses iTextSharp must also be released under the same license and that you must make your application's source code freely available (like iTextSharp's is). You can optionally buy a license to be released from the AGPL. While version 5.0 (and beyond) is released under the more restrictive AGPL, previous versions were released under the GNU Lesser General Public License (LGPL), which allows the use of iTextSharp within an application without requiring that the application also be released under the LGPL. In other words, by using version 4 or earlier, you can use iTextSharp in your web application without having to buy a license and without having to release your web application's source code. (The download available at the end of the article uses iTextSharp version 4.1.6.) Now that we have that out of the way, let's look at using iTextSharp to export charts to a PDF file.

Exporting a chart to a PDF file involves the same five steps as exporting a chart as an image. The primary difference is that step 4 - generating the exported content and sending it to the client - is a trifle more involved when exporting to PDF. When exporting a chart as an image we could just call the Chart control's SaveImage method and blast the chart image file contents directly to the Response.OutputStream stream. When exporting as a PDF, however, we need to create a PDF document, add the chart image to the PDF document, and then send the binary contents of that PDF document to the client via the Response.OutputStream stream. Other than this difference (and some other minor differences like the value of the Content-Type header), the exporting code is identical.

Here is the code for the export to PDF demo.

'STEP 1: Specify the content type
Response.ContentType = "application/pdf"

'STEP 2: Add a Content-Disposition header
Response.AddHeader("Content-Disposition", _
                   String.Format("attachment; filename={0}-{1}.pdf", _
                                 ddlCategoryNames.SelectedValue, _
                                 ddlOrderYears.SelectedValue))

'STEP 3: Render the chart
DisplayChart()

'STEP 4: Generate the exported content and send it to the client
'Create a Document object
Dim doc As New Document()

Try
   'Create a writer to dump the contents of the Document to the Response.OutputStream stream
   Dim writer As PdfWriter = PdfWriter.GetInstance(doc, Response.OutputStream)
   doc.Open()

   'Now create the chart image and add it to the PDF
   Using imgStream As New MemoryStream()
      'Save the chart to a MemoryStream
      chtSalesByCategory.SaveImage(imgStream, ChartImageFormat.Png)

      'Create an Image object from the MemoryStream data
      Dim img As Image = Image.GetInstance(imgStream.ToArray())

      'Scale the Image object to fit within the boundary of the PDF document and add it
      img.ScaleToFit(doc.PageSize.Width - (doc.LeftMargin + doc.RightMargin), _
                     doc.PageSize.Height - (doc.TopMargin + doc.BottomMargin))
      doc.Add(img)
   End Using
Finally
   doc.Close()
End Try

'STEP 5: Indicate that the data to send to the client has ended
Response.End()

That's all there is to it! Granted, the export PDF is bland and brain dead simple - as the screen shot below shows, the PDF contains nothing but the chart image, sized to fit within the PDF document's margins. But with a bit of extra code you could certainly gussy up the PDF to include additional text, a table of data used to built the chart, and other information.

The chart has been exported to a PDF file.

Conclusion


The Chart control makes it easy to display charts within a web page, but with a bit of code it's possible to generate the underlying chart image, which can then be exported. In this article we reviewed how to programmatically generate a chart image and then examined the steps necessary to export data to the browser so that the user is presented with a File Download dialog box rather than having the content displayed directly within the browser. We then put these two capabilities together, allowing the user to export a chart as either a PNG image or as a PDF file.

Happy Programming!

  • By Scott Mitchell


    Attachments:

  • Download the code for this article
  • Further Reading:

  • Programmatically Generating Chart Images
  • Plotting Chart Data
  • How To Raise a "File Download" Dialog Box for a Known MIME Type
  • Article Information
    Article Title: ASP.NET.Using Microsoft's Chart Controls In An ASP.NET Application: Exporting Charts
    Article Author: Scott Mitchell
    Published Date: October 6, 2010
    Article URL: http://www.4GuysFromRolla.com/articles/100610-1.aspx


    Copyright 2014 QuinStreet Inc. All Rights Reserved.
    Legal Notices, Licensing, Permissions, Privacy Policy.
    Advertise | Newsletters | E-mail Offers