How to Migrate from QuestPDF to IronPDF in C#
Full Comparison
Looking for a detailed feature-by-feature breakdown? See how IronPDF stacks up against QuestPDF on pricing, HTML support, and licensing.
Migrating from QuestPDF to IronPDF moves your PDF generation workflow from a C# fluent layout API to a standard HTML/CSS-based approach with broader PDF manipulation capabilities. This guide provides a step-by-step migration path so you can leverage existing web skills, reuse HTML templates, and pick up features the QuestPDF core library does not include.
Why Migrate from QuestPDF to IronPDF
Understanding QuestPDF
QuestPDF is a modern, fluent API created specifically for generating PDFs programmatically in C#. Unlike libraries that offer comprehensive HTML-to-PDF conversion, the QuestPDF core library is limited to a programmatic layout API. QuestPDF excels in scenarios where developers need to generate documents from scratch using C# code, without relying on HTML.
The Community tier is free under MIT terms for individuals, non-profits, FOSS projects, and organizations with under $1M USD in annual gross revenue. Above that threshold, QuestPDF offers a Professional license starting at $999 (perpetual, up to 10 developers) and an Enterprise license at $2,999 (perpetual, organization-wide), which need to be factored into long-term planning.
The Core Problem: No HTML Engine in the Core Library
QuestPDF is sometimes recommended for HTML-to-PDF conversion, but the core library does not render HTML. A community-maintained QuestPDF.HTML extension covers a limited subset of HTML/CSS, but the core engine is programmatic-only and does not run a real browser engine. Teams that already have HTML/CSS templates typically have to rebuild them in the fluent API.
| Feature | QuestPDF | IronPDF |
|---|---|---|
| HTML-to-PDF (core) | Not supported (fluent API only) | Full support |
| HTML-to-PDF (extension) | Partial via QuestPDF.HTML (limited subset) |
Full support |
| CSS Styling | Limited via extension | Full CSS3 |
| Existing Templates | Must rebuild from scratch | Reuse HTML/CSS assets |
| Design Tool Compatibility | None | Any web design tool |
| Learning Curve | New fluent C# API | Web skills transfer |
| Layout Preview | Companion app | Preview in any browser |
| PDF Manipulation | Merge / extract / overlay / encrypt (Document Operations API, 2024.12.0+) | Merging, splitting, editing, signing |
IronPDF provides native HTML-to-PDF rendering that the QuestPDF core does not include, removing the need to manually reconstruct documents in C# code. It also covers PDF manipulation features such as merge, split, edit, secure, and digital signing — QuestPDF's Document Operations API (2024.12.0+) covers merge, page extraction, overlay/underlay, attachments and encryption, but not editing existing page content, OCR, or digital signatures.
The QuestPDF Licensing Model
QuestPDF's Community License (MIT terms) is free for individuals, non-profits, FOSS projects, and organizations under $1M USD in annual gross revenue. Above that threshold, you need a Professional license at $999 (perpetual, up to 10 developers) or Enterprise at $2,999 (perpetual, organization-wide). Because the trigger is your organization's revenue rather than seat count, this can change downstream client conversations as well as your own licensing.
IronPDF offers a per-developer commercial license: no revenue audits, no client licensing requirements, and predictable costs.
For teams adopting modern .NET versions, IronPDF provides per-developer licensing without revenue-based triggers and a standard HTML/CSS approach that leverages existing web development skills.
Before You Start
Prerequisites
- .NET Environment: .NET Framework 4.6.2+ or .NET Core 3.1+ / .NET 5/6/7/8/9+
- NuGet Access: Ability to install NuGet packages
- IronPDF License: Obtain your license key from ironpdf.com
NuGet Package Changes
# Remove QuestPDF
dotnet remove package QuestPDF
# Add IronPDF
dotnet add package IronPdf
# Remove QuestPDF
dotnet remove package QuestPDF
# Add IronPDF
dotnet add package IronPdf
License Configuration
// Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
' Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
Find QuestPDF Usage
# Find all QuestPDF usages in your codebase
grep -r "QuestPDF\|Document.Create\|\.GeneratePdf" --include="*.cs" .
# Find all QuestPDF usages in your codebase
grep -r "QuestPDF\|Document.Create\|\.GeneratePdf" --include="*.cs" .
Complete API Reference
Namespace Changes
// Before: QuestPDF
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
// After: IronPDF
using IronPdf;
// Before: QuestPDF
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
// After: IronPDF
using IronPdf;
Imports IronPdf
Core API Mappings
| QuestPDF Concept | IronPDF Equivalent |
|---|---|
Document.Create() |
new ChromePdfRenderer() |
.Page() |
RenderHtmlAsPdf() |
.Text() |
HTML <p>, <h1>, <span> |
.Bold() |
CSS font-weight: bold |
.FontSize(24) |
CSS font-size: 24px |
.Image() |
HTML <img src="..."> |
.Table() |
HTML <table> |
.Column() |
CSS display: flex; flex-direction: column |
.Row() |
CSS display: flex; flex-direction: row |
PageSizes.A4 |
RenderingOptions.PaperSize |
.Margin() |
RenderingOptions.Margin* |
.GeneratePdf() |
pdf.SaveAs() |
| N/A | PdfDocument.Merge() |
| N/A | PdfDocument.FromFile() |
| N/A | pdf.SecuritySettings |
Code Migration Examples
Example 1: Basic Document Creation (HTML-to-PDF)
Before (QuestPDF):
// NuGet: Install-Package QuestPDF
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
class Program
{
static void Main()
{
QuestPDF.Settings.License = LicenseType.Community;
Document.Create(container =>
{
container.Page(page =>
{
page.Size(PageSizes.A4);
page.Margin(2, Unit.Centimetre);
page.Content().Column(column =>
{
column.Item().Text("Hello World").FontSize(20).Bold();
column.Item().Text("This is a paragraph of text.");
});
});
}).GeneratePdf("output.pdf");
}
}
// NuGet: Install-Package QuestPDF
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
class Program
{
static void Main()
{
QuestPDF.Settings.License = LicenseType.Community;
Document.Create(container =>
{
container.Page(page =>
{
page.Size(PageSizes.A4);
page.Margin(2, Unit.Centimetre);
page.Content().Column(column =>
{
column.Item().Text("Hello World").FontSize(20).Bold();
column.Item().Text("This is a paragraph of text.");
});
});
}).GeneratePdf("output.pdf");
}
}
Imports QuestPDF.Fluent
Imports QuestPDF.Helpers
Imports QuestPDF.Infrastructure
Module Program
Sub Main()
QuestPDF.Settings.License = LicenseType.Community
Document.Create(Sub(container)
container.Page(Sub(page)
page.Size(PageSizes.A4)
page.Margin(2, Unit.Centimetre)
page.Content().Column(Sub(column)
column.Item().Text("Hello World").FontSize(20).Bold()
column.Item().Text("This is a paragraph of text.")
End Sub)
End Sub)
End Sub).GeneratePdf("output.pdf")
End Sub
End Module
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a paragraph of text.</p>");
pdf.SaveAs("output.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a paragraph of text.</p>");
pdf.SaveAs("output.pdf");
}
}
Imports IronPdf
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a paragraph of text.</p>")
pdf.SaveAs("output.pdf")
End Sub
End Class
This example shows the paradigm difference. QuestPDF requires learning its fluent API: Document.Create(), container.Page(), page.Content().Column(), column.Item().Text(), with styling via method chaining like .FontSize(20).Bold(). You must also set the license type with QuestPDF.Settings.License = LicenseType.Community.
IronPDF uses standard HTML that any web developer knows: <h1> for headings, <p> for paragraphs. No new layout DSL to learn. IronPDF's approach offers cleaner syntax and integrates with the rest of a modern .NET web stack. See the HTML to PDF documentation for comprehensive examples.
Example 2: Invoice Generation
Before (QuestPDF):
// NuGet: Install-Package QuestPDF
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
class Program
{
static void Main()
{
QuestPDF.Settings.License = LicenseType.Community;
Document.Create(container =>
{
container.Page(page =>
{
page.Size(PageSizes.A4);
page.Margin(2, Unit.Centimetre);
page.Content().Column(column =>
{
column.Item().Text("INVOICE").FontSize(24).Bold();
column.Item().Text("Invoice #: 12345").FontSize(12);
column.Item().PaddingTop(20);
column.Item().Text("Customer: John Doe");
column.Item().Text("Total: $100.00").Bold();
});
});
}).GeneratePdf("invoice.pdf");
}
}
// NuGet: Install-Package QuestPDF
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
class Program
{
static void Main()
{
QuestPDF.Settings.License = LicenseType.Community;
Document.Create(container =>
{
container.Page(page =>
{
page.Size(PageSizes.A4);
page.Margin(2, Unit.Centimetre);
page.Content().Column(column =>
{
column.Item().Text("INVOICE").FontSize(24).Bold();
column.Item().Text("Invoice #: 12345").FontSize(12);
column.Item().PaddingTop(20);
column.Item().Text("Customer: John Doe");
column.Item().Text("Total: $100.00").Bold();
});
});
}).GeneratePdf("invoice.pdf");
}
}
Imports QuestPDF.Fluent
Imports QuestPDF.Helpers
Imports QuestPDF.Infrastructure
Module Program
Sub Main()
QuestPDF.Settings.License = LicenseType.Community
Document.Create(Sub(container)
container.Page(Sub(page)
page.Size(PageSizes.A4)
page.Margin(2, Unit.Centimetre)
page.Content().Column(Sub(column)
column.Item().Text("INVOICE").FontSize(24).Bold()
column.Item().Text("Invoice #: 12345").FontSize(12)
column.Item().PaddingTop(20)
column.Item().Text("Customer: John Doe")
column.Item().Text("Total: $100.00").Bold()
End Sub)
End Sub)
End Sub).GeneratePdf("invoice.pdf")
End Sub
End Module
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var htmlContent = @"
<h1>INVOICE</h1>
<p>Invoice #: 12345</p>
<br/>
<p>Customer: John Doe</p>
<p><strong>Total: $100.00</strong></p>
";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("invoice.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var htmlContent = @"
<h1>INVOICE</h1>
<p>Invoice #: 12345</p>
<br/>
<p>Customer: John Doe</p>
<p><strong>Total: $100.00</strong></p>
";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("invoice.pdf");
}
}
Imports IronPdf
Class Program
Shared Sub Main()
Dim htmlContent As String = "
<h1>INVOICE</h1>
<p>Invoice #: 12345</p>
<br/>
<p>Customer: John Doe</p>
<p><strong>Total: $100.00</strong></p>
"
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(htmlContent)
pdf.SaveAs("invoice.pdf")
End Sub
End Class
QuestPDF uses .Column() and .Item() for layout, with .PaddingTop(20) for spacing. IronPDF uses standard HTML: <h1> for the title, <p> for paragraphs, <br/> for spacing, and <strong> for bold text.
The real advantage: with IronPDF, designers can create and modify HTML templates independently. With QuestPDF, every design change requires a C# developer to modify code. Learn more in our tutorials.
Example 3: Headers and Footers with Page Numbers
Before (QuestPDF):
// NuGet: Install-Package QuestPDF
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
class Program
{
static void Main()
{
QuestPDF.Settings.License = LicenseType.Community;
Document.Create(container =>
{
container.Page(page =>
{
page.Size(PageSizes.A4);
page.Margin(2, Unit.Centimetre);
page.Header().Text("Document Header").FontSize(14).Bold();
page.Content().Text("Main content of the document.");
page.Footer().AlignCenter().Text(text =>
{
text.Span("Page ");
text.CurrentPageNumber();
});
});
}).GeneratePdf("document.pdf");
}
}
// NuGet: Install-Package QuestPDF
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
class Program
{
static void Main()
{
QuestPDF.Settings.License = LicenseType.Community;
Document.Create(container =>
{
container.Page(page =>
{
page.Size(PageSizes.A4);
page.Margin(2, Unit.Centimetre);
page.Header().Text("Document Header").FontSize(14).Bold();
page.Content().Text("Main content of the document.");
page.Footer().AlignCenter().Text(text =>
{
text.Span("Page ");
text.CurrentPageNumber();
});
});
}).GeneratePdf("document.pdf");
}
}
Imports QuestPDF.Fluent
Imports QuestPDF.Helpers
Imports QuestPDF.Infrastructure
Module Program
Sub Main()
QuestPDF.Settings.License = LicenseType.Community
Document.Create(Sub(container)
container.Page(Sub(page)
page.Size(PageSizes.A4)
page.Margin(2, Unit.Centimetre)
page.Header().Text("Document Header").FontSize(14).Bold()
page.Content().Text("Main content of the document.")
page.Footer().AlignCenter().Text(Sub(text)
text.Span("Page ")
text.CurrentPageNumber()
End Sub)
End Sub)
End Sub).GeneratePdf("document.pdf")
End Sub
End Module
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var htmlContent = "<p>Main content of the document.</p>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.Header = new TextHeaderFooter()
{
CenterText = "Document Header",
FontSize = 14
};
pdf.Footer = new TextHeaderFooter()
{
CenterText = "Page {page}"
};
pdf.SaveAs("document.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var htmlContent = "<p>Main content of the document.</p>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.Header = new TextHeaderFooter()
{
CenterText = "Document Header",
FontSize = 14
};
pdf.Footer = new TextHeaderFooter()
{
CenterText = "Page {page}"
};
pdf.SaveAs("document.pdf");
}
}
Imports IronPdf
Class Program
Shared Sub Main()
Dim htmlContent As String = "<p>Main content of the document.</p>"
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(htmlContent)
pdf.Header = New TextHeaderFooter() With {
.CenterText = "Document Header",
.FontSize = 14
}
pdf.Footer = New TextHeaderFooter() With {
.CenterText = "Page {page}"
}
pdf.SaveAs("document.pdf")
End Sub
End Class
QuestPDF uses page.Header() and page.Footer() with fluent methods like .AlignCenter() and .CurrentPageNumber(). IronPDF uses TextHeaderFooter objects with properties like CenterText and FontSize. The {page} placeholder automatically inserts the current page number.
Critical Migration Notes
The Paradigm Shift
The core change is moving from a custom C# fluent layout API to standard HTML/CSS:
// QuestPDF: Fluent C# layout API
container.Page(page =>
{
page.Content().Column(column =>
{
column.Item().Text("Invoice").Bold().FontSize(24);
column.Item().Row(row =>
{
row.RelativeItem().Text("Customer:");
row.RelativeItem().Text("Acme Corp");
});
});
});
// IronPDF: Standard HTML/CSS
var html = @"
<div style='font-family: Arial; padding: 40px;'>
<h1 style='font-weight: bold; font-size: 24px;'>Invoice</h1>
<div style='display: flex; justify-content: space-between;'>
<span>Customer:</span>
<span>Acme Corp</span>
</div>
</div>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
// QuestPDF: Fluent C# layout API
container.Page(page =>
{
page.Content().Column(column =>
{
column.Item().Text("Invoice").Bold().FontSize(24);
column.Item().Row(row =>
{
row.RelativeItem().Text("Customer:");
row.RelativeItem().Text("Acme Corp");
});
});
});
// IronPDF: Standard HTML/CSS
var html = @"
<div style='font-family: Arial; padding: 40px;'>
<h1 style='font-weight: bold; font-size: 24px;'>Invoice</h1>
<div style='display: flex; justify-content: space-between;'>
<span>Customer:</span>
<span>Acme Corp</span>
</div>
</div>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
' QuestPDF: Fluent VB.NET layout API
container.Page(Sub(page)
page.Content().Column(Sub(column)
column.Item().Text("Invoice").Bold().FontSize(24)
column.Item().Row(Sub(row)
row.RelativeItem().Text("Customer:")
row.RelativeItem().Text("Acme Corp")
End Sub)
End Sub)
End Sub)
' IronPDF: Standard HTML/CSS
Dim html As String = "
<div style='font-family: Arial; padding: 40px;'>
<h1 style='font-weight: bold; font-size: 24px;'>Invoice</h1>
<div style='display: flex; justify-content: space-between;'>
<span>Customer:</span>
<span>Acme Corp</span>
</div>
</div>"
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
Layout Pattern Conversions
| QuestPDF Pattern | HTML/CSS Equivalent |
|---|---|
.Column() |
display: flex; flex-direction: column |
.Row() |
display: flex; flex-direction: row |
.RelativeItem() |
flex: 1 |
.Table() |
<table> element |
.PaddingTop(20) |
padding-top: 20px or <br/> |
.AlignCenter() |
text-align: center |
.FontSize(24) |
font-size: 24px |
.Bold() |
font-weight: bold or <strong> |
Page Settings Conversion
// QuestPDF
page.Size(PageSizes.A4);
page.Margin(2, Unit.Centimetre);
// IronPDF
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.MarginTop = 20; // mm (2cm = 20mm)
renderer.RenderingOptions.MarginBottom = 20;
renderer.RenderingOptions.MarginLeft = 20;
renderer.RenderingOptions.MarginRight = 20;
// QuestPDF
page.Size(PageSizes.A4);
page.Margin(2, Unit.Centimetre);
// IronPDF
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.MarginTop = 20; // mm (2cm = 20mm)
renderer.RenderingOptions.MarginBottom = 20;
renderer.RenderingOptions.MarginLeft = 20;
renderer.RenderingOptions.MarginRight = 20;
' QuestPDF
page.Size(PageSizes.A4)
page.Margin(2, Unit.Centimetre)
' IronPDF
Dim renderer = New ChromePdfRenderer()
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
renderer.RenderingOptions.MarginTop = 20 ' mm (2cm = 20mm)
renderer.RenderingOptions.MarginBottom = 20
renderer.RenderingOptions.MarginLeft = 20
renderer.RenderingOptions.MarginRight = 20
New Capabilities After Migration
After migrating to IronPDF, you gain capabilities that QuestPDF cannot provide:
PDF Merging
var cover = renderer.RenderHtmlAsPdf("<h1>Cover</h1>");
var content = renderer.RenderHtmlAsPdf(reportHtml);
var existing = PdfDocument.FromFile("appendix.pdf");
var merged = PdfDocument.Merge(cover, content, existing);
merged.SaveAs("complete.pdf");
var cover = renderer.RenderHtmlAsPdf("<h1>Cover</h1>");
var content = renderer.RenderHtmlAsPdf(reportHtml);
var existing = PdfDocument.FromFile("appendix.pdf");
var merged = PdfDocument.Merge(cover, content, existing);
merged.SaveAs("complete.pdf");
Dim cover = renderer.RenderHtmlAsPdf("<h1>Cover</h1>")
Dim content = renderer.RenderHtmlAsPdf(reportHtml)
Dim existing = PdfDocument.FromFile("appendix.pdf")
Dim merged = PdfDocument.Merge(cover, content, existing)
merged.SaveAs("complete.pdf")
PDF Security
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SecuritySettings.OwnerPassword = "admin";
pdf.SecuritySettings.UserPassword = "reader";
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.FullPrintRights;
pdf.SaveAs("protected.pdf");
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SecuritySettings.OwnerPassword = "admin";
pdf.SecuritySettings.UserPassword = "reader";
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.FullPrintRights;
pdf.SaveAs("protected.pdf");
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SecuritySettings.OwnerPassword = "admin"
pdf.SecuritySettings.UserPassword = "reader"
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.FullPrintRights
pdf.SaveAs("protected.pdf")
URL to PDF
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.EnableJavaScript = true;
var pdf = renderer.RenderUrlAsPdf("https://example.com/report");
pdf.SaveAs("webpage.pdf");
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.EnableJavaScript = true;
var pdf = renderer.RenderUrlAsPdf("https://example.com/report");
pdf.SaveAs("webpage.pdf");
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.EnableJavaScript = True
Dim pdf = renderer.RenderUrlAsPdf("https://example.com/report")
pdf.SaveAs("webpage.pdf")
Load and Edit Existing PDFs
var pdf = PdfDocument.FromFile("existing.pdf");
// Modify, merge, add security, etc.
pdf.SaveAs("modified.pdf");
var pdf = PdfDocument.FromFile("existing.pdf");
// Modify, merge, add security, etc.
pdf.SaveAs("modified.pdf");
Dim pdf = PdfDocument.FromFile("existing.pdf")
' Modify, merge, add security, etc.
pdf.SaveAs("modified.pdf")
Feature Comparison Summary
| Feature | QuestPDF | IronPDF |
|---|---|---|
| HTML-to-PDF | Core: not supported (limited via QuestPDF.HTML extension) |
Primary feature |
| Learning Curve | Fluent C# API | Standard web skills |
| Template Preview | Companion app | Any browser |
| Design Collaboration | Developers only | Designers + Developers |
| Existing Assets | Must rebuild | Reuse HTML/CSS |
| PDF Manipulation | Merge / extract / overlay (Document Operations API, 2024.12.0+) | Supported |
| Security/Signing | Encryption + permissions (no digital signing) | Encryption + digital signing |
| Licensing Model | Revenue-based ($1M threshold) | Per-developer |
| Client Impact | May need licenses above $1M revenue | None |
| Bootstrap/Tailwind | Not supported | Supported |
| URL to PDF | Not supported | Supported |
Migration Checklist
Pre-Migration
- Identify all QuestPDF document templates (
Document.Create,.GeneratePdf) - Document the DSL patterns used (
.Column(),.Row(),.Table(),.Text()) - Map styling methods to CSS equivalents
- Obtain IronPDF license key from ironpdf.com
Package Changes
- Remove
QuestPDFNuGet package - Install
IronPdfNuGet package:dotnet add package IronPdf
Code Changes
- Update namespace imports
- Remove
QuestPDF.Settings.License = LicenseType.Community - Convert
Document.Create()pattern toChromePdfRenderer+ HTML - Replace
.Column()/.Row()with CSS Flexbox - Replace
.Table()with HTML<table>elements - Convert
.Text().Bold().FontSize(24)to<h1 style='...'> - Replace
page.Header()/page.Footer()withTextHeaderFooter - Replace
.CurrentPageNumber()with{page}placeholder - Convert
.GeneratePdf()topdf.SaveAs() - Add license initialization at application startup
Post-Migration
- Visual comparison of PDF output
- Test multi-page documents for correct page breaks
- Add new capabilities (security, merging, URL-to-PDF) as needed

