.Net, ASP.NET, CSS3, GridView, HTML, iTextSharp, JavaScript, PDF, Programming, Reports, Software, Technology, VB.NET, Visual Studio 2010, Web Development

Generate a PDF from an ASP.NET Web Page using the iTextSharp XMLWorker Namespace

If you need to quickly and easily generate PDF documents from ASP.NET, then the iTextSharp library for .NET is very convenient. To install and start using iTextSharp, you can download the zipped reference files from the SourceForge Web site and then add them to your Visual Studio project the same way as you would do with any other third party library file.

The latest version of iTextSharp has deprecated the older HTMLWorker object in favor of the newer XMLWorkerHelper object. This is good news for any developer who likes to use CSS formatting. Although the CSS support is still basic, it is a definite step up from the earlier version of the object which did not support CSS at all. For example, the new object allows a number of important behaviors such as PDF page breaks that were impossible to do using the older object.

To make use of the XMLWorkerHelper object you will need to reference two DLL files in your Visual Studio project. These are:

  1. itextsharp.dll
  2. itextsharp.xmlworker.dll

Once you have referenced these two libraries you are ready to start coding.

In this article I provide a fully working example in both C# and VB.NET. Each example consists of a report page that outputs a simple table, and the main PDF generation page. See the explanation below for further details.

Just to note: if you are interested in further information about iTextSharp then please have a look at the collection of articles I’ve written that cover using iTextSharp for .NET PDF generation.

Starting your Reports

In this article I will show how to take a report Web page written in ASP.NET and save this to the Web server as a PDF file that the user can be redirected to. This is basic functionality, but definitely useful! If you don’t want to keep a physical copy on your Server, you can simply update the code to remove the line to save the file, and then stream the document directly to the user.

Keep in mind when writing your Web report that you can use CSS, but make sure to test your report to make sure your formatting has translated correctly.

For this example you will need two Web pages.

  1. The first is your Web report that you want to export to PDF.
  2. The second is a Web page from which your users can click a button in order to generate the PDF from your Web report.

In the example code that I am providing at the end of this article, the test Web report is simply a HashTable that is databound to a GridView. For clarity, I have named the test report TestReport.aspx or CSharpTestReport.aspx for the C# version.

The page that reads the report page and converts it into a PDF file on the server is called TestGenPDF.aspx or CSharpTestGenPDF.aspx for the C# version. All of the actual iTextSharp code is written on this page.

Reviewing the iTextSharp Code

To begin working with the iTextSharp tool, you will need to import the library files from your newly referenced iTextSharp DLLs. For a basic Web page to PDF conversion you will need the following namespaces:

  • iTextSharp.tool.xml
  • iTextSharp.text.pdf
  • System.IO

For starters, you will need to include the System.IO library in order to manipulate the files on your Web server’s file system. This includes actually creating and writing the new PDF report file to a sub-folder of your Web site called Reports.

The following line tells .NET to run the Web plage and to store the resulting page inside of a StringWriter object:

 Server.Execute("TestReport.aspx", strWriter)

The iTextSharp.tool.xml library is required in order to use the XMLWorkerHelper object. In the example code below this is necessary for the following line to run correctly:

XMLWorkerHelper.GetInstance().ParseXHtml(pdfWrite, docWorkingDocument, srdDocToString)

Furthermore, the iTextSharp.text.pdf library is needed for the calls to the iTextSharp PdfWriter object which receives the stream of text that needs to be written out in PDF format in the following lines:

 Dim pdfWrite As PdfWriter
 pdfWrite = PdfWriter.GetInstance(docWorkingDocument, New FileStream(strFileName, FileMode.Create))

The sample code also makes use of the iTextSharp Document object. You can either import this separately, or in the case of the sample code below I simply referenced it directly in code to avoid any sort of confusion about what sort of document is being generated.

Dim docWorkingDocument As iTextSharp.text.Document = New iTextSharp.text.Document(iTextSharp.text.PageSize.A4.Rotate(), 1, 1, 0, 0)

As you can see, when instantiating the iTextSharp document you are also able to set various properties of the document. This includes the layout of the report in the PDF document as well as the PDF document margins.

From the line of code above you can see that I have set the example document that we are working with to generate in landscape layout.

