Case Study

Languages: VB

Technologies: Reporting

Crystal Decisions began working with Microsoft on their .NET technology long before the .NET term was even coined. Several years later, as Crystal Reports for Visual Studio .NET nears release with Visual Studio .NET, the Crystal Decisions team looks back on its experiences developing an enterprise-reporting SDK making extensive use of the .NET Framework.

One of the challenges the Crystal team had to address from the beginning was that we weren t starting from scratch; we had an established industry-leading product and needed to bring a subset of it to the .NET platform. However, we were pleasantly surprised by the ease with which we were able to accomplish this task. The rest of this article will describe some of the components we are exposing to the .NET world and the .NET features we are leveraging in doing so.

Report Engine

The core of the Crystal Reports product is in its report-processing engine, implemented mostly as C++ DLLs. This engine is comprised of over one million lines of code, so the task of rewriting it in a managed language seemed daunting. The decision was made early on not to rewrite the engine, but rather to leverage our existing investment and create a wrapper to expose the engine s API to the .NET world. We chose to use Managed Extensions to C++ (MC++) to create this wrapper.

MC++, which allows the mixture of unmanaged and managed code within the same DLL, enables direct access to the existing engine as well as the ability to expose a managed object model that would be usable from any managed language like VB .NET or C# in both Windows Forms and Web Forms (ASP.NET) contexts.

FIGURE 1 shows a code example of the report engine object model being used to print a report using VB .NET. The developer can also use the engine to export the report to another file format such as PDF, DOC, RTF, or XLS.

Imports CrystalDecisions.CrystalReports.Engine

Dim Report As New ReportDocument()

Dim numCopies As Integer = 1

Dim collate As Boolean = False

Dim startPage As Integer = 1

Dim endPage As Integer = 5

 

Report.Load("C:\Reports\Inventory.rpt")

Report.PrintToPrinter(numCopies, collate, _

 startPage, endPage)

FIGURE 1: Printing a report directly to a printer.

 

Web Delivery

While printing and exporting are key features, we expect the majority of developers will want to deliver reports over the Web in HTML format. Crystal Reports already has the ability to produce HTML 3.2 and HTML 4 output, so the Web control architecture of ASP.NET was a perfect fit. A Web control is a server-side control that renders itself into HTML while providing features such as client-side state management, control events, and caching. Web controls also work great within the Visual Studio .NET development environment because they provide a design-time representation of what they look like so the author can lay out the page accordingly.

The Crystal team created a control named CrystalReportViewer (found in the CrystalDecisions.Web namespace). The control inherits from the WebControl class (found in the System.Web.UI.WebControls namespace). The following code demonstrates using the Crystal Reports Web control in an ASP.NET page:

 

<%@ Register TagPrefix="CR" Namespace="CrystalDecisions.Web"

 Assembly="CrystalDecisions.Web" %>

 

<CR:CrystalReportViewer id="CRViewer1" runat="server"

 width="500px" height="500px"

 ReportSource="C:\Reports\Inventory.rpt"/>

 

The ReportSource property is used to specify which report the Web control should request from the engine. In this example, it is set to a file path to a Crystal Report (RPT) file.

State Management

Anybody who s ever created a medium- to large-scale Web application in ASP has learned that while per-user session variables are easy to use, they are generally to be avoided. Session variables consume server memory, which reduces the ability to scale the application. Alternatives such as storing state in the query string, however, are often tedious to implement.

ASP.NET solves this problem by introducing view state. Storing things in ASP.NET view state is as easy as storing things in session variables; however, it does not store the data in server memory. Instead, ASP.NET serializes the view state into a string which gets sent down as a hidden form field to the client. When the client performs an action on the page, the view state is posted back to the server for the Web control to use.

The view state is available for ASP.NET application developers as well as ASP.NET control developers. The Crystal Reports Web control uses view state to store information such as the current page number of a report or any report parameters. This eliminates the dependency on server memory for per-user state and decreases the time and maintenance of implementing a complex state management mechanism.

Web Control Events

One of the things that make client controls like ActiveX controls rich is that they provide events to which the application developers can respond. Web controls give you the best of both worlds because they follow a thin-client model but are able to expose events to ASP.NET developers.

One of the powerful features of Crystal Decisions product is the ability to quickly and easily have interactive report viewing over the Web. That is, users can easily drill deeper into consolidated data to find specific information. Even more valuable, however, is the fact that the Crystal Reports Web control can be set to expose events such as Navigate and Drill that fire when users click and drill-down on the report. Developers can handle these events and change the appearance of other controls to reflect the navigation. FIGURE 2 shows an ASP.NET page using VB .NET that handles the Drill event and interacts with other controls.

 

<%@ Register TagPrefix="CR" Namespace="CrystalDecisions.Web"

 Assembly="CrystalDecisions.Web" %>

<%@ Page Language="VB" %>

<%@ Import Namespace="CrystalDecisions.Web" %>

 

<html>

<head>

    <script runat="server">

      Protected Sub CRViewer1_OnDrill(Source As Object,

       e As DrillEventArgs)

         Label1.Text = "You drilled down on " & _

          e.NewGroupName

      End Sub

    </script>

</head>

<body>  

    <form runat="server">

        <CR:CrystalReportViewer id="CRViewer1"

         runat="server" width="500px" height="500px"

         ReportSource="C:\Sales.rpt"

         OnDrill="CRViewer1_OnDrill"/>

        <asp:Label id=Label1 runat=server/>

    </form>

</body>

</html>

FIGURE 2: Handling events of the Crystal Reports WebForms control.

 

Caching

The Web control uses ASP.NET view state effectively to scale; however, there is still a performance hit when the report-processing engine needs to process a report. We have found ASP.NET s caching API extremely useful in this scenario.

The Cache class (found in the System.Web.Caching namespace) is a collection of objects that the ASP.NET developer can use to store and retrieve application data. The collection private to a given application is straightforward to use. The developer simply stores an object based on a string-based key, as shown here:

 

Cache(key) = object

 

The Crystal team uses this caching API to store report jobs that could be used across sessions. This allows a report to be processed once and the output reused across many requests to increase robustness and scalability. We also provide an interface named ICachedReport that allows developers to customize the way a report job is cached.

 

XML Web Services

Early on, we saw that XML Web Services were going to be big. Web Services provide an easy way for businesses to share information programmatically using open Internet standards like XML and HTTP. However, while the passing of data to business partners is a good thing, the business on the other end needs to present that data in a way that s useful. They need to turn data into information. This is the business Crystal Decisions has been in for a long time, so we came up with a way to leverage ASP.NET s Web Services API to expose Crystal Reports as XML Web Services. Pages are serialized into XML and sent over the wire using SOAP to either our rich-client viewer or thin-client viewer. Surprisingly enough, this really wasn t that much work. Microsoft did a great job in doing all the groundwork in exposing and consuming XML Web Services.

 


Web integration with Crystal Reports for Visual Studio .NET.

 

The Crystal Reports team at Crystal Decisions is excited about the product we ve built for .NET. The core .NET Framework allowed us to leverage our existing code base, rapidly add new and powerful features, and deliver a high-quality product to the .NET world. We think budding ASP.NET developers will do the same.

For more information on Crystal Reports for Visual Studio .NET, visit http://www.crystaldecisions.com/aspnet.

Ryan Marples is a program manager at Crystal Decisions. His responsibility includes delivering developer tools as part of the Crystal Reports product. For the past two years Ryan has been living and breathing .NET while working closely with Microsoft to deliver a new release of Crystal Reports built atop the .NET Framework that will ship with Visual Studio .NET. You can contact Ryan at ryan.marples@crystaldecisions.com

Tell us what you think! Please send any comments about this article to editors@devproconnections.com. Please include the article title and author.