Skip to footer content
MIGRATION GUIDES

How to Migrate from HiQPdf to IronPDF in C#

HiQPdf is a commercial HTML-to-PDF library with several concerning limitations that affect production applications:

  1. Restrictive "Free" Version: The free version imposes a 3-page limit with intrusive watermarks—essentially unusable for production workloads requiring complete document generation.

  2. Older WebKit Engine: HiQPdf uses an older WebKit-based rendering engine that struggles with modern JavaScript frameworks like React, Angular, and Vue.

  3. Unclear .NET Core Support: Documentation doesn't explicitly clarify .NET Core / .NET 5+ support, creating uncertainty for modern application development.

  4. Fragmented Packages: Multiple NuGet packages for different platforms (HiQPdf, HiQPdf.Free, HiQPdf.NetCore, HiQPdf.NetCore.x64, HiQPdf.Client) complicate dependency management.

  5. Complex API: Requires verbose configuration through Document, Header, Footer property chains rather than fluent, intuitive methods.

  6. Limited JavaScript Support: The WebKit engine has challenges rendering content generated by modern JavaScript frameworks and complex dynamic layouts.

HiQPdf vs IronPDF Comparison

AspectHiQPdfIronPDF
Rendering EngineWebKit-based (older)Modern Chromium
Free Tier3-page limit + watermark30-day full trial
Modern JS SupportLimitedFull (React, Angular, Vue)
.NET Core/5+ SupportMultiple packages neededSingle unified package
API DesignComplex property chainsClean fluent API
CSS3 SupportPartialFull support
DocumentationFragmentedComprehensive
NuGet PackageMultiple variantsSingle package

For teams planning .NET 10 and C# 14 adoption through 2025 and 2026, IronPDF provides a future-proof foundation with documented support for the latest .NET versions and a modern Chromium rendering engine.


Migration Complexity Assessment

Estimated Effort by Feature

FeatureMigration ComplexityNotes
HTML to PDFVery LowDirect method replacement
URL to PDFVery LowDirect method replacement
Merge PDFsLowDifferent merge approach
Headers/FootersMediumPlaceholder syntax change
Page Size/MarginsLowSame units (mm)
TriggerMode/DelaysLowProperty mapping

Paradigm Shift

The fundamental shift in this HiQPdf migration is from property chain configuration to fluent rendering options:

HiQPdf:   converter.Document.Header.Height = 50;
          converter.Document.Header.Add(new HtmlToPdfVariableElement(...));

IronPDF:  renderer.RenderingOptions.TextHeader = new TextHeaderFooter() { ... };

Before You Start

Prerequisites

  1. .NET Version: IronPDF supports .NET Framework 4.6.2+ and .NET Core 3.1+ / .NET 5/6/7/8/9+
  2. License Key: Obtain your IronPDF license key from ironpdf.com
  3. Remove HiQPdf: Plan to remove all HiQPdf NuGet package variants

Identify All HiQPdf Usage

# Find HiQPdf namespace usage
grep -r "using HiQPdf\|HtmlToPdf\|PdfDocument" --include="*.cs" .

# Find header/footer usage
grep -r "\.Header\.\|\.Footer\.\|HtmlToPdfVariableElement" --include="*.cs" .

# Find placeholder syntax
grep -r "CrtPage\|PageCount" --include="*.cs" .

# Find NuGet references
grep -r "HiQPdf" --include="*.csproj" .
# Find HiQPdf namespace usage
grep -r "using HiQPdf\|HtmlToPdf\|PdfDocument" --include="*.cs" .

# Find header/footer usage
grep -r "\.Header\.\|\.Footer\.\|HtmlToPdfVariableElement" --include="*.cs" .

# Find placeholder syntax
grep -r "CrtPage\|PageCount" --include="*.cs" .

# Find NuGet references
grep -r "HiQPdf" --include="*.csproj" .
SHELL

NuGet Package Changes

# Remove all HiQPdf variants
dotnet remove package HiQPdf
dotnet remove package HiQPdf.Free
dotnet remove package HiQPdf.NetCore
dotnet remove package HiQPdf.NetCore.x64
dotnet remove package HiQPdf.Client

# Install IronPDF (single package for all platforms)
dotnet add package IronPdf
# Remove all HiQPdf variants
dotnet remove package HiQPdf
dotnet remove package HiQPdf.Free
dotnet remove package HiQPdf.NetCore
dotnet remove package HiQPdf.NetCore.x64
dotnet remove package HiQPdf.Client

# Install IronPDF (single package for all platforms)
dotnet add package IronPdf
SHELL