Once this page has run the report page and output the PDF file to the Web server, it uses JavaScript to point the user’s browser to the newly generated file as follows:

Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), "myscript", "window.open('reports/" & strFileShortName & "','_blank','location=0,menubar=0,status=0,titlebar=0,toolbar=0');", True)

The reason for using JavaScript instead of a simple Server Redirect is that I wish the PDF to appear in a new browser window rather than replacing the main browser window. This is a handy trick to use since opening a new window is not possible using a Server redirect.

An alternate method would be to stream the PDF directly to the user’s browser, but this can have problems as well. For example when streaming the PDF, if any extra Bytes are somehow included, Adobe will attempt to correct the PDF, and then the user will be prompted to save the streamed PDF if they click the close button.

Summary

Below I’m providing a fully working example of the iTextSharp functionality I described in this article. I provide a C# and a VB.NET version of the example.

This working example in either language consists of two pages TestGenPdf.aspx and TestReport.aspx. TestReport.aspx generates an example report as an HTML table based on a GridView control. The iTextSharp PDF functionality is contained in the TestGenPdf.aspx example page.

If you are interested in related articles, I have posted an article reviewing some of the features of the iTextSharp HTMLWorker object.

As always, please feel free to post any questions or comments related to this article in the comments section at the end of this post.

THE EXAMPLE IN C#

Here is the example written in C#. Note that as explained earlier, CSharpTestGenPdf.aspx is the main page that will run and export to PDF the report coded on the second page called CSharpTestReport.aspx.

CSharpTestGenPdf.aspx

This is the main PDF generation page that calls the report page (called CSharpTestReport.aspx). Note that I also added a line to import a logo image from an Images folder to this example. You can leave this line out if you don’t want to add an image.


<%@ Page Language="C#" %>
<%@ Import Namespace="iTextSharp.tool.xml" %>
<%@ Import Namespace="iTextSharp.text.pdf" %>
<%@ Import Namespace="System.IO" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
 protected void Button1_Click(object sender, System.EventArgs e)
 {
 string strHtml = null;
 MemoryStream memStream = new MemoryStream();
 StringWriter strWriter = new StringWriter();
 Server.Execute("CSharpTestReport.aspx", strWriter);
 strHtml = strWriter.ToString();
 strWriter.Close();
 strWriter.Dispose();
 iTextSharp.text.Image addLogo = default(iTextSharp.text.Image);
 addLogo = iTextSharp.text.Image.GetInstance(Server.MapPath("Images") + "/mylogo.gif");
 string strFileShortName = "test" + DateTime.Now.Ticks + ".pdf";
 string strFileName = HttpContext.Current.Server.MapPath("reports\\" + strFileShortName);
 iTextSharp.text.Document docWorkingDocument = new iTextSharp.text.Document(iTextSharp.text.PageSize.A4.Rotate(), 1, 1, 0, 0);
 StringReader srdDocToString = null;
 try
 {
 PdfWriter pdfWrite = default(PdfWriter);
 pdfWrite = PdfWriter.GetInstance(docWorkingDocument, new FileStream(strFileName, FileMode.Create));
 srdDocToString = new StringReader(strHtml);
 docWorkingDocument.Open();
 addLogo.ScaleToFit(128, 37);
 addLogo.Alignment = iTextSharp.text.Image.ALIGN_RIGHT;
 docWorkingDocument.Add(addLogo);
 XMLWorkerHelper.GetInstance().ParseXHtml(pdfWrite, docWorkingDocument, srdDocToString);
 }
 catch (Exception ex)
 {
 Response.Write(ex.Message);
 }
 finally
 {
 if ((docWorkingDocument != null))
 {
 docWorkingDocument.Close();
 docWorkingDocument.Dispose();
 }
 if ((srdDocToString != null))
 {
 srdDocToString.Close();
 srdDocToString.Dispose();
 }
 }
 Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "myscript", "window.open('reports/" + strFileShortName + "','_blank','location=0,menubar=0,status=0,titlebar=0,toolbar=0');", true);
 }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
 <title></title>
</head>
<body>
 <form id="form1" runat="server">
 <div>
 <asp:Button ID="Button1" runat="server" Text="Generate PDF" OnClick="Button1_Click" />
 </div>
 </form>
