Explore the Reports Starter Kit

In Part II of the Starter Kits series, extract the best parts of code and design from the free Microsoft ASP.NET Reports Starter Kit.

Brian Noyes

October 30, 2009

13 Min Read
ITPro Today logo

asp:feature

LANGUAGES: C# | VB .NET

ASP.NET VERSIONS: 1.0 | 1.1

 

Explore the Reports Starter Kit

In Part II of the Starter Kits series, extract the bestparts of code and design from the free Microsoft ASP.NET Reports Starter Kit.

 

By Brian Noyes

 

In Minethe Starter Kits I introduced you to the ASP.NET Starter Kits and showedyou how to use and extend the Community Starter Kit (CSK). This month I'llfocus on the Reports Starter Kit (RSK) and show you how to extract the bestnuggets of code and design from it. The RSK demonstrates many concepts forproducing Web-based reporting solutions and displaying data in a variety offormats, including tables, hierarchical grids, drill-down reports, andgraphical representations of your critical business data.

 

The bad news is-unlike the CSK- theRSK isn't an extensible framework of capabilities you can install and simplystart populating with your own data and content. Instead, the RSK represents acollection of sample page types or mini-applications for displaying varioustypes of reports, along with a design for getting the data to the pages fromyour data tier. The pages and middle-tier objects have a lot of application codemixed in specific to the sample, so you'll have to use them more like bigsample snippets rather than something you can plug your data into and go. Thegood news is there are some great lessons in the RSK that'll show you effectivetechniques to collect and display data in various reporting formats in your ownASP.NET applications.

 

In this article, I'll focus on four aspects of the RSKthat I think are its best lessons. These include how to create and display Webgraphics on the fly, the use of custom collections for passing data throughyour middle tier, the use of the Data Access Application Blocks to simplifyyour data-access code, and the use of nested data-bound list controls onASP.NET pages. The download code for this article, available in both C# and VB.NET, contains an implementation of a new visual report format to add to whatthe RSK provides. This new format follows the basic design of the other visualreports in the RSK and all the lessons I just mentioned (except the nesting oflist controls).

 

Data a Manager Can Understand

The first step in reporting data is to decide in what formyou want it displayed. Naturally, the most engaging report is the kind thateven pointy-haired managers can understand: graphical or visual. This means youmust take your business data and present it using one of many recognized formsof graphically summarized data. The RSK contains implementations for two formsof visual reports: simple pie charts and bar charts.

 

When implementing visual reports in the RSK, you havelimited options compared to a professional graphics component such as thoseavailable from Infragistics, ComponentOne, or ChartFX. In fact, if you plan toreport from pages in your Web application visually in a variety of commonformats, I highly recommend you consider one of those vendor's products ratherthan trying to write it all yourself. But if you have custom visual reports youwant to create that those products don't support, or you simply want to code ityourself for small projects, the RSK and the code for this article will giveyou a jumpstart.

 

This article's sample code includes a set of classes and apage that allow you to create line charts with multiple series of data (seeFigure 1). I won't go into great detail on how to write the graphic-renderingcode for this sample; for good coverage of that material see GetGraphic by Ken Getz and BuildDynamic Web Charts by Dino Esposito - but I will mention the processbriefly.

 


Figure 1. The sample code for this article implements a third type ofvisual report: a line graph of multiple series. The report uses a collection ofannual sales collections to display line graphs of those sales.

 

In the case of the RSK, the visual reports display asingle series of sales by category. For the line graph visual reportimplemented in this article, I displayed multiple series of annual sales byregion. I drew on the same set of data being used for the Cross Tab Report inthe RSK.

 

To render your data graphically, use the Bitmap class fromthe .NET Framework Class Library. You get a Graphics object for it using theGraphics.FromImage method, then you can use Graphics object methods to renderyour graphic (see Figure 2).

 

// Create the bitmap we will draw to

Bitmap chartSurface = new Bitmap(Width,Height);

// Get the graphics object for the bitmap

Graphics g = Graphics.FromImage(chartSurface);

// Fill the background with the BG color

g.Clear(_backgroundColor);

// Do any drawing on the Graphics object

// to render the graphic

// g.DrawLine(), g.FillEllipse(), etc.

// Clean up and release the graphics object

g.Dispose();

// return the result

return chartSurface;

Figure 2. You can obtain a Graphics objectrepresenting the Bitmap surface, on which you then can render your data usingdrawing commands. Once you are done rendering, you have a Bitmap object readyto go that you can save or return as a stream.

 