Quick Start Migration

Step 1: Update License Configuration

Before (HiQPdf):

HtmlToPdf converter = new HtmlToPdf();
converter.SerialNumber = "HIQPDF-SERIAL-NUMBER";
HtmlToPdf converter = new HtmlToPdf();
converter.SerialNumber = "HIQPDF-SERIAL-NUMBER";
$vbLabelText   $csharpLabel

After (IronPDF):

// Set globally at application startup
IronPdf.License.LicenseKey = "YOUR-IRONPDF-LICENSE-KEY";
// Set globally at application startup
IronPdf.License.LicenseKey = "YOUR-IRONPDF-LICENSE-KEY";
$vbLabelText   $csharpLabel

Step 2: Update Namespace Imports

// Before (HiQPdf)
using HiQPdf;

// After (IronPDF)
using IronPdf;
using IronPdf.Rendering;
// Before (HiQPdf)
using HiQPdf;

// After (IronPDF)
using IronPdf;
using IronPdf.Rendering;
$vbLabelText   $csharpLabel

Complete API Reference

Main Class Mapping

HiQPdf ClassIronPDF ClassNotes
HtmlToPdfChromePdfRendererMain converter class
PdfDocumentPdfDocumentSame name, different namespace
HtmlToPdfVariableElementTextHeaderFooter or HtmlHeaderFooterHeader/footer content

Conversion Method Mapping

HiQPdf MethodIronPDF MethodNotes
ConvertHtmlToMemory(html, baseUrl)RenderHtmlAsPdf(html)Returns PdfDocument
ConvertUrlToMemory(url)RenderUrlAsPdf(url)Returns PdfDocument
File.WriteAllBytes(path, bytes)pdf.SaveAs(path)Direct save method

PDF Document Method Mapping

HiQPdf MethodIronPDF MethodNotes
PdfDocument.FromFile(path)PdfDocument.FromFile(path)Same method name
document1.AddDocument(document2)PdfDocument.Merge(pdf1, pdf2)Static merge method
document.WriteToFile(path)pdf.SaveAs(path)Different method name
HiQPdf PlaceholderIronPDF PlaceholderDescription
{CrtPage}{page}Current page number
{PageCount}{total-pages}Total page count

Code Migration Examples

Example 1: HTML to PDF Conversion

Before (HiQPdf):

// NuGet: Install-Package HiQPdf
using HiQPdf;
using System;

class Program
{
    static void Main()
    {
        HtmlToPdf htmlToPdfConverter = new HtmlToPdf();
        byte[] pdfBuffer = htmlToPdfConverter.ConvertUrlToMemory("https://example.com");
        System.IO.File.WriteAllBytes("output.pdf", pdfBuffer);

        // Convert HTML string
        string html = "<h1>Hello World</h1><p>This is a PDF document.</p>";
        byte[] pdfFromHtml = htmlToPdfConverter.ConvertHtmlToMemory(html, "");
        System.IO.File.WriteAllBytes("fromhtml.pdf", pdfFromHtml);
    }
}
// NuGet: Install-Package HiQPdf
using HiQPdf;
using System;

class Program
{
    static void Main()
    {
        HtmlToPdf htmlToPdfConverter = new HtmlToPdf();
        byte[] pdfBuffer = htmlToPdfConverter.ConvertUrlToMemory("https://example.com");
        System.IO.File.WriteAllBytes("output.pdf", pdfBuffer);

        // Convert HTML string
        string html = "<h1>Hello World</h1><p>This is a PDF document.</p>";
        byte[] pdfFromHtml = htmlToPdfConverter.ConvertHtmlToMemory(html, "");
        System.IO.File.WriteAllBytes("fromhtml.pdf", pdfFromHtml);
    }
}
$vbLabelText   $csharpLabel

After (IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderUrlAsPdf("https://example.com");
        pdf.SaveAs("output.pdf");

        // Convert HTML string
        string html = "<h1>Hello World</h1><p>This is a PDF document.</p>";
        var pdfFromHtml = renderer.RenderHtmlAsPdf(html);
        pdfFromHtml.SaveAs("fromhtml.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderUrlAsPdf("https://example.com");
        pdf.SaveAs("output.pdf");

        // Convert HTML string
        string html = "<h1>Hello World</h1><p>This is a PDF document.</p>";
        var pdfFromHtml = renderer.RenderHtmlAsPdf(html);
        pdfFromHtml.SaveAs("fromhtml.pdf");
    }
}
$vbLabelText   $csharpLabel

