Returning PDFs from an ASP.NET MVC action
internet, itext, opensource, pdf, programming, spark April 12th, 2009This 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.

April 13th, 2009 at 7:13 am
Returning PDFs from an ASP.NET MVC action | Where’s Lou…
Thank you for submitting this cool story – Trackback from DotNetShoutout…
April 13th, 2009 at 7:49 pm
ASP.NET MVC action 返回一个XML文件 | Where’s Lou…
9efish.感谢你的文章 – Trackback from 9eFish…
April 27th, 2009 at 2:26 pm
Nice post…
May 11th, 2009 at 11:57 am
Sweet, thanks.
May 11th, 2009 at 12:02 pm
While I can’t seem to find the itext.dtd file anywhere online on its own, it is a part of one of the examples I found:
http://www.ridgway.co.za/archive/2005/07/31/itextsharpxmltopdfexample.aspx
(direct link to zip file containing dtd: http://www.ridgway.co.za/Images/ridgway_co_za/iTextSharpExample.zip)
May 11th, 2009 at 1:09 pm
Yeah, it seems iText’s xml format is a result of loader-builder code streaming the source to create in-memory objects. So no dtd, schema, or serializable classes. Kind of unfortunate but understandable.
May 27th, 2009 at 8:51 pm
[...] Returning PDFs from an ASP.NET MVC action [...]
November 12th, 2009 at 3:54 am
How is it possible to add headers amd footers
February 16th, 2010 at 2:52 pm
I know this is an old post, but I am really struggling to render my pdf using the spark view engine. The view engine was really easily to install and configure; it’s the XML for the pdf that’s got me against the wall. Bill’s link to the dtd was a big help. However, if I read the dtd correctly, and supported by my testing, it seems you cannot have tables within tables. I am trying to create a pdf form with areas with borders inside of borders. Any clue how that would be accomplished?
February 17th, 2010 at 12:44 am
Sorry – no idea really. The PDF capabilities in general, and that XML dialect in particular, are things I learned just enough to integrate and write a sample. You’ll need to hunt down the author of those libraries for an answer.
April 27th, 2010 at 7:47 pm
This is a good post. Although will you be able to point me in the right direction on how i can go about discovering more of these tags and attributes in itextsharp.dll assembly? For example, I’d like to know what tags and what attributes are out there so that I can easily format my pdf document as how i would format html. I am struggling in this area only because of my lack of knowledge of these tags and attributes.