Once the Bitmap is rendered, you need to return it to thebrowser as something that can be placed on a page. One approach would be tosave off the Bitmap as a temporary file and return an tag in thepage that refers to that temp file. Because that's not a scalable solution,however, you must design some maintenance facilities for cleaning up the tempfiles later. A better approach is the way the RSK does it: Return the Bitmap asa binary stream from another page. That way, the tag simply canrefer to that other page as the source of the Bitmap and it'll be requested andreturned by the server as a binary stream. Or, you could return the image as astream from an HTTP handler class instead of an actual page, but the result isthe same.

 

The charting approach used in the RSK passes the chartdata as Response.QueryString parameters to a class named ChartGenerator. Thisisn't a very scalable approach due to the length and encoding limitations of aquery string. A better approach for real-world applications is either to postthe data to the target page or handler, or design more intelligence into thechart generator so it could retrieve the data from the business tier itself.

 

Three of the other report types the RSK demonstratesprovide ways for displaying hierarchical data: the Master-Details,Hierarchical, and Drill-Down reports. The Master-Details Report includes parentand child grids; the child grid displays the details of items selected in theparent grid. The Hierarchical and Drill-Down reports show two ways of providingan interactive navigation of the data from the top-level elements down intotheir dependent or child data items.

 

Gather the Seeds That You Sow

Once you know how you want to display data, the next thingyou need to tackle is the plan to get the data from where it rests in thedatabase to where it goes into action in your display pages. Although the RSKdoesn't include much in the way of business logic, it does include an excellentpractice for your business tier if you want to decouple the tiers of yourarchitecture: Use custom collection classes to transport your data to thepresentation tier.

 

The data-binding features of the DataGrid, DataList, andRepeater controls make wiring up data for Web page display a snap, evenproviding rich layout and interactivity. Unfortunately, simply passing yourdata straight through from your queries or stored procedures and binding it tothe controls in the form of a DataSet or DataReader becomes quite tempting.Although using this approach results in less code and improves performance, ithas one problem: It couples your presentation tier directly to the data tier- one of the key pitfalls n-tieredarchitectures aim to prevent. When you use this approach, you start writingdata-binding code in your pages that relies directly on the schema of the dataas it is returned from the database. Then, as soon as you need to change yourstored procedures or schema, your presentation tier breaks.

 

To prevent this, you  must realize that databinding supports many forms of collectionsincluding custom, type-safe collections of business objects you can create inyour business tier to isolate the presentation code from the underlying datatier. The RSK demonstrates one step along this road by creating collectionclasses derived from ArrayList for the data exposed to the reporting pages. Theproblem with this approach of inheriting directly from ArrayList is that theresulting collection is not type-safe. The code that populates the collectionclass easily could insert objects of any type into the collection, and thedisplay code probably is going to choke in a big way if it receives acollection of heterogeneous data that contains objects it doesn't understand.

 

If you're going to use collection classes to separate yourpresentation and data tiers, I recommend taking it one step further; I'vedemonstrated how in the sample code for this article. Instead of deriving fromArrayList, derive from CollectionBase, which contains an ArrayList member thatallows you the same flexibility and ease in populating the collection, and itimplements the ICollection, IList, and IEnumerable interfaces expected bycollection iterators and data-bound list controls. When using this base class,you need to provide your own implementations of the methods to access the itemsin the collection (see Figure 3). This ensures that only items of the propertype can be put into the collection and that you can return items retrievedfrom the collection as typed, instead of untyped, object references. In fact,this article's  sample code defines twocollection classes; one is a collection of collections to handle the multipledata series of annual sales displayed in the line graph (see Figure 1). Thedesign of these collections is shown in Figure 4.

 

using System;

using System.Collections;

 

public class RegionAnnualSalesItemCollection

       : CollectionBase

{

  public intAdd(RegionAnnualSalesItem item)

  {

    returnthis.List.Add(item);

  }

 

  public voidRemove(RegionAnnualSalesItem item)

  {

    this.List.Remove(item);

  }

 

  public void Insert(intindex, RegionAnnualSalesItem item)

  {

    this.List.Insert(index, item);

  }

 

  public intIndexOf(RegionAnnualSalesItem item)

  {

    returnthis.List.IndexOf(item);

  }

 

  public RegionAnnualSalesItemthis[int index]

  {

    get {

      returnthis.List[index] as RegionAnnualSalesItem;

    }

    set {

      this.List[index] =value as RegionAnnualSalesItem;

    }

  }

}

Figure 3. By deriving from CollectionBase, you getfree implementations of the ICollection, IList, and IEnumerable interfaces. Youthen provide your own implementations of the methods to access the items in thecollection in a type-safe manner, and you can ensure that your collectionremains a homogeneous collection of a specific object type.

 


Figure 4. The sample code for this article implements two collections;one contains the annual sales item data for a single region and the othercontains the series of regional annual sales. They both derive fromCollectionBase and implement type-safe collection classes decoupled from thedatabase that provides the data.

 