The HiQPdf approach requires creating an HtmlToPdf instance, calling ConvertUrlToMemory() or ConvertHtmlToMemory() to get a byte array, then manually writing bytes to a file. IronPDF's ChromePdfRenderer returns a PdfDocument object with a direct SaveAs() method, eliminating the manual file writing step. The modern Chromium engine also provides better rendering for complex HTML/CSS/JavaScript content. See the HTML to PDF documentation for additional rendering options.

Example 2: Merge Multiple PDFs

Before (HiQPdf):

// NuGet: Install-Package HiQPdf
using HiQPdf;
using System;

class Program
{
    static void Main()
    {
        // Create first PDF
        HtmlToPdf converter1 = new HtmlToPdf();
        byte[] pdf1 = converter1.ConvertHtmlToMemory("<h1>First Document</h1>", "");
        System.IO.File.WriteAllBytes("doc1.pdf", pdf1);

        // Create second PDF
        HtmlToPdf converter2 = new HtmlToPdf();
        byte[] pdf2 = converter2.ConvertHtmlToMemory("<h1>Second Document</h1>", "");
        System.IO.File.WriteAllBytes("doc2.pdf", pdf2);

        // Merge PDFs
        PdfDocument document1 = PdfDocument.FromFile("doc1.pdf");
        PdfDocument document2 = PdfDocument.FromFile("doc2.pdf");
        document1.AddDocument(document2);
        document1.WriteToFile("merged.pdf");
    }
}
// NuGet: Install-Package HiQPdf
using HiQPdf;
using System;

class Program
{
    static void Main()
    {
        // Create first PDF
        HtmlToPdf converter1 = new HtmlToPdf();
        byte[] pdf1 = converter1.ConvertHtmlToMemory("<h1>First Document</h1>", "");
        System.IO.File.WriteAllBytes("doc1.pdf", pdf1);

        // Create second PDF
        HtmlToPdf converter2 = new HtmlToPdf();
        byte[] pdf2 = converter2.ConvertHtmlToMemory("<h1>Second Document</h1>", "");
        System.IO.File.WriteAllBytes("doc2.pdf", pdf2);

        // Merge PDFs
        PdfDocument document1 = PdfDocument.FromFile("doc1.pdf");
        PdfDocument document2 = PdfDocument.FromFile("doc2.pdf");
        document1.AddDocument(document2);
        document1.WriteToFile("merged.pdf");
    }
}
$vbLabelText   $csharpLabel

After (IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();

        // Create first PDF
        var pdf1 = renderer.RenderHtmlAsPdf("<h1>First Document</h1>");
        pdf1.SaveAs("doc1.pdf");

        // Create second PDF
        var pdf2 = renderer.RenderHtmlAsPdf("<h1>Second Document</h1>");
        pdf2.SaveAs("doc2.pdf");

        // Merge PDFs
        var merged = PdfDocument.Merge(pdf1, pdf2);
        merged.SaveAs("merged.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();

        // Create first PDF
        var pdf1 = renderer.RenderHtmlAsPdf("<h1>First Document</h1>");
        pdf1.SaveAs("doc1.pdf");

        // Create second PDF
        var pdf2 = renderer.RenderHtmlAsPdf("<h1>Second Document</h1>");
        pdf2.SaveAs("doc2.pdf");

        // Merge PDFs
        var merged = PdfDocument.Merge(pdf1, pdf2);
        merged.SaveAs("merged.pdf");
    }
}
$vbLabelText   $csharpLabel

The HiQPdf approach requires loading documents from files using PdfDocument.FromFile(), calling AddDocument() on the first document to append the second, then using WriteToFile() to save. IronPDF provides a cleaner static PdfDocument.Merge() method that accepts multiple PdfDocument objects directly—no intermediate file operations required. Learn more about merging and splitting PDFs.

Example 3: PDF Headers and Footers with Page Numbers

Before (HiQPdf):

// NuGet: Install-Package HiQPdf
using HiQPdf;
using System;

class Program
{
    static void Main()
    {
        HtmlToPdf htmlToPdfConverter = new HtmlToPdf();

        // Add header
        htmlToPdfConverter.Document.Header.Height = 50;
        HtmlToPdfVariableElement headerHtml = new HtmlToPdfVariableElement("<div style='text-align:center'>Page Header</div>", "");
        htmlToPdfConverter.Document.Header.Add(headerHtml);

        // Add footer with page number
        htmlToPdfConverter.Document.Footer.Height = 50;
        HtmlToPdfVariableElement footerHtml = new HtmlToPdfVariableElement("<div style='text-align:center'>Page {CrtPage} of {PageCount}</div>", "");
        htmlToPdfConverter.Document.Footer.Add(footerHtml);

        byte[] pdfBuffer = htmlToPdfConverter.ConvertHtmlToMemory("<h1>Document with Headers and Footers</h1>", "");
        System.IO.File.WriteAllBytes("header-footer.pdf", pdfBuffer);
    }
}
// NuGet: Install-Package HiQPdf
using HiQPdf;
using System;

