Click here to Skip to main content
13,903,514 members
Click here to Skip to main content
Add your own
alternative version


7 bookmarked
Posted 24 Apr 2015
Licenced CPOL

Create PDF With Bookmark and TOC from HTML with iTextSharp-LGPL.4.1.6

, 24 Apr 2015
Rate this:
Please Sign up or sign in to vote.
How to export HTML to PDF with Bookmart and TOC using iTextSharp-LGPL.4.1.6


This tip shows how to export HTML to PDF with Bookmark and TOC using iTextSharp. Technology includes ASP.NET MVC, iTextSharp 4.1.6 (LGPL/MPL). 

Prepare Your HTML Content

Create new view has name PDFContent.cshtml with your content. Here is a sample:

<p>This article shows how to create a load more button to your Kendo Grid 
without using default paging control. Technology includes ASP.NET MVC, 
jQuery and Kendo Grid Controls. I also used SQL Server Database Northwind for this sample.</p>

<p>With Kendo Grid you can&nbsp;easily configure the grid to display data and perform sorting, 
paging and grouping operations via its built-in settings. Now, I will show you how to add a 
load more button without using paging control. This article will apply for 
both server and client paging of Kendo Grid.</p>
<br />

<h2>Setting up Environment</h2>
<p>Please follow steps instruction 
<a href="">here 
</a>to setup environment.</p>


Using the Code

Step 1 - Add iTextSharp References and Create Your New Action for Controller

This action will export PDF on your Controller, as follows:

using iTextSharp;
using iTextSharp.text;
using iTextSharp.text.html;
using iTextSharp.text.html.simpleparser;
using iTextSharp.text.pdf;
public ActionResult Index()
    string htmlContent = RenderRazorViewToString("~/Views/Shared/PDFContent.cshtml");

    return File(GenerateHtmlToPDFDocument(htmlContent), "application/pdf");
With the PDFContent.cshtml we've just created above.

Step 2 - Render Razor View to String

We need to create a function RenderRazorViewToString to get the content in PDFContent.cshtml, as follows:

/// <summary>
/// Render View to String
/// </summary>
/// <param name="viewName"></param>
/// <returns></returns>
public string RenderRazorViewToString(string viewName)
    using (var sw = new StringWriter())
        var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
        var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
        viewResult.View.Render(viewContext, sw);
        return sw.GetStringBuilder().ToString();

Step 3 - Create Bookmark From Your HTML Content

This function will split all H2 tags in your HTML content and create section for them.

/// <summary>
/// Create chapter content from html
/// </summary>
/// <param name="html"></param>
/// <returns></returns>
public Chapter CreateChapterContent(string html)
    // Declare a font to used for the bookmarks
    iTextSharp.text.Font bookmarkFont = iTextSharp.text.FontFactory.GetFont
    (iTextSharp.text.FontFactory.HELVETICA, 16, iTextSharp.text.Font.NORMAL, new Color(255, 153, 0));

    Chapter chapter = new Chapter(new Paragraph(""), 0);
    chapter.NumberDepth = 0;

    // Create css for some tag
    StyleSheet styles = new StyleSheet();

    styles.LoadTagStyle("h2", HtmlTags.HORIZONTALALIGN, "center");
    styles.LoadTagStyle("h2", HtmlTags.COLOR, "#F90");
    styles.LoadTagStyle("pre", "size", "10pt");

    // Split H2 Html Tag
    string pattern = @"<\s*h2[^>]*>(.*?)<\s*/h2\s*>";
    string[] result = Regex.Split(html, pattern);

    // Create section title & content
    int sectionIndex = 0;
    foreach (var item in result)
        if (string.IsNullOrEmpty(item)) continue;

        if (sectionIndex % 2 == 0)
            chapter.AddSection(20f, new Paragraph(item, bookmarkFont), 0);
            foreach (IElement element in HTMLWorker.ParseToList(new StringReader(item), styles))


    chapter.BookmarkTitle = "Demo for Load More Button in Kendo UI Grid";
    return chapter;

Step 4 - Generate PDF Document

First, we need to generate chapter content from Step 3 to PDF Document.

