Printing from ASP.NET MVC

Even though we're less inclined to print web-pages nowadays, it often makes sense to save useful content from a website as a PDF file to read offline. Modern browsers give us everything we need to do that, and there is much that the website designer can do to improve the results. However, there are times that something more demanding is required, such as a properly-formatted invoice or chart, and then the web application needs a way of creating PDFs directly.

Because you use the web to view and share information, you don’t want to use the printer anymore, right? Yet, just because the web (and software in general) is so pervasive in our life and business you might still need to print information at least occasionally, or at least to save the content as a PDF file. And here’s the question: what’s the most effective way to print content from an ASP.NET MVC application?

All browsers offer some native services to support printing. When users right-click on a web page, the browser promptly offers to print the content or, in some cases, save it as PDF. Additionally, the client operating system such as Windows 10, or custom drivers, may also offer to print any content to a PDF file.

Do the native services of the browsers provide the ideal way to print business content from within a web application?

Overall, I believe the answer is “No; nobody can simply rely on browser native services to print application-specific content”. At the very minimum, you must prepare any content you intend to print just for that. This means, for example, removing or adapting stylesheets to remove overlays and graphics, smooth fonts and colors. After that, the physical act of printing is a mere matter of right-clicking the browser window and selecting the most appropriate print driver, whether a PDF driver or a regular print driver.

In this article, I’ll go through the most common things to do to print from an ASP.NET MVC application with a special focus on the programmatic creation of PDF files.

Printer-friendly Versions of Existing Pages

In HTML, the @media rule allows the website designer to specify a set of CSS settings that are appropriate for when the page is sent to a printer driver to be printed on paper or as a PDF file. What would be appropriate? Usually, you’d want a different font, and remove most of the graphics and colors that make the same page quite more catching to the eye. Here’s how to use the @media rule to specify different CSS files for screen and print.

This job of setting a different CSS file for printing is only the first step of a longer process. Let’s say you present users a page with some content that might be useful to print or save as PDF. The figure below shows a reasonable example.

D:\My Articles\SimpleTalk\2017\Pdf\Fig01.png

The figure presents the schedule of some user of some application and does that in a way that attempts to be appealing to the viewer on-screen. It may not be that easy or effective to just print the displayed HTML. The page is quite simple and doesn’t include any rich graphics as many other web pages. Nonetheless, printing a screen-optimized web page rarely leads to great results. Designs that work well on-screen don’t usually translate well to the printed page. That’s why I usually add a PRINT button to any page with content that users might want to print or save. The print button just opens up a separate popup window where the content is rendered in a printer-friendly way.

Any page with content that users might need to print should have a printer-friendly version that is displayed on demand. It’s extra work for sure, but the level of service for users grows significantly. Furthermore, the extra work is, most of the time, no more than a simple change of CSS files. Based on my own experience I wouldn’t honestly just say so: When you are creating a printer-friendly version of a web page, you will usually want to create a new page from scratch; albeit largely based on an existing one. When, by good fortune, the structure of the screen page lends itself well to be printed as-is, then you can do the job with just a couple of LINK elements for screen and print, as shown above.

Writing HTML Content to PDF Files

Sometimes, beyond just outputting the content of an HTML page to a physical printer, you just need to create PDF files that users can then print and archive conveniently. There are many libraries to create PDF files, both commercial and open-source, and some of them are even usable from JavaScript. The hard part is in laying out content to the PDF surface. The PDF file format, originally created by Adobe over two decades ago, is today the universal way to exchange documents between individuals and/or organizations worldwide. The PDF format is largely based on the PostScript programming language for layout and graphics. In addition to the PostScript-like description of the content, a PDF file contains fonts and meta information to organize and compress the document content. Creating a PDF file programmatically—even with the help of ad hoc libraries—is not a walk in the park. It’s probably quite easy to create a text-only document, but the more sophisticated the final layout of the document, the more painful and long it gets to code it. It is even worse when the idea of the document you have in mind is expressed with HTML. In this case, the difficulty is in switching from an HTML layout to a PostScript layout.

