By far the #1 complaint I hear from users of various web applications is that printing a page is not WYSIWYG. It’s really a simple problem that the industry has sort of swept under the rug for most of the history of the Internet. Browser printing in the current versions of IE and Firefox is simply horrible, and while server technologies like ASP.NET and PHP have gotten better and better at screen presentation with every release, printing simply not kept up pace. As web developers we spend our time figuring out all the intricacies of browser page rendering, and often are asked to do the same thing for printing. It’s frankly a frustrating, difficult problem to solve. IE7 should finally fix many of these problems when it’s released, but what are we supposed to do until then? And even when it’s released, how many years will we be designing to support the current crop of web browsers?
Adobe PDF Printing Rocks
Adobe’s PDF format does have it’s issues, but it also has huge advantages that make it a great solution for creating printable website documents. 1) Nearly all your users already have the free reader software and 2) Printing is nearly 100% WYSIWYG. So what’s the solution to your website printing problems at least until you can guarantee that the majority of your users will be using a print-friendly browser? Simple, when a user makes a print request on your site, dynamically create PDF documents on the fly making sure to include all of your users page state, and output that PDF document to the browser. Simple right? Well, it’s actually easier said than done. You have two big issues when attempting to solve this problem: Finding a decent PDF writing component to deploy on your webservers, and being able to accurately render a html page to this component while at the same time preserving your user’s page state.
Finding a Decent PDF Component
You can then take the resulting document and stream it back to the browser. Here’s what the PDF output looks like rendered via the Acrobat reader in IE
Preserving Page State
A problem you’ll find with this method of generating PDF documents is that while it works well for static HTML pages and other content, it quickly breaks down for anything but the simplest web applications. The reason? This PDF component won’t carry the user’s state information such as login status, session and viewstate cache, through the request, therefore, the resulting PDF output may not show things like secure content, grid sorting, or other page content that is dependent on Page State. You’ll often bump up against this limitation when you’re trying to stream the content of a web response to some other output location, such as a file, database, cache, email or something else entirely. The solution to this problem is to create a custom ASP.NET Response.Filter. This will allow you to intercept the response that would normally be sent to the user’s browser, and do all kinds of neat things with it, like turn it into a PDF document. Here’s a great article from a great site that talks all about these Response.Filter thingeys.
Putting it all Together
In order to get this all to work properly, you’ve got to wire it all up. I’ve found that the following method works best:
First, create a linkbutton on your master page to allow the user to create a “Printable PDF View” Handle the button click event, and hand off the response to your custom PDF response filter. Here’s the code Snippet which switches the filter:
In your custom filter, write the output stream temporarially to the cache (or wherever you want to temporarially store it). It has to be stored somewhere that any web request can access it. Good candidates are the file system, cache, or the database. NOTE: This is what is called “Security by Obscurity” and is generally considered not secure enough for any highly sensitive data, such as credit card information. The issue is that while it may be extremely difficult to guess the GUID and you’d have to make the page request during the milliseconds or so that passes while this rendered HTML waits to be picked up, it is possible that it could be intercepted. So, don’t do this if you work for a bank or the government . I don’t and find it secure enough for most applications I work with.
The PDF component has be issued a one-time ticket (GUID) to pickup the resulting HTML (which may contain secure information) and the Http response is re-directed to an ASHX handler that will create the PDF document. This handler creates a SuperGoo pdf document, and requests the stored html, passing in the ticket (GUID).
A final ASHX handler writes out the stored HTML and removes it from cache.
This all allows the exact HTML that would normally be sent back to the browser, to be routed through the PDF component and sent back to the user in PDF resulting in a true WYSIWYG printable page.
I’ve thrown together a quick sample app that you can download here that demonstrates this entire process. You’ll have to visit webSuperGoo and download the trial PDF component to get this to work. It shows you the following page, allows you to set some session and view state information, then allows you to generate a WYSIWYG PDF document.
Clicking the Printable PDF View link will generate a pdf, with the calendar and other page state and login information saved.
Good luck, and I hope this can help solve your web printing headaches, it certainly did for me!
[tags: ASP.NET, PDF, WYSIWYG Printing]