</body>
</html>

CSharpTestReport.aspx

This is the report page that outputs a simple GridView control in table format.


<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
 Hashtable m_testData = new Hashtable();
 protected void Page_Load(object sender, System.EventArgs e)
 {
 m_testData.Add("test_1_id", "test_1_value");
 m_testData.Add("test_2_id", "test_2_value");
 m_testData.Add("test_3_id", "test_3_value");
 m_testData.Add("test_4_id", "test_4_value");
 GridView1.DataSource = m_testData;
 GridView1.DataBind();
 }
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
 <title></title>
</head>
<body>
 <form id="form1" runat="server">
 <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
 <Columns>
 <asp:TemplateField HeaderText="key">
 <EditItemTemplate>
 <asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("key") %>'></asp:TextBox>
 </EditItemTemplate>
 <ItemTemplate>
 <asp:Label ID="Label1" runat="server" Text='<%# Bind("key") %>'></asp:Label>
 </ItemTemplate>
 </asp:TemplateField>
 <asp:TemplateField HeaderText="value">
 <EditItemTemplate>
 <asp:TextBox ID="TextBox2" runat="server" Text='<%# Bind("value") %>'></asp:TextBox>
 </EditItemTemplate>
 <ItemTemplate>
 <asp:Label ID="Label2" runat="server" Text='<%# Bind("value") %>'></asp:Label>
 </ItemTemplate>
 </asp:TemplateField>
 </Columns>
</asp:GridView>
 </form>
</body>
</html>

THE EXAMPLE IN VB.NET

Here is the exact same example written in VB.NET. Unlike the C# example above, I do not import a logo image into the PDF.

TestGenPdf.aspx

This is the main PDF generation page that calls the report page (called TestReport.aspx).

<%@ Page Language="VB" %>
<%@ Import Namespace="iTextSharp.tool.xml" %>
<%@ Import Namespace="iTextSharp.text.pdf" %>
<%@ Import Namespace="System.IO" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
 Protected Sub Button1_Click(sender As Object, e As System.EventArgs)
 Dim strHtml As String
 Dim memStream As New MemoryStream()
 Dim strWriter As New StringWriter()
 Server.Execute("TestReport.aspx", strWriter)
 strHtml = strWriter.ToString()
 strWriter.Close()
 strWriter.Dispose()
 Dim strFileShortName As String = "test" & DateTime.Now.Ticks & ".pdf"
 Dim strFileName As String = HttpContext.Current.Server.MapPath("reports\" & strFileShortName)
 Dim docWorkingDocument As iTextSharp.text.Document = New iTextSharp.text.Document(iTextSharp.text.PageSize.A4.Rotate(), 1, 1, 0, 0)
 Dim srdDocToString As StringReader = Nothing
 Try
 Dim pdfWrite As PdfWriter
 pdfWrite = PdfWriter.GetInstance(docWorkingDocument, New FileStream(strFileName, FileMode.Create))
 srdDocToString = New StringReader(strHtml)
 docWorkingDocument.Open()
 XMLWorkerHelper.GetInstance().ParseXHtml(pdfWrite, docWorkingDocument, srdDocToString)
 Catch ex As Exception
 Response.Write(ex.Message)
 Finally
 If Not docWorkingDocument Is Nothing Then
 docWorkingDocument.Close()
 docWorkingDocument.Dispose()
 End If
 If Not srdDocToString Is Nothing Then
 srdDocToString.Close()
 srdDocToString.Dispose()
 End If
 End Try

 Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), "myscript", "window.open('reports/" & strFileShortName & "','_blank','location=0,menubar=0,status=0,titlebar=0,toolbar=0');", True)

 End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
 <title></title>
</head>
<body>
 <form id="form1" runat="server">
 <div>
 <asp:Button ID="Button1" runat="server" Text="Generate PDF" OnClick="Button1_Click" />
 </div>
 </form>
</body>
</html>

TestReport.aspx

This is the report page that outputs a simple GridView control.