class Program
{
    static void Main()
    {
        HtmlToPdf htmlToPdfConverter = new HtmlToPdf();

        // Add header
        htmlToPdfConverter.Document.Header.Height = 50;
        HtmlToPdfVariableElement headerHtml = new HtmlToPdfVariableElement("<div style='text-align:center'>Page Header</div>", "");
        htmlToPdfConverter.Document.Header.Add(headerHtml);

        // Add footer with page number
        htmlToPdfConverter.Document.Footer.Height = 50;
        HtmlToPdfVariableElement footerHtml = new HtmlToPdfVariableElement("<div style='text-align:center'>Page {CrtPage} of {PageCount}</div>", "");
        htmlToPdfConverter.Document.Footer.Add(footerHtml);

        byte[] pdfBuffer = htmlToPdfConverter.ConvertHtmlToMemory("<h1>Document with Headers and Footers</h1>", "");
        System.IO.File.WriteAllBytes("header-footer.pdf", pdfBuffer);
    }
}
$vbLabelText   $csharpLabel

After (IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();

        // Configure header and footer
        renderer.RenderingOptions.TextHeader = new TextHeaderFooter()
        {
            CenterText = "Page Header",
            FontSize = 12
        };

        renderer.RenderingOptions.TextFooter = new TextHeaderFooter()
        {
            CenterText = "Page {page} of {total-pages}",
            FontSize = 10
        };

        var pdf = renderer.RenderHtmlAsPdf("<h1>Document with Headers and Footers</h1>");
        pdf.SaveAs("header-footer.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();

        // Configure header and footer
        renderer.RenderingOptions.TextHeader = new TextHeaderFooter()
        {
            CenterText = "Page Header",
            FontSize = 12
        };

        renderer.RenderingOptions.TextFooter = new TextHeaderFooter()
        {
            CenterText = "Page {page} of {total-pages}",
            FontSize = 10
        };

        var pdf = renderer.RenderHtmlAsPdf("<h1>Document with Headers and Footers</h1>");
        pdf.SaveAs("header-footer.pdf");
    }
}
$vbLabelText   $csharpLabel

The HiQPdf approach requires setting Document.Header.Height, creating HtmlToPdfVariableElement objects, and calling Add() on the header/footer sections. Page number placeholders use {CrtPage} and {PageCount} syntax. IronPDF provides a cleaner TextHeaderFooter configuration with CenterText properties and different placeholder syntax: {page} and {total-pages}. See the headers and footers documentation for additional options including HTML-based headers.


Critical Migration Notes

Placeholder Syntax Change

The most important change for documents with page numbers is the placeholder syntax:

// HiQPdf placeholders
"Page {CrtPage} of {PageCount}"

// IronPDF placeholders
"Page {page} of {total-pages}"
// HiQPdf placeholders
"Page {CrtPage} of {PageCount}"

// IronPDF placeholders
"Page {page} of {total-pages}"
$vbLabelText   $csharpLabel

Complete placeholder mapping:

  • {CrtPage}{page}
  • {PageCount}{total-pages}

Merge Method Difference

HiQPdf modifies the first document in place:

// HiQPdf: Modifies document1
document1.AddDocument(document2);
document1.WriteToFile("merged.pdf");
// HiQPdf: Modifies document1
document1.AddDocument(document2);
document1.WriteToFile("merged.pdf");
$vbLabelText   $csharpLabel

IronPDF returns a new merged document:

// IronPDF: Returns new document
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("merged.pdf");
// IronPDF: Returns new document
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("merged.pdf");
$vbLabelText   $csharpLabel

No 3-Page Limit

HiQPdf's free version caps output at 3 pages with watermarks. IronPDF generates complete documents without artificial limitations during the trial period.

Reuse ChromePdfRenderer

Unlike HiQPdf where you might create new HtmlToPdf instances for each conversion, IronPDF's ChromePdfRenderer should be reused:

// IronPDF: Create once, reuse
var renderer = new ChromePdfRenderer();
var pdf1 = renderer.RenderHtmlAsPdf(html1);
var pdf2 = renderer.RenderHtmlAsPdf(html2);
// IronPDF: Create once, reuse
var renderer = new ChromePdfRenderer();
var pdf1 = renderer.RenderHtmlAsPdf(html1);
var pdf2 = renderer.RenderHtmlAsPdf(html2);
$vbLabelText   $csharpLabel

Troubleshooting

Issue 1: HtmlToPdf Not Found

Problem: HtmlToPdf class doesn't exist in IronPDF.

Solution: Replace with ChromePdfRenderer:

// HiQPdf
HtmlToPdf htmlToPdfConverter = new HtmlToPdf();

// IronPDF
var renderer = new ChromePdfRenderer();
// HiQPdf
HtmlToPdf htmlToPdfConverter = new HtmlToPdf();

// IronPDF
var renderer = new ChromePdfRenderer();
$vbLabelText   $csharpLabel

Issue 2: ConvertHtmlToMemory Not Found

Problem: ConvertHtmlToMemory() method doesn't exist.

Solution: Use RenderHtmlAsPdf():

// HiQPdf
byte[] pdfBytes = converter.ConvertHtmlToMemory(html, "");

// IronPDF
var pdf = renderer.RenderHtmlAsPdf(html);
byte[] pdfBytes = pdf.BinaryData;
// HiQPdf
byte[] pdfBytes = converter.ConvertHtmlToMemory(html, "");

// IronPDF
var pdf = renderer.RenderHtmlAsPdf(html);
byte[] pdfBytes = pdf.BinaryData;
$vbLabelText   $csharpLabel

Issue 3: Page Number Placeholders Not Working

Problem: {CrtPage} and {PageCount} appear literally in output.

Solution: Update to IronPDF placeholder syntax:

// HiQPdf syntax (won't work)
"Page {CrtPage} of {PageCount}"

// IronPDF syntax
"Page {page} of {total-pages}"
// HiQPdf syntax (won't work)
"Page {CrtPage} of {PageCount}"

// IronPDF syntax
"Page {page} of {total-pages}"
$vbLabelText   $csharpLabel

Issue 4: HtmlToPdfVariableElement Not Found

Problem: HtmlToPdfVariableElement class doesn't exist.

Solution: Use TextHeaderFooter or HtmlHeaderFooter:

// HiQPdf
HtmlToPdfVariableElement headerHtml = new HtmlToPdfVariableElement("<div>Header</div>", "");
converter.Document.Header.Add(headerHtml);

// IronPDF
renderer.RenderingOptions.TextHeader = new TextHeaderFooter()
{
    CenterText = "Header",
    FontSize = 12
};
// HiQPdf
HtmlToPdfVariableElement headerHtml = new HtmlToPdfVariableElement("<div>Header</div>", "");
converter.Document.Header.Add(headerHtml);

// IronPDF
renderer.RenderingOptions.TextHeader = new TextHeaderFooter()
{
    CenterText = "Header",
    FontSize = 12
};
$vbLabelText   $csharpLabel

Migration Checklist

Pre-Migration

  • Inventory all HiQPdf API calls in codebase
  • Document current page sizes, margins, and settings
  • Identify header/footer configurations and placeholders
  • Obtain IronPDF license key
  • Test IronPDF in development environment

Code Migration

  • Remove all HiQPdf NuGet packages (all variants)
  • Install IronPdf NuGet package: dotnet add package IronPdf
  • Update namespace imports
  • Replace HtmlToPdf with ChromePdfRenderer
  • Convert ConvertHtmlToMemory() to RenderHtmlAsPdf()
  • Convert ConvertUrlToMemory() to RenderUrlAsPdf()
  • Update header/footer placeholders ({CrtPage}{page}, {PageCount}{total-pages})
  • Replace HtmlToPdfVariableElement with TextHeaderFooter
  • Update merge operations (AddDocumentPdfDocument.Merge)
  • Add license key initialization at startup

Testing

  • Test HTML to PDF conversion
  • Test URL to PDF conversion
  • Verify header/footer rendering
  • Verify page number placeholders
  • Test PDF merging
  • Test JavaScript-heavy pages (now supported with Chromium)

Post-Migration

  • Remove HiQPdf serial number from configuration
  • Update documentation
  • Monitor for any rendering differences

Curtis Chau
Technical Writer

Curtis Chau holds a Bachelor’s degree in Computer Science (Carleton University) and specializes in front-end development with expertise in Node.js, TypeScript, JavaScript, and React. Passionate about crafting intuitive and aesthetically pleasing user interfaces, Curtis enjoys working with modern frameworks and creating well-structured, visually appealing manuals.

...

Read More