Once you've defined the business layer collections you'llexpose to your presentation tier, it's a simple matter in your business classesto gather the data from the database and populate the collections. Then, if inthe future your data-tier implementation changes, only these translationclasses in your business tier must also change; the presentation-layerconsumers of the business collections do not. Any design decision like thisrequires you to consider trade-offs. You pay a slight performance penalty fordoing this translation in the business tier and you must write a little morecode (and maintain it). But in terms of providing a decoupled, maintainable,and scalable object-oriented architecture, it's usually worth the trade-offdepending on your priorities.

 

In terms of collecting the data, the other nice techniquethe RSK demonstrates is the use of the Data Access Application Blocks (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/daab-rm.asp)to simplify calls made to the database. If you've done much ADO.NET programmingusing stored procedures, you've probably written many methods that feelrepetitive. You create a connection and a command object, then create each ofthe parameters and add them to the Command object's Parameters collection.Finally, you execute the command and harvest the results. The Data AccessApplication Blocks provide a SqlHelper class that encapsulates all thatrepetitive code for you; it allows you to do in a few lines of code whatmight've taken tens in raw ADO.NET.

 

For example, if you had a GetOrders stored procedure thattook two parameters and returned a result set, you could make the call and getthe results in a single line of code like this:

 

DataSet ds =SqlHelper.ExecuteDataset(

connString, "GetOrders", 24, 36);

 

The ExecuteDataset method takes a variable number ofarguments as object references following the name of the stored procedure tocall, and before making the call it iterates through those arguments, wrapsthem up as SqlParameter objects, and attaches them to the underlying SqlCommandobject. Similar methods exist for scalar and non-query types of storedprocedure results.

 

Cater to Your Nesting Instincts

One other great technique the RSK demonstrates is nestingthe data-bound list controls within one another to achieve a logical display ofhierarchical data. The Tabular Report, Cross-Tab Report, Hierarchical Report,and Drill-Down Report pages in the RSK each demonstrate different ways ofnesting DataList and DataGrid controls within other DataList controls toachieve various layouts and interactivity with the hierarchical data display(see Figure 5). Although not demonstrated in the kit, you can achieve the samekinds of nesting with Repeater controls as well, but you must handle more ofthe details of the resulting layout.

 


Figure 5. Using templates, nesting DataGrids within DataLists to achievea hierarchical display of data is straightforward.

 

This might sound complex, but the approach actually isquite easy- it simplyrequires a little understanding of the use of templates with the data-boundlist controls. The basic approach is to create child controls within an itemtemplate for a DataList, or a bound column template for a DataGrid, that bindto some data item in its parent control. So, if you have order details tied toa particular order item, the parent list control can display order items, andthe child list control can bind using the parent's item identifier to performthe query needed to populate its data (see Figure 6).

 

 

  

   

    

   

   

    

   

  

      Order

      <%#DataBinder.Eval(Container.DataItem,

       "OrderDate") %>

     DataSource='<%#GetOrderDetails((int)

     DataBinder.Eval(Container.DataItem, "OrderID")) %>'>

 

Figure 6. In this code, a DataGrid is nested in aparent DataList. The DataGrid binds to data populated using the parent listitem's order ID with a helper method defined in the page's codebehind.

 

If, in the code for the page, you write helper methodsthat use business objects to retrieve the child data based on the parent item'sdata, binding the child list controls to its parent item's data becomes asimple matter.

 

The RSK has many samples of how to create and displaytabular and graphical data reports. You'll need to dig through the code andextract the coding patterns and techniques because the sample-specific code isinterspersed with the generic design of the code. Using the design and codingtechniques in the RSK should get you on the road to rich Web-based reportingapplications much quicker than you could simply by blazing the trail on yourown. Next, month I'll close this series with the Time Tracker, Portal, andCommerce Starter Kits. These kits demonstrate how to create line-of-businessapplications with rich interfaces that target both mobile and desktop users,and they include good techniques and design patterns worth emulating.

 

The sample code in thisarticle is available for download.

 

Brian Noyes is anassociate of IDesign Inc. (http://www.idesign.net)and a trainer, consultant, and writer. He's an MCSD with more than 12 years ofprogramming, design, and engineering experience. Brian specializes in .NETarchitecture, design, and coding of data-driven Web and Windows applications,data access and XML technologies, and Office automation. He also is acontributing editor for asp.netPRO and other publications. E-mail him at mailto:[email protected].

 

Tell us what you think! Please send any comments aboutthis article to [email protected] include the article title and author.

 

 

 

Sign up for the ITPro Today newsletter
Stay on top of the IT universe with commentary, news analysis, how-to's, and tips delivered to your inbox daily.

You May Also Like