푸터 콘텐츠로 바로가기
MIGRATION GUIDES

How to Migrate from QuestPDF to IronPDF in C#

Migrating from QuestPDF to IronPDF transforms your PDF generation workflow from a proprietary C# fluent API to a standard HTML/CSS-based approach with comprehensive PDF manipulation capabilities. This guide provides a complete, step-by-step migration path that enables you to leverage existing web skills, reuse HTML templates, and gain features that QuestPDF simply cannot provide.

Why Migrate from QuestPDF to IronPDF

Understanding QuestPDF

QuestPDF is a modern, fluent API created specifically for generating PDFs programmatically in C#. Unlike some of its peers that offer comprehensive HTML-to-PDF conversion capability, QuestPDF is limited to programmatic layout API functionalities. QuestPDF excels in scenarios where developers need to generate documents from scratch using C# code, without relying on HTML.

The library is free for businesses with revenue under $1M, but it comes with a requirement to prove this revenue level, which could be a compliance burden for some. Users who surpass this threshold need to purchase a license, which must be factored into long-term planning when evaluating QuestPDF as a potential solution.

The Core Problem: No HTML Support

QuestPDF is often recommended for HTML-to-PDF conversion, but it doesn't support HTML at all. Despite being heavily promoted on developer forums, QuestPDF uses its own proprietary layout language that requires learning an entirely new DSL instead of leveraging existing web skills.

Feature QuestPDF IronPDF
HTML-to-PDF NOT SUPPORTED Supported
CSS Styling NOT SUPPORTED Full CSS3
Existing Templates Must rebuild from scratch Reuse HTML/CSS assets
Design Tool Compatibility None Any web design tool
Learning Curve New proprietary DSL Web skills transfer
Layout Preview Requires IDE plugin Preview in any browser
PDF Manipulation None Merging, splitting, editing

IronPDF provides native HTML-to-PDF rendering that QuestPDF completely lacks, eliminating the need to manually reconstruct documents in C# code. It includes comprehensive PDF manipulation features (merge, split, edit, secure) that QuestPDF cannot perform.

The QuestPDF Licensing Model

QuestPDF's "Community License" is only free if your company has less than $1 million in annual gross revenue. Your clients (not just you as a developer) may need to purchase licenses if they exceed revenue thresholds. Unlike a simple per-developer commercial license, QuestPDF's model requires revenue disclosure and compliance tracking.

IronPDF offers simple licensing: one license per developer, no revenue audits, no client licensing requirements, and clear, predictable costs.

For teams planning .NET 10 and C# 14 adoption through 2025 and 2026, IronPDF provides transparent licensing without revenue-based audits and a standard HTML/CSS approach that leverages existing web development skills.


Before You Start

Prerequisites

  1. .NET Environment: .NET Framework 4.6.2+ or .NET Core 3.1+ / .NET 5/6/7/8/9+
  2. NuGet Access: Ability to install NuGet packages
  3. 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
SHELL

License Configuration

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

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" .
SHELL

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;
$vbLabelText   $csharpLabel

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");
    }
}
$vbLabelText   $csharpLabel

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");
    }
}
$vbLabelText   $csharpLabel

This example demonstrates the fundamental 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 proprietary DSL to learn. IronPDF's approach offers cleaner syntax and better integration with modern .NET applications. 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");
    }
}
$vbLabelText   $csharpLabel

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");
    }
}
$vbLabelText   $csharpLabel

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");
    }
}
$vbLabelText   $csharpLabel

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");
    }
}
$vbLabelText   $csharpLabel

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 fundamental change is moving from a proprietary C# DSL to standard HTML/CSS:

// QuestPDF: Proprietary fluent 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>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: Proprietary fluent 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>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);
$vbLabelText   $csharpLabel

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;
$vbLabelText   $csharpLabel

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");
$vbLabelText   $csharpLabel

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");
$vbLabelText   $csharpLabel

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");
$vbLabelText   $csharpLabel

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");
$vbLabelText   $csharpLabel

Feature Comparison Summary

Feature QuestPDF IronPDF
HTML-to-PDF Not supported Primary feature
Learning Curve Proprietary DSL Standard web skills
Template Preview Plugin required Any browser
Design Collaboration Developers only Designers + Developers
Existing Assets Must rebuild Reuse HTML/CSS
PDF Manipulation Not supported Supported
Security/Signing Not supported Supported
Licensing Model Revenue-based Per-developer
Client Impact May need licenses 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 QuestPDF NuGet package
  • Install IronPdf NuGet package: dotnet add package IronPdf

Code Changes

  • Update namespace imports
  • Remove QuestPDF.Settings.License = LicenseType.Community
  • Convert Document.Create() pattern to ChromePdfRenderer + 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() with TextHeaderFooter
  • Replace .CurrentPageNumber() with {page} placeholder
  • Convert .GeneratePdf() to pdf.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

커티스 차우
기술 문서 작성자

커티스 차우는 칼턴 대학교에서 컴퓨터 과학 학사 학위를 취득했으며, Node.js, TypeScript, JavaScript, React를 전문으로 하는 프론트엔드 개발자입니다. 직관적이고 미적으로 뛰어난 사용자 인터페이스를 만드는 데 열정을 가진 그는 최신 프레임워크를 활용하고, 잘 구성되고 시각적으로 매력적인 매뉴얼을 제작하는 것을 즐깁니다.

커티스는 개발 분야 외에도 사물 인터넷(IoT)에 깊은 관심을 가지고 있으며, 하드웨어와 소프트웨어를 통합하는 혁신적인 방법을 연구합니다. 여가 시간에는 게임을 즐기거나 디스코드 봇을 만들면서 기술에 대한 애정과 창의성을 결합합니다.