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
Jobs

ASP ASP.NET ASP FAQs Message Board Feedback ASP Jobs
 
Print this Page!
Published: Wednesday, February 10, 2010

Using Microsoft's Chart Controls In An ASP.NET Application: Serializing Chart Data

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


    In most usage scenarios, the data displayed in a Microsoft Chart control comes from some dynamic source, such as from a database query. The appearance of the chart can be modified dynamically, as well; past installments in this article series showed how to programmatically customize the axes, labels, and other appearance-related settings. However, it is possible to statically define the chart's data and appearance strictly through the control's declarative markup. One of the demos examined in the Getting Started article rendered a column chart with seven columns whose labels and values were defined statically in the <asp:Series> tag's <Points> collection.

    Given this functionality, it should come as no surprise that the Microsoft Chart Controls also support serialization. Serialization is the process of persisting the state of a control or an object to some other medium, such as to disk. Deserialization is the inverse process, and involves taking the persisted data and recreating the control or object. With just a few lines of code you can persist the appearance settings, the data, or both to a file on disk or to any stream. Likewise, it takes just a few lines of codes to reconstitute a chart from the persisted information.

    This article shows how to use the Microsoft Chart Control's serialization functionality by examining a demo application that allows users to create custom charts, specifying the data to plot and some appearance-related settings. The user can then save a "snapshot" of this chart, which persists its appearance and data to a record in a database. From another page, users can view these saved chart snapshots. Read on to learn more!

    - continued -

    An Overview of the Demo Application


    Before we dig into how to serialize and deserialize chart data, let's take a moment to explore the demo application available for download at the end of this article. The demo includes a chart that plots the sales per month for a particular category of products from the Northwind database. The user viewing the chart must select the category and year for which to display the sales data, and can optionally choose a color palette. The screen shot below shows this page in action. Here the user has selected to view the sales for the products in the Condiments category for 1996, displayed in a SeaGreen palette.

    The user has selected to view the sales for the products in the Condiments category for 1996, displayed in a SeaGreen palette.

    Note that there's also a "Save Chart As Snapshot" button. If the user clicks this they are shown an interface where they can enter a name for the snapshot.

    The user can save the chart to a database table.

    Entering a name and clicking the "Save Chart Snapshot" button serializes the chart's appearance settings and its data, storing the resulting serialized information to a database table (ChartSnapshots).

    On another page users can select from the saved snapshots and view a chart. A drop-down list shows each saved snapshot. Selecting displays the snapshot title, the date the snapshot was taken, and the chart data. The screen shot below shows this page when the user has opted to load the "Condiments, 1996, SeaGreen" snapshot, which is the one we created and saved in the above screen shot.

    The user is viewing the 'Condiments, 1996, SeaGreen' snapshot, which was created in the previous screen shot.

    Keep in mind that the serialized chart information in this demo includes both the appearance-related settings (the palette selection, the chart's height and width, and so forth) and chart data, meaning that if a user views the snapshot at a later point in time they will be seeing the data from when the snapshot was generated. In other words, if the user creates a snapshot on February 1st, 2010 that shows the year to date sales for 2010 and then views that snapshot again on February 15th, it's vital to realize that the data will show the year to date sales as of February 1st, when the snapshot was taken, and not as of the date when the snapshot is viewed. If the charts are being populated with historical data then this is of no concern, but such a snapshot feature would not be useful when viewing charts whose data is still being updated.

    Serializing Chart Information


    Serializing a chart's data and/or appearance settings is easy and can be accomplished in just a few lines of code. The actual serialization logic is handled by the ChartSerializer class, which is accessible from the Chart control via the Serializer property. To serialize a chart, do the following:
    1. Indicate whether you want to serialize the chart data, the appearance properties, or both by setting the Serializer's Content property to one of the following values:

      SettingDescription
      AppearanceSerializes all non-default appearance-related properties, such as line color, chart height, etc.
      DataSerializes all data values in the chart; does not serialize appearance-related properties.
      DefaultSerializes all non-default chart content, including the chart data and the appearance-related properties.
      AllSerializes all chart content, including the chart data and the appearance-related properties.

    2. Call the Serializer property's Save method, passing in either: a file name (if you want to serialize to disk); a stream; or an XmlWriter or TextWriter object.
    That's all there is to it! When the "Save Chart Snapshot" button is clicked, the following code serializes the chart data and non-default appearance-related settings to a string, serializedChartContent:

    'Need to rebind the data to the chart so that the Series Points collection is populated (otherwise the data won't be serialized)
    chtCategorySales.DataBind()

    Dim serializedChartContent As String = String.Empty

    'Serialize the chart
    Using writer As New StringWriter
       'Serialize all content to a StringWriter
       chtCategorySales.Serializer.Content = SerializationContents.Default
       chtCategorySales.Serializer.Save(writer)


       'Dump the contents to a string
       serializedChartContent = writer.ToString()

       'Close the StringWriter
       writer.Close()
    End Using

    The above code starts by rebinding the data to the Chart control. By default, the chart data is not persisted in view state and must be rebound on each page load. If you bind the chart to a data source control, as this example does, then this happens automatically during the page lifecycle, but that automatic binding occurs later in the page lifecycle than the Button's Click event handler, which is where the above code lives. Consequently, if we do not explicitly rebind the data to the chart then the serialized output will not contain any of the chart's data points (since they haven't been added to the chart yet).

    Next, a StringWriter object is created (writer). This object will be used to hold the serialized content. The Serializer's Content property is then set to Default, indicating that we want to serialize all data points and non-default appearance-related settings. The actual serialization occurs on the next line, when we call the Serializer object's Save method, passing in the StringWriter. Finally, the contents written to the StringWriter are dumped out to a string, serializedChartContent, and the StringWriter is closed.

    After the above code runs, the contents of serializedChartContent along with the snapshot title entered by the user are added to a new record in the ChartSamples table.

    If you look at the serialized data in the database table you'll see that the Chart control serializes its appearance-related settings and data points using XML that's nearly identical to the Chart control's declarative syntax. Here's a snippet. You can see the full XML by examining the contents in the ChartSamples table. (They are also displayed in a TextBox at the bottom of the ViewChartSnapshots.aspx page.)

    <?xml version="1.0" encoding="utf-16"?>
    <Chart Width="550" Height="350">
       <Series>
          <Series Name="SalesByMonth" XValueMember="Month" YValueMembers="Total" ...>
             <Points>
                <DataPoint XValue="7" YValues="2177.8" />
                <DataPoint XValue="8" YValues="2333.8" />
                <DataPoint XValue="9" YValues="1864" />
                ...
             </Points>
          </Series>
       </Series>
       <ChartAreas>
          <ChartArea Name="MainChartArea">
             <AxisY>
                <LabelStyle Format="C0" />
                <StripLines>
                   <StripLine TextAlignment="Near" IntervalOffset="3243.0499999999997" ... />
                </StripLines>
             </AxisY>
             <AxisX>
                <MajorGrid Enabled="False" />
                <CustomLabels>
                   <CustomLabel FromPosition="0.5" ToPosition="1.5" Text="Jan" />
                   <CustomLabel FromPosition="1.5" ToPosition="2.5" Text="Feb" />
                   <CustomLabel FromPosition="2.5" ToPosition="3.5" Text="Mar" />
                   ...
                </CustomLabels>
             </AxisX>
          </ChartArea>
       </ChartAreas>
    </Chart>

    Deserializing The Persisted Chart Information


    Now that we have the a chart snapshot saved in the database all that remains is to allow the user to view one of these snapshots. The Microsoft Chart Controls make deserialization just as easy as serialization:
    1. Add a Chart control to the page
    2. Indicate what data to deserialize by setting the Chart control's Serializer object's Content property accordingly.
    3. Call the Serializer object's Load method, passing in the serialized information either as: a file name (if the chart was serialized to disk); as a stream; or as an XmlReader or TextReader object.
    The ViewChartSnapshots.aspx page in the demo performs this deserialization logic. The page contains a Chart control named chtViewer. Note that it does not have any properties set - these properties (and its data) will be set for us during the deserialization process.

    <asp:Chart ID="chtViewer" runat="server" />

    The page also includes a DropDownList control that's populated with the records in the ChartSnapshots table. Selecting an option from the list causes a postback. On postback the code connects to the database, gets back the snapshot's title, date created, and serialized information, and then runs the following code:

    'Display the snapshot in the Chart control
    lblSnapshotTitle.Text = String.Format("{0} (Snapshot taken {1:d})", SnapshotTitle, SnapshotDate)
    txtSnapshotData.Text = SnapshotData

    Using reader As New StringReader(SnapshotData)
       chtViewer.Serializer.Content = SerializationContents.Default
       chtViewer.Serializer.Load(reader)


       reader.Close()
    End Using

    Here, the variables SnapshotTitle, SnapshotDate, and SnapshotData hold the values returned from the database. A StringReader object is created to read the contents of the chart's persisted information (SnapshotData). The Chart control's Serializer object has its Content configured to deserialize the data and non-default appearance-related properties, while the Load method does the actual deserialization logic, reconstituting the chart based on the contents of SnapshotData.

    And that's all there is to it. With the above code, a user

    Conclusion


    The Microsoft Chart Controls make it amazingly simple to serialize and deserialize chart data. This state can be persisted to disk, to any stream, or to a string. The demo available for download at the end of this article shows how to persist this information to a database, but it could have been saved to disk or cached in memory. Keep in mind that if you serialize chart data to a persistent store then when re-hydrating that data users will be seeing chart data as of the date it was serialized. This is a non-issue when charting historical data, but should not be used when charting data that is still being updated.

    The Chart control's serialization capabilities can be used for shorter-term serialization. For example, if you have a Chart control that gets its data from a slow data source, you could cache the chart data in view state or for a short duration in the .NET data cache. The Samples Environment for Microsoft Chart Controls includes a demo that stores the serialized content in view state so that the chart can be reconstructed on postbacks without having to re-query its underlying data store.

    Happy Programming!

  • By Scott Mitchell


    Attachments:

  • Download the code for this article


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