When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips
Search

Sections:
Book Reviews
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
Web Hosts
XML
Information:
Advertise
Feedback
Author an Article

ASP ASP.NET ASP FAQs Message Board Feedback
 
Print this Page!
Published: Wednesday, August 19, 2009

Using Microsoft's Chart Controls In An ASP.NET Application: Rendering the Chart

By Scott Mitchell


A Multipart Series on Microsoft's Chart Controls
A picture is worth a 1,000 words... This adage rings especially true when it comes to reporting. Charts summarize and illuminate patterns in data in a way that long tables of numbers simply cannot. The Microsoft Chart Controls are a free and encompassing set of charts for WinForms and ASP.NET applications. This article series explores how to use these Chart Controls in an ASP.NET application.

  • Getting Started - walks through getting started using the Chart Controls, from version requirements to downloading and installing the Chart Controls, to displaying a simple chart in an ASP.NET page.
  • Plotting Chart Data - examines the multitude of ways by which data can be plotted on a chart, from databinding to manually adding the points one at a time.
  • Rendering the Chart - the Chart Controls offer a variety of ways to render the chart data into an image. This article explores these options.
  • Sorting and Filtering Chart Data - this article shows how to programmatically sort and filter the chart's data prior to display.
  • Programmatically Generating Chart Images - learn how to programmatically create and alter the chart image file.
  • Creating Drill Down Reports - see how to build drill down reports using the Chart control.
  • Adding Statistical Formulas - learn how to add statistical formulas, such as mean, median, variance, and forecasts, to your charts.
  • Enhancing Charts With Ajax - improve the user experience for dynamic and interactive charts using Ajax.
  • Serializing Chart Data - see how to persist a chart's data and appearance to a persistent store.
  • Using the Chart Controls with ASP.NET MVC - learn how to display charts in an ASP.NET MVC application.
  • Exporting Charts - allow visitors to export charts as images and PDF files.
  • (Subscribe to this Article Series! )

    Introduction


    The Microsoft Chart Controls provide ASP.NET developers with an API and a Web control for creating and displaying charts in a web page. Behind the scenes, the Microsoft Chart Controls take the data to be plotted and dynamically generates an image. This image can be generated using one of three techniques: the Chart Web control can generate the image and save it to the web server's file system in a specified location; the Chart control can generate the image and store it in memory, session, or elsewhere, and have that image served by a built-in HTTP Handler, ChartHttpHandler; or the Chart control can send back the binary contents of the chart image directly to the browser. The chart image can be rendered using one of four image types: PNG, JPG, BMP, or EMF. And when rendering a JPG you can specify its compression level.

    Regardless of the image file type and the technique used to generate the image, the Chart Web control renders an <img> element whose src attribute references the image (or the image-producing HTTP Handler or ASP.NET page). When a browser requests a web page with a Chart control on it, it receives this <img> element as part of the page's rendered markup and then makes a request to the URL specified in the src attribute (just like it does for any other image on a web page). The chart image file the browser requests either already exists in which case its contents are returned, or the image is dynamically-generated. Either way, the end result is that the browser is sent back the chart as an image file, which is displays.

    This article explores the three different techniques the Microsoft Chart Controls has at its disposal for generating chart images. We'll look at how to use each option, enumerate the pros and cons, and discuss when to consider using one option over another. Read on to learn more!

    - continued -

    Generating And Serving Static Images


    The simplest and most straightforward manner for generating the chart images is to have the Chart Web control itself create and save the chart image to the web server's file system whenever a page is requested. In short, whenever a page with a Chart control is requested, the Chart control takes the data to be plotted and generates an image of the appropriate image type (PNG, JPG, etc.). It then saves this image in a specified folder and renders an <img> element whose src attribute points to the just-created image.

    The two key Chart control properties that dictate how the chart image is rendered are ImageStorageMode and ImageLocation. To have the chart images rendered as a static file on the web server's file system, set the ImageStorageMode property to UseImageLocation and the ImageLocation property to the file name and folder name where you want the images stored.

    The following snippet shows how to create a Chart control that saves the generated chart image to a specific file on the file system, ~/Images/Chart.png. This location is specified via the ImageLocation property.

    <asp:Chart ID="chtSalesPerDOW" runat="server" Width="500" Height="350"
             ImageLocation="~/Images/Chart"
             ImageStorageMode="UseImageLocation"
             ImageType="Png"
    >
       ...
    </asp:Chart>

    First, note that the ImageStorageMode property is set to UseImageLocation. This property instructs the Chart control to render the chart image itself and to save it to the web server's file system.

    The next property, ImageLocation, specifies the location on the web server's file system where the chart image should be saved. This chart image should be saved to a folder within the website (as opposed to C:SomeRandomDirectory), as the image needs to be accessible to the browser visiting the page. Note that the ImageLocation does not specify the extension of the image file. Rather, that extension is based on the ImageType property.

    The ImageType property is set to Png, which generates a PNG image file that has the extension .png. (I explicitly set the ImageType property in the above markup to illustrate how the file extension is dependent on the ImageType. However, I did not need to set the ImageType property to Png explicitly, as Png is this property's default value.)

    Putting it all together, based on the ImageStorageMode, ImageLocation, and ImageType properties, the Chart control will save the rendered chart image to a file named ~/Images/Chart.png.

    Folders and Permissions
    When saving images to the web server's file system you need to ensure that the folder you specify in the ImageLocation property exists and has the appropriate permissions. Namely, the folder needs to enable Write permissions for the system (or user) account that the request is operating under. If you are testing through Visual Studio using the ASP.NET Development Web Server, then the web server operates under the same account as you're logged on as, so there should be no permission issues. However, if you are using IIS then you'll need to be certain to grant Write permissions to the appropriate account (most likely Network Service).

    Anytime a website or API or Web control starts saving files to the web server's file system there are a number of technological challenges that must be addressed:

    • How are naming conflicts resolved? The Chart control in the above code snippet saves the chart image with the file name ~/Images/Chart.png. But what if a file with that name already exists? Is the file overwritten?
    • How are concurrent requests handled? What happens if two users visit the same chart-generating page at the same time? If the Chart control displays the same data to all users, then there's no problem, but what might happen if the data displayed in the chart is based on input entered by the visiting user. Imagine that one user comes to this page and has their chart rendered as an image and saved to the file system (~/Images/Chart.png), but before the HTML is sent down to the client another user's visits this page, generating a different chart. This second chart would be saved to the file system with the same file name as the first one (~/Images/Chart.png). A few moments later, when the first user's browser completes downloading the page's HTML and requests the chart image, the image returned will be the second user's chart! To work around this we could create a new image file each time the page was visited rather than overwrite the existing file, but then what would we name this new file?
    • How are stale files removed from the file system? If every time a user visits a chart page a new chart image is created, the web server's file system will soon fill up with image files. Consequently, there needs to be some mechanism that periodically removes old chart images.
    The good news is that the Microsoft Chart Controls include built-in functionality that addresses these challenges. When generating static images you can specify keywords in the ImageLocation property that provide instructions on how to resolve naming conflicts and indicate what policies to use to clean up old chart image files. The allowable keywords follow:

    KeywordDescription
    #UIDGenerates a unique file name for each image. When the image file is generated the #UID keyword is replaced with a globally unique identifier value. For example, setting ImageLocation to "~/Images/Chart_#UID" would generate an image file name like ~/Images/Chart_7795fa87-ef6b-4e9f-9c66-abb2b9980185.png (assuming the ImageType property was set to Png).

    When using this keyword you are responsible for deleting the generated image files.

    #SEQ(maxFiles,minutes)Generates a sequence number that ranges from 1 up to maxFiles, before restarting back at 1. This ensures that there are never more than maxFiles number of chart image files stored in the specified folder. The minutes parameter specifies the number of minutes old a file must be before the file name can be reused.

    For example, setting ImageLocation to "~/Images/Chart_#SEQ(50,5)" would generate an image file name like ~/Images/Chart_000001.png. The next generated image would be named ~/Images/Chart_000002.png, and so on up to ~/Images/Chart_000050.png.

    #NOGUIDPARAMWhen the Chart control renders the <img> element whose src attribute points to the chart image file, it appends a globally unique identifier onto the querystring. This is done so that the browser won't serve a cached version of the image.

    Imagine that you use the keyword #SEQ(5,5) in the ImageLocation property. A user may visit the web page with the Chart and get back an <img> element with an src attribute of ~/Images/Chart_000002.png. If the user visits the same page a bit later, there may have been 5 subsequent requests by other users, thereby cycling the file name of the chart image back to ~/Images/Chart_000002.png. Upon seeing this URL in the src attribute, the browser may say, "Wait, I already have this image in my cache," and serve that instead, which is problematic in the case when the user is viewing a different chart than the one in the cache. To circumvent this issue, the Chart control tacks on a GUID to the querystring (like ~/Images/Chart_000002.png?7795fa87-ef6b-4e9f-9c66-abb2b9980185.

    The #NOGUIDPARAM, if present, instructs the Chart control not to tack on a GUID to the querystring. This setting would make sense for a page that always generates the exact same chart all the time, regardless of the person visiting or any external factors.

    The demo available for download at the end of this article includes a demo named StaticImages.aspx, which generates a static image for the chart using an ImageLocation value of ~/Images/TempChartImages/Chart_#SEQ(25,5).

    Dynamically Generating Images Using The ChartHttpHandler


    In order to display the chart in a user's browser it is imperative that the browser can get the chart image by making a request to some URL on the server. In the previous section we saw how to have the Chart control save the image to the web server's file system. When using this approach the Chart control sends down an <img> element with the src pointing directly to the image file.

    Another option is to have the Chart control save the generated image to session, in memory, or to some location on the hard drive that need not be web accessible (such as C:SomeRandomDirectory). However, with this approach the browser cannot request the chart image directly. Instead, an intermediary process needs to be able to accept the request for the chart image, go and get it from the appropriate location (memory, session, disk, etc.) and then return the chart's contents to the browser.

    The intermediary in this case is the ChartHttpHandler HTTP Handler, which ships as part of the Microsoft Chart Controls. (For background on HTTP Handlers, see HTTP Handlers and HTTP Modules in ASP.NET.) As noted in the Getting Started installment, when you first drag the Chart control onto an ASP.NET page Visual Studio automatically updates your Web.config file to include, among other things, a reference to the ChartHttpHandler HTTP Handler:

    <httpHandlers>
    ...

    <add path="ChartImg.axd" verb="GET,HEAD" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false" />
    </httpHandlers>

    This configuration states that any request that comes in for a file named ChartImg.axd should be handled by the ChartHttpHandler class.

    There's another bit of configuration in Web.config that's needed to specify how and where the Chart control will save the data. As alluded to earlier, the Chart can save the generated chart image to memory, to session, or to a folder in the file system. This location information, along with other pertinent settings, is specified in the <appSettings> section under a key named ChartImageHandler. The demo available for download has the following setting:

    <configuration>
       ...

       <appSettings>
          <add key="ChartImageHandler" value="storage=memory;deleteAfterServicing=true;"/>
       </appSettings>


       ...
    </configuration>

    The above configuration instructs the Chart Web control to save the chart image to memory (storage=memory) and to free that memory as soon as the image is served (deleteAfterServicing=true). Alternatively, I could have set the storage parameter to file or session to store the chart images to disk or into session state, respectively. And there are additional parameters that allow you to specify an optional timeout and the location on disk where the files will be stored (when using the storage=file option). You can even create your own class for storing and the chart image files and plug it into the Microsoft Chart Controls.

    For a complete list of configuration options see the Image File Management documentation.

    After configuring Web.config, the last step is to tell the Chart control to use the HTTP Handler and Web.config instructions rather than to store the image to the file system. This is done by setting the Chart control's ImageStorageMode property to UseHttpHandler (the default value).

    <asp:Chart ... ImageStorageMode="UseHttpHandler">
       ...
    </asp:Chart>

    Setting the ImageStorageMode to UseHttpHandler causes the Chart control to generate an <img> element with an src value like:

    <img src="ChartImg.axd?i=chart_1c564444b4a743489506139f3d9b5ce4_2.png&g=0deaa777d76843ac98e9c2bd05aee6db" ... />

    Note that the URL in the src attribute points to ChartImg.axd. There is no file named ChartImg.axd; instead, when a request comes in for that resource the ASP.NET engine hands off the request to the ChartHttpHandler. The ChartHttpHandler inspects the settings in Web.config and uses the data in the querystring to pull the chart image out of memory (in this case), sends the chart image data back to the client, and then (in this case) removes the chart data from memory.

    Considerations When Using the ASP.NET Web Development Server
    If you are testing an ASP.NET website that uses the Microsoft Chart Controls, are using Visual Studio's built-in ASP.NET Development Web Server, and have the Chart control configured to use the ChartHttpHandler, realize that the settings in Web.config for the HTTP Handler are ignored. Regardless of your settings, the Microsoft Chart Controls stores the chart images in memory. You can circumvent this behavior by adding the following to the ChartImageHandler configuration string: WebDevServerUseConfigSettings=true, as in:

    <configuration>
       ...

       <appSettings>
          <add key="ChartImageHandler" value="storage=file;dir=C:\ChartImages\;WebDevServerUseConfigSettings=true;"/>
       </appSettings>

       ...
    </configuration>

    Serving Images Directly From The Chart Control


    The two rendering modes we just examined are similar in that there is a two step process for serving the chart image to the browser: first the Chart control creates the image, storing it on disk or in session or in memory. Next, the Chart control sends down an <img> element in the page's markup that instructs the browser to make another request for the image. It is possible to configure the Chart Web control to return the actual binary contents of the image file rather than an <img> element. This technique is referred to as binary streaming.

    To use binary streaming you cannot have the Chart control in a web page with other content. Instead, the Chart control must be in a separate web page and be the only Web control in that page. Imagine that we created a new page named SalesChart.aspx that contained a Chart control that uses binary streaming. To view the chart image, a user could request this ASP.NET page directly from their browser (http://www.yourserver.com/SalesChart.aspx), which would return just the contents of the image. To show this chart in a web page with other text and images, you'd need to use an Image Web control or an <img> HTML element that references the SalesChart.aspx page, like so:

    <asp:Image runat="server" ID="imgSalesFigures" ImageUrl="~/SalesChart.aspx" />

    Or:

    <img src="SalesChart.aspx" />

    The download available at the end of this article includes a demo named BinaryStreaming.aspx and a web page named SalesChart.aspx. The SalesChart.aspx ASP.NET page includes a Chart control (and nothing else). The Chart's RenderType property is set to BinaryStreaming, which is what tells the Chart control that it should stream the chart image's output to the output stream rather than saving it to disk, session, or memory. Other than that, the Chart's markup and the code that builds the chart is just like it would be if the Chart control was in another Web page and was not using binary streaming.

    Here's the complete contents of the SalesChart.aspx ASP.NET page (with some of the Chart's declarative markup removed for brevity). Note that the page contains no other Web controls or HTML content. It does not use a master page. Instead, it contains just the @Page directive and the Chart Web control.

    <%@ Page Language="VB" AutoEventWireup="false" CodeFile="SalesChart.aspx.vb" Inherits="Demos_Rendering_SalesChart" %>
    <asp:Chart ID="chtSalesPerDOW" runat="server" Width="500" Height="350"
             RenderType="BinaryStreaming">
       ...
    </asp:Chart>

    To show the sales chart in another web page, use an Image Web control or <img> element. (See the BinaryStreaming.aspx demo, which uses an Image Web control.)

    What Rendering Technique To Use


    By default, the Chart control's properties are configured to use the HTTP Handler approach. Moreover, when adding a Chart control to the project for the first time Visual Studio adds the following ChartImageHandler configuration in <appSettings>:

    <appSettings>
       <add key="ChartImageHandler" value="storage=file;timeout=20;dir=c:\TempImageFiles\;" />
    </appSettings>

    This configuration instructs the HTTP Handler to store images to disk for 20 minutes in the c:\TempImageFiles\ folder.

    Does this default behavior mean that using an HTTP Handler and storing the image files to disk is the best approach? Not necessarily. The reason there exist so many options for serving images from the Chart control is because different approaches and their pros and cons and are best suited for certain scenarios. The following table lists the various options along with pros and cons for each configuration.

    OptionProsCons
    Static Images to Disk
    • Easy to setup and understand.
    • Each Chart control can customize the naming pattern and folder location of the static images it generates.
    • No security. A visitor can see the URL to the image in their browser (such as Chart_000002.png) and try to visit other images, like Chart_000003.png, Chart_000004.png, and so forth. This would allow a visitor to see another user's chart, which could be undesired if the charts are showing potentially sensitive data.
    • Increases disk I/O, which may impact the performance.
    • Requires some extra steps to ensure that Write permissions are enabled on the folder where the chart images are created.
    Images Served Using an HTTP Handler
    • Can "lock down" charts to only allow the user who created the chart to retrieve it; see the privateImages attribute in the ChartImageHandler configuration.
    • Can reduce disk I/O by creating and serving images directly from memory.
    • Provides the ability to create and use a custom chart image store.
    • Configuration is in Web.config, which is external to the Web control's other properties.
    • Policy is applied to entire website. Cannot have some Chart controls store images to session and others store to memory, for example.
    Binary Streaming
    • Avoids the create/wait/stream pattern used by the static files and HTTP Handler approaches, sending the image directly to the browser.
    • Can apply advanced authorization logic in the ASP.NET page's code-behind class.
    • The Chart control is on a separate page than the page being requested by the browser. Consequently, if the chart's data is based on the visitor's input, say the values they choose from some drop-down lists, you'll need to create some mechanism to transfer the user's input from the ASP.NET page they are visiting to the web page that generates the chart. This can be done a number of ways - through the querystring or session, for instance - but this responsibility falls on your shoulders.
    • AJAX and other interactivity features are not supported. (We'll explore AJAX and the interactivity features in a future installment.)

    Conclusion


    The Microsoft Chart Controls offer three techniques for serving chart data: the Chart control can generate the chart image and save it to the web server's file system; the Chart control can save the image to session, memory, or to a folder outside of the web application and have the chart image served via the ChartHttpHandler HTTP Handler; or the Chart can be setup to stream the chart contents directly to the client. This article showed how to use each of these options and discussed the pros and cons of each. Be sure to download the demo, which has examples showcasing all three techniques.

    Happy Programming!

  • By Scott Mitchell


    Attachments:

  • Download the code for this article
  • Further Readings:

  • Image File Management
  • Chart Image Rendering
  • HTTP Handlers and HTTP Modules in ASP.NET
  • A Multipart Series on Microsoft's Chart Controls
    A picture is worth a 1,000 words... This adage rings especially true when it comes to reporting. Charts summarize and illuminate patterns in data in a way that long tables of numbers simply cannot. The Microsoft Chart Controls are a free and encompassing set of charts for WinForms and ASP.NET applications. This article series explores how to use these Chart Controls in an ASP.NET application.

  • Getting Started - walks through getting started using the Chart Controls, from version requirements to downloading and installing the Chart Controls, to displaying a simple chart in an ASP.NET page.
  • Plotting Chart Data - examines the multitude of ways by which data can be plotted on a chart, from databinding to manually adding the points one at a time.
  • Rendering the Chart - the Chart Controls offer a variety of ways to render the chart data into an image. This article explores these options.
  • Sorting and Filtering Chart Data - this article shows how to programmatically sort and filter the chart's data prior to display.
  • Programmatically Generating Chart Images - learn how to programmatically create and alter the chart image file.
  • Creating Drill Down Reports - see how to build drill down reports using the Chart control.
  • Adding Statistical Formulas - learn how to add statistical formulas, such as mean, median, variance, and forecasts, to your charts.
  • Enhancing Charts With Ajax - improve the user experience for dynamic and interactive charts using Ajax.
  • Serializing Chart Data - see how to persist a chart's data and appearance to a persistent store.
  • Using the Chart Controls with ASP.NET MVC - learn how to display charts in an ASP.NET MVC application.
  • Exporting Charts - allow visitors to export charts as images and PDF files.
  • (Subscribe to this Article Series! )



    ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article