This feature is based on a post from Bill Barry, “Using Spark to render PDFs,” to the Spark discussion group.

It’s based on iTextSharp, a port of the iText Java PDF library. It seemed like such a useful twist on the view engine, and so applicable to web sites, that I integrated what Bill had done into the Spark project and added a PdfViewResult action result for the ASP.NET MVC library.

Here’s an example of how to return it from an action. You’ll find this in the PdfRendering sample.

        public ActionResult Invoice(string invoiceNumber, string format)
        {
            var repos = new InvoiceRepository();
            var invoice = repos.GetInvoice(invoiceNumber);

            if (format == "xml")
            {
                Response.ContentType = "text/xml";
                return View(invoice);
            }

            return new PdfViewResult {ViewData = new ViewDataDictionary(invoice)};
        }

The only line that really matters here is the return new PdfViewResult. If you were to use this in a application you’d probably have a base controller which would have a method to return a new PfdViewResult, so this line would read more like return PdfView(invoice);.

This example also takes an optional format=xml querystring parameter for returning the result of the view as iText xml instead of PDF. I have to say iText was a pain to figure out and the PDF format itself seems a bit quirky. Eventually I went through the itextsharp.dll assembly in reflector to try and figure out what elements and attributes could be used where.

Here are the contents of the itext.spark master layout.

<itext creationdate="${DateTime.Now}" producer="Spark.Reporting">
  <use content="view"/>
</itext>

I’m guessing if there were a number of PDFs on the file you could probably put page header/footer information here. That’s beyond my knowledge of iText.

And here is the Invoice.spark template. It’s a bit crazy looking but you get the idea.

<use master="itext"/>

<viewdata model="Invoice"/>

<image url="${Context.Server.MapPath('~/Content/images/logo.png')}"/>

<paragraph>
  <chunk style="font-weight:bold;">Invoice #:</chunk>
  <chunk>${Model.InvoiceNumber}</chunk>
</paragraph>
<paragraph>
  <chunk style="font-weight:bold;">Purchace Order:</chunk>
  <chunk>${Model.PurchaseOrder}</chunk>
</paragraph>

<table width="100%" widths="1;1"><row>
<cell><Address caption="'Ship to'" account="Model.ShipTo"/></cell>
<cell><Address caption="'Bill to'" account="Model.BillTo"/></cell>
</row></table>

<table width="100%" widths="3;8;2;4;4">
<row>
  <cell>Part#</cell>
  <cell>Description</cell>
  <cell horizontalalign="right">Qty</cell>
  <cell horizontalalign="right">Price</cell>
  <cell horizontalalign="right">Total</cell>
</row>
<row each="var line in Model.Items">
  <cell><chunk style="font-size:8;">${line.Product.PartNumber}</chunk></cell>
  <cell>${line.Product.Name}</cell>
  <cell horizontalalign="right">${line.Quantity}</cell>
  <cell horizontalalign="right">${line.Product.Price.ToString("c")}</cell>
  <cell horizontalalign="right">${line.TotalPrice().ToString("c")}</cell>
</row>
<row>
  <cell/>
  <cell colspan="3">Total</cell>
  <cell horizontalalign="right">${Model.TotalPrice().ToString("c")}</cell>
</row>
</table>

<paragraph leading="48.0" font="unknown" align="Default" red="255" green="0" blue="0">
  Hello World! Yay!
  <Chunk>${DateTime.Now}</Chunk>
</paragraph>

Any features of Spark are available generating the iText PDF xml, for example the _global.spark file is providing namespaces and the _Address.spark partial file is being used a few times at the top.