Ok, what's interesting today? Reporting. Web reporting...
Note: Those who are not entirely familiar with XtraReports and its Web based reporting engine can read about the basic concepts behind it here: Getting Started - Creating a Web Report. In general, there are two basic controls which can be used for web reporting: the ReportViewer and ReportToolbar. They are dropped onto a Web page, linked together, and can be used to represent and maintain an XtraReport assigned to the ReportViewer.Report property.
I think that everyone who has ever tried to create a web report should be aware of some hidden pitfalls. For instance, performance problems. Web reporting imposes different constraints and solutions to this problem can sometimes be rather difficult. Some time ago I found a nice KB article which Plato recently submitted to our Knowledge Base. I think that this article will be very useful for those who want to greatly improve the performance of their web reports!
Look at How to cache a report object in a web application.
What is the problem then? In particular, the problem is that the ReportViewer disposes of its report on every postback. So, to be able to show the report again, the server has to recreate it. In general, the problem is that for now the XtraReport's document (which is a sequence of bricks for all generated data) can't be saved to a file. We already have this request in our "To Do" list (www.devexpress.com/issue=AS3465), but unfortunately this list is still very long. So, in ASP .NET the report is recreated every time on the server when any of the ReportToolbar's buttons are clicked or a postback occurs. If a report is very complex the obvious need is to prevent this lengthy recreation process.
Luckily, we are able to workaround this problem, and Plato's article nicely describes how. Just store the created report to a page's cache (or a Session), and then restore it again, if necessary.
First, you need to disconnect the ReportViewer from the Report at design time and use the page's OnInit method to set the ReportViewer.Report property.
override protected void OnInit(EventArgs e) {
InitializeComponent();
base.OnInit(e);
if (Cached)
ReportViewer.Report = RestoreReport();
else
ReportViewer.Report = CreateReport();
}
Note: I've slightly modified the code from that article so that it will be easier to understand in the context of this blog entry.
Here, Cached is the property that indicates whether a report has already been cached or not.
private bool Cached {
get {
if(Session["ReportIndex"] != null) {
return true;
}
else {
return false;
}
}
}
If a report has already been saved to a Session, then it can be easily restored as follows:
private XtraReport RestoreReport() {
return Session["ReportIndex"] as XtraReport;
}
Creating a report object at runtime is also a very obvious. Interestingly here a created report should be saved to a Session, from which it will be restored:
private XtraReport CreateReport() {
XtraReport report = new XtraReport1();
report.CreateDocument();
StoreReport(report);
return report;
}
private void StoreReport(XtraReport report) {
Session["ReportIndex"] = report;
}
But all this will be in vain if you forget one important thing. Every time a ReportViewer is unloaded, it disposes of the report assigned to its Report property. To avoid this you should handle the ReportViewer.ReportUnload event and set the ReportViewer.Report property to null.
private void InitializeComponent() {
this.ReportViewer.Unload += new System.EventHandler(this.ReportViewer_Unload);
}
private void ReportViewer_Unload(object sender, System.EventArgs e) {
ReportViewer.Report = null;
}
That's all you need to do... The first time a report is loaded will take a while, but then an end-user can easily navigate through its pages without needing to wait so long.
I hope this approach will be useful to all those who use XtraReports for Web reporting, and make your life a bit easier.
PS. If you have any comments on this, or have any ideas on how web performance can be improved, please, add your comments to this post.