We have spent quite a bit of time looking at all the various ways to render images and what we can do with those rendered images. It's time to turn away from image rendering and look at something perhaps equally useful. In this recipe, we will look at how we can generate a PDF from an action. We will specifically look at how to render an order summary. Obviously, you could take this in many directions!
There are a couple of things that we will need to do to get ready for this recipe. First of all, we are going to use the iTextSharp library (another project ported from the Java world). You can get this here: http://sourceforge.net/projects/itextsharp/. Make sure you download the 2.0 version. There is also a copy in the dependencies folder.
Then I am going to have you go fetch a helper class that will make working with iTextSharp way easier. The class we are going to use is called HtmlToPdfBuilder
and was created by "Hugo Bonacci". You can find it here http://somewebguy.wordpress.com/2009/05/08/itextsharp-simplify-your-html-to-pdf-creation/ or in the Models
folder of this recipe's code.
Models
folder called PdfResult
. PdfResult
class to inherit from ActionResult
. Then create the ExecuteResult
.PdfResult.cs:
public class PdfResult : ActionResult { public override void ExecuteResult(ControllerContext context) { } }
ExecuteResult
method, we will piece together a PDF. First off, we need to create an instance of HtmlToPdfBuilder
.HtmlToPdfBuilder builder = new HtmlToPdfBuilder(PageSize.LETTER);
HtmlPdfPage
, which we will use to create one page in our PDF.HtmlPdfPage page1 = builder.AddPage();
HtmlPdfPage
, we can create a page by feeding in chunks of HTML. You can programmatically do this either one chunk at a time, or you can feed in one big blob of HTML. Both methods work!page1.AppendHtml("<h1>Order #19807</h1>"); page1.AppendHtml("<p>Andrew Siemer<br>"); page1.AppendHtml("4254 Some Street<br>"); page1.AppendHtml("Los Angeles, CA</p>"); page1.AppendHtml("<table><tr><td><b>Product</b></td><td><b>Price </b></td></tr>"); page1.AppendHtml("<tr><td>ASP.NET MVC Cookbook</td> <td>$40.00</td></tr></table>");
byte[] file = builder.RenderPdf();
HttpResponseBase response = context.HttpContext.Response; response.ContentType = "application/pdf"; MemoryStream pdfStream = new MemoryStream(file);
while (true) { int read = pdfStream.Read(buffer, 0, buffer.Length); if (read == 0) break; response.OutputStream.Write(buffer, 0, read); } response.End();
PdfResult
is built, we can go to our HomeController. In our HomeController we will create a new method named GetPdf
. This action will be a PdfResult
. Because we coded our PDF generation directly in the ActionResult
, all we need to do is declare the method.HomeController.cs:
public PdfResult GetPdf() { return new PdfResult(); }
Index.aspx:
Click <%= Html.ActionLink("here","GetPdf", "Home") %> to get your order in PDF format!
In this recipe, we created a PDF using the iTextSharp
product. We were able to do it so easily because we used the HtmlToPdfBuilder
that Hugo Bonacci created. This class is an easy-to-use wrapper for a great but not so easy-to-use PDF generation tool.
Once we had the PDF, we converted it into an array of bytes. Once you have something converted into an array of bytes, streaming it down to the client that requested the resource is rather straightforward using the HTTP
response.