<%@ Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
 Dim m_testData As New Hashtable()
 Protected Sub Page_Load(sender As Object, e As System.EventArgs)
 m_testData.Add("test_1_id", "test_1_value")
 m_testData.Add("test_2_id", "test_2_value")
 m_testData.Add("test_3_id", "test_3_value")
 m_testData.Add("test_4_id", "test_4_value")
 GridView1.DataSource = m_testData
 GridView1.DataBind()
 End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
 <title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
 <Columns>
 <asp:TemplateField HeaderText="key">
 <EditItemTemplate>
 <asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("key") %>'></asp:TextBox>
 </EditItemTemplate>
 <ItemTemplate>
 <asp:Label ID="Label1" runat="server" Text='<%# Bind("key") %>'></asp:Label>
 </ItemTemplate>
 </asp:TemplateField>
 <asp:TemplateField HeaderText="value">
 <EditItemTemplate>
 <asp:TextBox ID="TextBox2" runat="server" Text='<%# Bind("value") %>'></asp:TextBox>
 </EditItemTemplate>
 <ItemTemplate>
 <asp:Label ID="Label2" runat="server" Text='<%# Bind("value") %>'></asp:Label>
 </ItemTemplate>
 </asp:TemplateField>
 </Columns>
</asp:GridView>
</form>
</body>
</html>

Advertisement

13 thoughts on “Generate a PDF from an ASP.NET Web Page using the iTextSharp XMLWorker Namespace”

  1. Hi, Justin
    Great article. I’m working just in the same task, but I’ve a problem with the parseXHtml method,
    i call the method this way:

    ‘ sr is an html string

    Dim document As New Document(iTextSharp.text.PageSize.A4, 1, 1, 0, 0)
    Dim writer As PdfWriter
    writer = PdfWriter.getInstance(document, New System.IO.FileStream(Request.MapPath(“\”)+”Test.pdf”, System.IO.FileMode.Create))
    document.Open()
    Dim sr2 As new System.IO.StringReader(sr)

    XMLWorkerHelper.getInstance().parseXHtml(writer, document, sr2)

    and compilation says:

    BC30311: Value of type ‘iTextSharp.text.Document’ cannot be converted to ‘System.IO.Stream’

    I’ve revied everything and I can’t find the solution,
    i check the dll versions

    itextsharp.dll 5.3.5.0
    itextsharp.xmlworker.dll 5.4.2.0

    it seems like i’m using a java version (or something similar) instead the xmlworker version you’re using
    but i can’t find a different version

    Thanks in advance and great work

    Kiko Fdez
    Spain

    1. Wondering if you solved this issue as I have run across the same thing. Any information would be greatly appreciated :)

  2. Great tips…..persons who are not very tech familiar they can use carious software available online. Expert PDF is one of best software i used for converting html to pdf asp.net.

  3. Justin, although this article has been around for a while, I read it today and followed the example and I was successfully able to generate PDF (for the first time ever!!).

    Not to mention, that I’ve been trying to generate PDF from HTML since last few days and I didn’t find any article/example that worked for me. I gave a try to wkhtmlx0 and wasted more than a day with no resolution. This morning I decided to give iTextSharp a try and looked for articles that give an implementation example. After following your article, in few hours, I got it to work as per my requirement.

    Thanks a lot for the helpful article. Keep up the good work.

    If I may give a suggestion, it would be very helpful to rewrite the article and separate markup from c# code (with separate code behind page aspx.cs). And more importantly rather than explaining only iTextSharp specific code, do a step by step explanation of the entire code. It would help newbies.

    1. Hi Rohit, thanks very much for your feedback! I’m happy to hear that the article was useful to you and that you were able to generate a PDF using iTextSharp. I will take your advice and put together a step by step explanation of the code. Cheers!

  4. Hey Justin, great example. I can’t seem to modify your example to export the page I’m on to a pdf. The closest I’ve gotten has been changing TestReport.aspx to Request.RawUrl and attempting to call the PDF generation from the code behind. Can you help provide the solution for exporting the current page?

    1. Have You tries Zetpdf.com? It’s really convenient and simple to use. All in one website I would say.

  5. But when I use both the DLLs i get this error “Could not load file or assembly ‘itextsharp, Version=5.5.5.0, Culture=neutral, PublicKeyToken=8354ae6d2174ddca’ or one of its dependencies. The located assembly’s manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s