/// <summary>
/// Generate PDF from HTML
/// </summary>
/// <param name="html"></param>
/// <returns></returns>
public byte[] GenerateHtmlToPDFDocument(string html)
    MemoryStream workStream = new MemoryStream();
    Document pdfDoc = new Document(PageSize.A4);
    PdfWriter.GetInstance(pdfDoc, workStream).CloseStream = false;
    HTMLWorker parser = new HTMLWorker(pdfDoc);

    // Get chapter content
    Chapter chapter = CreateChapterContent(html);


    // Add chapter content to PDF


    byte[] byteInfo = workStream.ToArray();
    workStream.Write(byteInfo, 0, byteInfo.Length);
    workStream.Position = 0;

    // Generate TOC for existing content
    return GeneratePDFTOCContent(byteInfo, html);

And then, we will generate TOC for your PDF, as follows:

/// <summary>
/// Generate PDF To Content
/// </summary>
/// <param name="content"></param>
/// <returns></returns>
public byte[] GeneratePDFTOCContent(byte[] content, string html)
    var reader = new PdfReader(content);
    StringBuilder sb = new StringBuilder();

    // Title of PDF
    sb.Append("<h2><strong style='text-align:center'>
    Demo for Load More Button in Kendo UI Grid</strong></h2><br>");

    // Begin to create TOC
    sb.Append(string.Format("<tr><td width='80%'><strong>
    {0}</strong></td><td align='right' width='10%'>
    <strong>{1}</strong></td></tr>", "Section", 
    using (MemoryStream ms = new MemoryStream())
        // XML document generated by iText 
        SimpleBookmark.ExportToXML(SimpleBookmark.GetBookmark(reader), ms, "UTF-8", false);

        // rewind to create xmlreader
        ms.Position = 0;
        using (XmlReader xr = XmlReader.Create(ms))
            string page = null;
            string text = null;

            string format = @"<tr><td width='80%'>{0}</td>
            <td align='right' width='10%'>{1}</td></tr>";
            // extract page number from 'Page' attribute 
            Regex re = new Regex(@"^\d+");
            while (xr.Read())
                if (xr.NodeType == XmlNodeType.Element && 
                xr.Name == "Title" && xr.IsStartElement())
                    page = re.Match(xr.GetAttribute("Page")).Captures[0].Value;

                    if (xr.NodeType == XmlNodeType.Text)
                        text = xr.Value.Trim();
                        int pageSection = int.Parse(page) + 1;
                        sb.Append(String.Format(format, text, pageSection.ToString()));


    MemoryStream workStream = new MemoryStream();
    var document = new Document(reader.GetPageSizeWithRotation(1));
    var writer = PdfWriter.GetInstance(document, workStream);
    writer.CloseStream = false;


    // Add TOC
    StyleSheet styles = new StyleSheet();
    styles.LoadTagStyle("h2", HtmlTags.HORIZONTALALIGN, "center");
    styles.LoadTagStyle("h2", HtmlTags.COLOR, "#F90");

    foreach (IElement element in HTMLWorker.ParseToList(new StringReader(sb.ToString()), styles))

    // Append your chapter content again
    Chapter chapter = CreateChapterContent(html);


    byte[] byteInfo = workStream.ToArray();
    workStream.Write(byteInfo, 0, byteInfo.Length);
    workStream.Position = 0;

    return byteInfo;


  1. iTextSharp - Links and Bookmarks
  2. Creating HTML Table of Contents from PDF Bookmarks
  3. Render a razor view to string
  4. Demo for Load More Button in Kendo UI Grid


  • 24th April, 2015 - Initial version


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Ly Nguyen - LN
Software Developer (Senior) Success Software Services
Vietnam Vietnam
No Biography provided

You may also be interested in...


Comments and Discussions

Questionobsolete Pin
pixeltrace9-Sep-17 20:30
memberpixeltrace9-Sep-17 20:30 
GeneralLicense. Pin
Valery Possoz24-Apr-15 9:22
professionalValery Possoz24-Apr-15 9:22 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web01 | 2.8.190306.1 | Last Updated 24 Apr 2015
Article Copyright 2015 by Ly Nguyen - LN
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid