Case Study
Languages: VB
Technologies: Reporting
Keeping
Pace
Developing
Crystal Reports for Visual Studio .NET
By Ryan
Marples
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 mailto:ryan.marples@crystaldecisions.com
Tell us what you think! Please send any comments about this
article to mailto:editors@devproconnections.com.
Please include the article title and author.