ASP.Net & Web EricSavage - 05 Jun 2009 12:37 pm
Active Reports: Displaying reports in a browser
Our client required a modification to an existing web solution that displayed confidential results in html format, which could be printed from the results page. The data was sensitive and was being forged, so we looked at adding a watermark. This required moving across to using reporting rather than html, so we started building up a report structure.
I was very pleased to find that Active Reports provided a WebViewer control, especially since it gave you the option of either displaying reports with an ActiveX option or with a Adobe Reader option. My assumption was the latter required extra processing to convert a document to PDF first. However, the ActiveX option requires the client user to have internet access to download the plugin, whereas the Adobe browser plugin can be installed from a downloadable installer that can be run on any PC.
I was seriously misled though. Having run down the development path with WebViewer for a while, I couldn’t get rid of the licensing message at the bottom and discovered that the control is only available to Professional users, whereas we were using Standard. If you do have Active Reports Professional, have a look at the WebViewer.
Fortunately, the Active Reports website hinted at another approach, which I adapted for my own use and it works well. My original concern with PdfExport was that the user experienced the lag that happens while Adobe Reader fires up in its own window. Also, if I displayed the PDF in the current window, you lose the context of the website.
The end solution uses an IFrame, effectively using two pages to achieve the solution. The ViewSpecResult (the parent page) has an IFrame and the PdfPage sits inside it and invokes the report generation.
Here is the ViewSpecResultASP markup:
<%@ Page Language="C#" AutoEventWireup="true"
CodeBehind="ViewSpecResult.aspx.cs"
Inherits="ResultsViewing.ViewSpecResult" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>Results Viewing</title>
<link href="FormStyling.css" rel="stylesheet" type="text/css" />
<style id="headerscript" runat="server" type="text/css">
IFRAME
{
POSITION: absolute;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<div>
<iframe runat="server" src="PDFPage.aspx" height="70%"
width="98%" id="IFRAME1"></iframe>
</div>
</form>
</body>
</html>
The ViewSpecResult C#/VB code is empty. The PdfPage ASP markup is like this:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="PDFPage.aspx.cs" Inherits="ResultsViewing.PDFPage" %> <%@ Import Namespace="ResultsViewing"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Results Report</title> </head> <body> <form id="form1" runat="server"> <div> </div> </form> </body> </html>
The PdfPage.aspx.cs code looks something like this in my application:
public partial class PDFPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string xml = ReportController.GenerateXmlForSpecimenArray();
MemoryStream m_stream =
ReportController.GenerateReportToMemoryStream(xml);
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposistion",
"inline; filename=MyExport.pdf");
Response.BinaryWrite(m_stream.ToArray());
Response.End();
}
}
This calls through to a central controller close, which generates the report something like this:
public static ReportSimple GenerateReport(string xml)
{
string xslFilename = HttpContext.Current.Server.MapPath("~")
+ "header.xsl";
ReportSimple report = new ReportSimple(xslFilename);
XMLDataSource dataSource = new XMLDataSource();
dataSource.FileURL = null;
dataSource.RecordsetPattern = "//SPECIMEN_HEADER";
dataSource.LoadXML(xml);
TrimXmlNodes(dataSource);
report.DataSource = dataSource;
SetWatermark(report);
report.Run();
return report;
}
public static MemoryStream GenerateReportToMemoryStream(string xml)
{
MemoryStream memoryStream = new MemoryStream();
ReportSimple report = GenerateReport(xml);
PdfExport export = new PdfExport();
export.Security.Encrypt = true;
export.Security.Permissions = PdfPermissions.AllowPrint;
export.Export(report.Document, memoryStream);
memoryStream.Position = 0;
return memoryStream;
}
Now all this code has been adapted from the official Active Reports knowledge base, where the solution is more complex in that it provides for a separate Web Service to do the report generation, which helps to spread the server load. This was overkill for my application.
Note that I pulled off some interesting XML data sourcing for this application. I’ll write about it in another post after this for those who are interested. I saved huge amounts of processing time this way using XSLT.

on 13 Jul 2009 at 10:36 pm 1.aashish said …
that looks cool to me. can we try this product for free? like a trail pack?
on 14 Jul 2009 at 8:14 am 2.EricSavage said …
Have a look at the Active Reports website to see what their trial offers are:
http://www.datadynamics.com/
on 09 Feb 2010 at 2:16 pm 3.returnCode said …
Thank’s a lot man!
You help me a lot!