Most web applications require the content of a page to be rendered as a PDF that users can then download. Through the figure above, I presented a possible, fairly low-cost, strategy for achieving just this. You offer to open up a printer-friendly HTML page for users, and have them print it to paper or PDF using any drivers installed on the client machine. It’s a simple and effective approach and, personally, I have quite a long record of projects where I successfully used it. It works but it doesn’t cover all possible scenarios. In some cases, in fact, you need to create a physical PDF file (for example, to attach it to a server-sent email message) and you would ideally do it from a HTML template. In this case, the problem becomes how to convert—programmatically—some HTML content to the PDF format. Before discussing a couple of programmatic options, let me just mention a third way—using the wkHtmltoPdf open-source command line utility. (See http://wkhtmltopdf.org.)

You deploy the file to the server, configure permissions properly so that a new file can be created and then launch the executable programmatically:

The value assigned to the Arguments property is the URL serving the HTML that the utility will convert to PDF. If you embed this code in a custom application, the URL will be a method exposed by some controller class.

Using the SelectPdf Library

There are many libraries out there that help to create PDF files programmatically and in many cases they also convert HTML content to PDF. Most of these libraries are commercial products that require a monthly subscription. Overall, it’s no big deal for a high-traffic web site or any web site where the creation of PDF files is a crucial feature. It might be too expensive, however, for those sites where having PDF files created is only an enhancement, and the customer is not necessarily willing to pay even a small extra price for it.

There are also many open-source and free PDF libraries but, as far as I know, none of them supports HTML-to-PDF conversions, with one notable exception: the SelectPDF library. (See http://www.selectpdf.com or install it via Nuget.) SelectPDF is a fully-featured commercial product that also offers a free community edition with some limitations such as the fact that no processed documents are allowed to have more than five pages. Here’s a code snippet that shows how to integrate the library in the implementation of a controller action method.

The wrapper class PdfService receives the HTML string to convert and the full server-side file name to create. The third parameter—baseUrl—is optional but required if the HTML string references external resources such as images, stylesheets or script files. The good news is that baseUrl works well even with a localhost base server. Here’s the code necessary to actually create the PDF file with SelectPDF.

The minimal code that is strictly required to create a PDF is three lines: create the converter, create the document and save it to disk. However, you might want to specify a bunch of options—for example to enable printing of backgrounds graphics and fonts—and create a footer. When creating a footer, page_number and total_pages are two pseudo variables you use to instruct the library to create the text you wish printed. When deploying a solution based on SelectPdf, in addition to the Select.HtmlToPdf DLL you also must deploy the HTML engine. It’s a pretty large file (about 45 MB) named Select.Html.dep.

Using a library to convert HTML to PDF in the context of a web application is extremely efficient from a development perspective. You don’t need at all to learn about PostScript and the internal PDF rendering logic. You stay focused on HTML and HTML layout logic and just rely on an external tool to make the conversion. At any rate, using a built-in tool to save to PDF doesn’t save you the burden of thinking about a printer-friendly layout for any content to be saved. Compared to the approach summarized by the figure above, using a library like SelectPDF only saves users from right-clicking on a popup window and printing through a PDF driver.

Creating PDF Files from JavaScript

I confess that I was shocked when I first heard about the possibility of creating PDF files through JavaScript libraries. Yet, it’s not simply a possibility; it’s a concrete reality. You can achieve that in two main ways. First, you can use a low-level JavaScript PDF writer and compose the PDF file using the native PDF rendering logic. This capability is offered by the jsPDF library. (See http://parall.ax/products/jspdf.) In this way, you create a rendering surface and start adding writing instructions. Here’s the bare minimum code you need.

It’s easy and effective as long as the template of the final document is fairly simple—it allows to specify fonts, colors, position, even simple shapes and images. However, if you need to add more sophisticated layout structures like tables—and even more if you want to use HTML as your layout language—the direct use of jsPDF loses much of its original appeal.

The jsPDF library supports plugins and a plugin exists that tries to render HTML tables to PDF. The plugin is jsPdf.autotable.js and you can find it here: http://simonbengtsson.github.io/jsPDF-AutoTable. While it works in some way, though, it is far from being the foundation of a true fully-fledged client-side HTML-to-PDF converter.

Another approach to creating PDF files you might want to try is to pass through the HTML5 canvas element. The idea is that you use an ad hoc library to take an existing segment of the DOM and render it to a HTML5 Canvas element. Then, using the native interface of Canvas you save it to a PNG or JPG image and add it to a PDF file created with jsPDF. The HTML2Canvas conversion library can be found at: http://html2canvas.hertzen.com. As the home page of the site clearly states, that’s mostly a way to capture web screenshots using JavaScript. However, once you’ve done just that you can easily save it to PDF.

The main drawback with this approach is the quality of the resulting print. Because all you print is an image it might not be zoomed in with great results.

Wrapping Up

Creating PDF files from within web applications, including ASP.NET MVC applications, is an increasingly common task, yet it is a highly specialized task with plenty of commercial products to help out. In this article, I summarized a couple of options that won’t cost money but still present some limitations. As usual in this business, any solution you work out is a trade-off between what you need and what you want to pay. In my vision of the world, the ideal is when you’re able to pay a reasonable price for exactly what you need: no more no less.

  • 13633 views

  • Rate
    [Total: 32    Average: 4.1/5]
  • david

    great articel, I only miss the PRINT button

  • Aaron Fischer

    should look at pdfkit.org. for multiple reasons we picked this for use in rendering pdfs in nodejs and browser.

  • Ben Edwards

    Good article.
    A few extra quirks to watch out for:
    – Printer friendly css is often stripped out by modern browsers, particularly webkit based ones. 🙁
    – If you want proper document formatting then your options are more limited. wkhtmltopdf can do headers and footers but for full word-style support you will need to use paid solutions like princexml or aspose (with a word template).
    – Major gotcha for people using Azure Webapps – sometimes rendering pdfs results in whichever library you are using calling some low level Win32 apis that are disabled in webapps (to reduce security footprint). I personally encountered this issue when trying to add svg images into my pdfs. wkhtmltopdf in my experience does not have this issue.

  • spiderman

    Check out Rotativa (https://github.com/webgio/Rotativa). I’ve been using this for years to render MVC Razor views as PDF documents and it’s never failed me.

  • David A Bacher

    From a commercial standpoint, you also have Syncfusion, DevExpress, ComponentOne — someone else mentioned the Apose libraries.

    Using Canvas or another image-file based conversion is generally a bad idea. While a PDF may be used to print, a lot of users will just save the file off somewhere. If I have this PDF file that I’ve saved off, it’s really useful to copy / paste text from it. In certain use cases, you’ll get a lot of complaints if you elect to go the Canvas route.

    Using JavaScript can be troublesome if you have a significant number of users who might be using Microsoft browsers, or who are potentially on older versions of Android. Old Android tablets that no longer receive software updates are surprisingly common, and are quickly replacing old versions of Internet Explorer as the scourge of web developers.

    • Ed Charbeneau

      Great point David, don’t forget about Telerik too. There’s several methods of getting data exported here http://www.telerik.com/kendo-ui/exporting-web-content and http://docs.telerik.com/devtools/document-processing/introduction

      • David A Bacher

        I’ve heard Telerik is excellent as well.

        Crystal Reports is my old poster child for how not to do export. They had an Excel option for years, and that output a floating text box for each page, and then all the data was formatted in the floating text box. And so it had an Excel option, but it was worthless because 100% of the cells were empty.