SQL Server Reporting Services stream PDF to browser
SQL Server Reporting Services has become more and more popular, in no small measure due to the fact that it is free. When used in web applications, there is often an requirement to present the user a report as PDF file. For all of the obvious reasons (fidelity, print accuracy etc) . One of our current projects had a similar requirement - but with a few added twists.
Our customer requested the ability to generate a PDF in a web application and as a workflow queue , store the report in a database - and to top it all off - have the entire process wrapped in a web service. The customers business process dictated that a report is generated and then locked, pending a review . While the report is locked it can be reviewed by any number of users but not changed. Plus it has to be the original PDF that was created in the first place ( so no “locking of data” and re-running the report over and over).
At first I wasn’t sure this was even possible. Can we render a PDF from SSRS by calling it directly without all the accoutrements of the SSRS web site etc. A quick email with Phil confirmed that in theory this can be done because in his words ” SSRS is just a web service itself. You don’t need the reporting services web site. ”
We ended up building a very interesting contraption. The web client calls a WCF web service that manages all interaction with SSRS and handles some parts of the queuing and workflow.
Yes the web client could call SSRS directly. The WCF piece is a wrapper that in the future will entail printing to other formats as well.
Depending on the state of the report the WCF Service either hands processing off to SSRS or simply pulls a previously generated report out of the database.
I have to give .NET a ton of credit here because this sort of approach would have been really difficult to deal with had it not been for the great serialization capabilities built into .NET.
There are two big areas of concern that we dealt with in building this tool. One was the need to get a serialized copy of the PDF file out of SSRS into the WCF Service, and the second of course was rendering the same information in the browser as it is streamed from the WCF.
Here is what the pertinent section of the WCF code looked like:
ReportingService repService = new ReportingService();
repService.Credentials = new NetworkCredential(Settings.Default.SSRSUsername,
Settings.Default.SSRSPassword,
Settings.Default.SSRSDomain);
byte[] data;
data = repService.Render(_reportName, “PDF”, null, null, parametersPassed, null, null, out encoding,
out mimetype, out parametersUsed, out warnings, out streamids);
The Credential Settings pertain to a domain user with appropriate rights to SSRS. The important part here is the fact that this call returns a byte array that contains the PDF of the report.
The technique of storing serialized data in a database has been around forever and I will not go into the details of that aspect of the system.
The second piece of the puzzle was the ASP.NET web client. And here is the code that renders the PDF in the browser. Notice that I am not listing the call to WCF that produces the rptresponse. Its simply the response object that contains the byte array written out in the example above.
byte[] report = rptresponse.Report;
Response.Clear();
//Send the file to the output stream
Response.Buffer = true;
Response.AddHeader(“Content-Length”, report.Length.ToString());
Response.AddHeader(“Content-Disposition”, “inline; filename= MyPdfTest”);
Response.AddHeader(“Expires”, “0″);
Response.AddHeader(“Pragma”, “cache”);
Response.AddHeader(“Cache-Control”, “private”);
//Set the output stream to the correct content type (PDF).
Response.ContentType = “application/pdf”;
//Output the file
Response.BinaryWrite(report);
//Flushing the Response to display the serialized data
//to the client browser.
Response.Flush();
So there you have it. In brief highlights the way one can produce PDF’s using SSRS via web services. I am sure there are other solutions to this problem, but in our case it was created reasonably quickly, it works well and runs surprisingly fast. Considering there is an entire extra step that pushes the report into a db, it seems very responsive.
Reference Material: http://support.microsoft.com/default.aspx/kb/875447
Write a comment