Over a million developers have joined DZone.

Creating Dynamic PDFs in ASP.NET MVC Using iTextSharp

PDFs are a great way to give your users a deliverable after they finish reading your site. Today, we go over an easy way to create dynamic PDFs for any type of content using iTextSharp and the Razor Engine.

· Web Dev Zone

Start coding today to experience the powerful engine that drives data application’s development, brought to you in partnership with Qlik.

Rolled up Paper on a Page with a lightbulb drawing

PDFs are a great way to give your users a deliverable after they finish reading your site.

Of course, there are other services that allow your readers to take content and store it somewhere for later reading like Evernote's Web Clipper and Pocket.

But today, we go over an easy way to create PDFs based on posts that you can immediately deliver to your audience.

I will be implementing this on the site in the future, so this code below will be 99% production ready.

First Ingredients

First, our project needs iTextSharp and the Razor Engine.

For those new to these libraries, iTextSharp is a .NET library that allows you to create PDFs using C# or VB.NET code.

The Razor Engine is the templating engine used to render your Views in your ASP.NET MVC application. The library was abstracted and can be used as a standalone package.

You can even use the AT (@) syntax for your Views (which we'll do later).

But, we're getting ahead of ourselves.

First, open your MVC project, then your Package Manager Console (View->Other Windows->Package Manager Console) and type:

Install-Package RazorEngine

Install-Package iTextSharp

Install-Package iTextSharp.xmlworker

Install-Package iTextSharp.xtra

Once these are installed, you are ready to write code.

Use the Clicky-Clicky!

In our View, we need a way to tell the server we want the PDF. For our demonstration, we'll simply make a link to issue the retrieval of it.

On our blog post page, we will have a section for requesting the PDF.

<div class="alert alert-success">    <a href="/Blog/GetPdf?code=@Model.Post.Hash">Get PDF version</a></div>

The Hash is the ID of the blog post we'll pass into the controller.

Need Some Action!

The link above points to GetPdf in the BlogController, so we'd better make one.

This Action Method is not optimal, but again, it's just for demonstration purposes.

We need to load the post based on the code so we can pass it on to the PdfBuilder.

GetPdf Action Method

public ActionResult GetPdf(string code){    var unitOfWork = this.ControllerContext.GetUnitOfWork<BlogUnitOfWork>();    var repository = unitOfWork.GetRepository<PostRepository>();    var post = repository.GetByHashId(code);    var builder = new PdfBuilder(post, Server.MapPath("/Views/Amp/Pdf.cshtml"));    return builder.GetPdf();

Notice I passed in the post object and the filename of the HTML I want rendered in the PDF.

The reason I have the Pdf.cshtml in the Amp folder is because since I already made a watered-down version of my blog posts using Google AMP's initiative (discussed here), I thought this would be a great place to put an even more watered down version of a post.

The Pdf.cshtml is definitely smaller. I wanted a vanilla version of a blog post and then we can spruce it up later if we want. I didn't want to tax the iTextSharp renderer. ;-)

Here's what the Pdf.cshtml looks like.


@model Post<html><head>    <title>@Model.Title</title></head><body><h2>@Model.Title</h2>

As you can see, very plain. I didn't even add any CSS to it. Very basic.

NOTE: See the @Raw method? This is the equivalent of @Html.Raw(data). Even though the Razor syntax in Visual Studio complains about it, the iTextSharp requires it so this is one of those times when it's okay to be red... so ignore it!

Let's Build a Builder

With all of that out of the way, let's create our PdfBuilder class.


public class PdfBuilder{    private readonly Post _post;    private readonly string _file;    public PdfBuilder(Post post, string file)    {        _post = post;        _file = file;    }    public FileContentResult GetPdf()    {        var html = GetHtml();        Byte[] bytes;        using (var ms = new MemoryStream())        {            using (var doc = new Document())            {                using (var writer = PdfWriter.GetInstance(doc, ms))                {                    doc.Open();                    try                    {                        using (var msHtml = new MemoryStream(Encoding.UTF8.GetBytes(html)))                        {                            iTextSharp.tool.xml.XMLWorkerHelper.GetInstance()                                .ParseXHtml(writer, doc, msHtml, Encoding.UTF8);                        }                    }                    finally                    {                        doc.Close();                    }                }            }            bytes = ms.ToArray();        }        return new FileContentResult(bytes, "application/pdf");    }    private string GetHtml()    {        var html = File.ReadAllText(_file);        return Razor.Parse(html, _post);

As mentioned above, all we are passing into this class is the post object and the filename we want to render into the PDF.

When we call the GetPdf() method, we need the HTML first, so we do that by calling the GetHtml() method.

We read the file and then we let the RazorEngine perform it's templating just like you would pass an object into your View from a controller.

The Razor Engine replaces all of the @ syntax with the object we passed into it and our final version of the HTML is returned with the replaced data.

Once we get our populated HTML, we can now turn that HTML into a PDF using iTextSharp's XmlWorkerHelper to perform all of the work.

Once we have all the bytes, we can return that as a FileContentResult ActionResult and specify the content type (application/pdf).

Everything is done in memory. However, instead of recreating it every time, you could save it to a directory and check if it exists. If it does, send that back to the user instead of creating it every single time.

Now, as soon as the user clicks on the link, it will return a PDF to their browser where they can save it or print it.


Today, I introduced a way to create dynamic PDFs for any type of content using iTextSharp and the Razor Engine.

The Razor Engine has many uses and I'm glad they abstracted it out from ASP.NET MVC.

I do have one last note about rendering the HTML into a PDF—while it's not a full-blown rendering engine, it can perform the basics to make it functional. I didn't include JavaScript. It does use inline CSS, not external style sheets. Keep it simple when generating your PDFs.

Remember, it's a document, not a web page.

With that said, these two NuGet packages pack quite a punch together. You can imagine the amount of PDF content you can generate on-the-fly. The possibilities are endless.

What are your thoughts on building PDF's on the fly? Are you making a catalog with your database of products? Please share your thoughts in the comments!

Create data driven applications in Qlik’s free and easy to use coding environment, brought to you in partnership with Qlik.


Published at DZone with permission of Jonathan Danylko, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}