Crystal Reports Online Training

Learn Online, Anytime, Anywhere

Step-by-step online tutorials.

14.06 Basic ASP.NET Code Templates

Printing from ASP.NET Websites

Printing reports within an ASP.NET application requires a slightly different coding template than the previous listings. Reports shown on an ASP.NET page are unique in that each time the user moves to a new report page, the web page gets reloaded. If a report is resource intensive, this can slow performance or tie up resources. For example, a report that connects to SQL Server will open a new connection each time the page is loaded. In addition to wasting resources, reports will often ‘forget’ which page they were previously showing. I frequently see people posting questions on the book’s forum asking why a page will jump from page 3 back to page 1.

Fixing this problem requires making two specific coding changes. The first requires loading the report in the web page’s Page_Init() event. Normally, you would put your code in the Page_Load() event, but the Page_Load() event has timing issues of how the report viewer binds to the report and how it responds to mouse click events. Putting the report initialization code in the Page_Init() event solves this timing problem and the viewer will respond to mouse clicks correctly.

The second change you need to make is saving the report object to the Session collection. This lets you persist the report across page views. When the page loads it can pull the existing report from the Session and pass it to the report viewer. This saves resources because the report won’t re-query the database or re-process the report each time the web page is loaded.

Saving the report to the Session collection adds a little complexity to your code because you have to determine if the report was already saved in the Session by the previous page. If so, load the existing report into a ReportDocument object variable. If the report isn’t in the Session, you have to instantiate a new report object and save it to the Session collection.

In the following code sample, there are two procedures. The first, the Page_Init() event, determines if the report is already in the Session. If not, it calls the second procedure, ConfigureReport(), which loads the report into memory and saves it to the Session collection.

Listing 14-6. Template for ASP.NET pages.
[VB.NET]
Partial Class _yourWebPage
Inherits System.Web.UI.Page
'The myReport object varialble is local to the web page
Dim myReport As CrystalDecisions.CrystalReports.Engine.ReportDocument
Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
If Session("myReport") Is Nothing Then
'The report hasn't been created yet. Do so now.
ConfigureReport()
Else
'The report has already been created, load it from the Session collection
myReport = CType(Session("myReport"), CrystalDecisions.CrystalReports.Engine.ReportDocument)
End If
CrystalReportViewer1.ReportSource = myReport
End Sub
Private Sub ConfigureReport()
myReport.Load(Server.MapPath("CrystalReport1.rpt"))
‘custom report modifications would go here
Session("myReport") = myReport
End Sub
[C#]
public partial class HealthInfo : System.Web.UI.Page
{
//The myReport object varialble is local to the web page
CrystalDecisions.CrystalReports.Engine.ReportDocument myReport = new CrystalDecisions.CrystalReports.Engine.ReportDocument;
protected void Page_Init(object sender, System.EventArgs e)
{
if (Session["myReport"]==null)
{
//The report hasn't been created yet. Do so now.
ConfigureReport();
} else {
//The report has already been created. Load it from the Session collection
myReport=(CrystalDecisions.CrystalReports.Engine.ReportDocument)Session["myReport"];
}
CrystalReportViewer1.ReportSource = myReport;
}
}
private void ConfigureReport()
{
myReport.Load(Server.MapPath("CrystalReport1.rpt"));
//custom report modifications would go here…
Session["myReport"]=myReport;
}
}

The myReport object variable is declared immediately after the class declaration for the web page (your Partial Class declaration will be named differently than the one I show in the code listing). This makes the myReport variable local to the web page and all the methods have access to it.

The Page_Init() event checks for two scenarios. The first scenario is that this is the first time the web page is loaded and the report hasn’t been created yet. It calls the ConfigureReport() method and saves the report to the Session collection. If the report is already in the Session, it pulls it from the collection into the myReport object variable. Notice that it has to cast the Session object as a ReportDocument class. This is because the Session collection doesn’t track a variable’s data type and it stores everything as a generic object variable.

The ConfigureReport() method declares and instantiates a new ReportDocument object and loads it into memory using the Load() method. It also uses theServer.MapPath() method to map the virtual file to a physical path on the server. After loading the report, it saves it to the Session collection using the name “myReport”. This name can be used to retrieve the report on the next page load. By creating a separate method to load the report into memory, you can call it from other places within the webpage if necessary (e.g. responding to a button click event).

The template modifies the report’s properties after the ReportDocument is loaded into memory.If you later call the viewer’s Refresh() method, the viewer loads the report back into memory again and loses all changes you made to the report. You will have to set the properties again.