Skip to footer content
MIGRATION GUIDES

How to Migrate from PrinceXML to IronPDF in C#

Migrating from PrinceXML to IronPDF transforms your PDF generation workflow from an external command-line process to a native .NET library. This guide provides a complete, step-by-step migration path that eliminates process management overhead, simplifies deployment, and provides extensive PDF manipulation capabilities beyond generation.

Why Migrate from PrinceXML to IronPDF

Understanding PrinceXML

PrinceXML is a sophisticated tool designed to excel at converting HTML content into print-perfect PDF documents through its dedicated support for CSS Paged Media specifications. This specialization allows PrinceXML to render documents with high fidelity to intended print designs—a valuable attribute for industries requiring detailed print styling, like publishing or legal documentation.

However, PrinceXML is not a .NET library and operates as a separate command-line tool, which may complicate integration for environments that prefer pure .NET solutions. Its reliance on a separate server process involves additional system resource management and potentially increased complexity for project deployments.

The External Process Problem

PrinceXML operates as a separate command-line executable that creates significant architectural challenges for .NET applications:

  1. Process Management Overhead: Must spawn, monitor, and terminate external processes.

  2. No Native .NET Integration: Communicate via stdin/stdout or temporary files.

  3. Deployment Complexity: Requires Prince installation on every server.

  4. Licensing Per Server: Each deployment needs a separate license ($495+).

  5. Error Handling Difficulty: Parse text output for error detection.

  6. No Async/Await: Blocking calls or complex async wrappers required.

  7. Path Dependencies: Must locate Prince executable on PATH or absolute path.

PrinceXML vs IronPDF Comparison

AspectPrinceXMLIronPDF
ArchitectureExternal ProcessNative .NET Library
IntegrationCommand-lineDirect API
DeploymentInstall on every serverSingle NuGet package
Error HandlingParse text output.NET exceptions
Async SupportManual wrappersNative async/await
PDF ManipulationGeneration onlyFull manipulation (merge, split, edit)
LicensingPer server ($495+)Per developer
UpdatesManual reinstallNuGet update
DebuggingDifficultFull debugger support
Digital SignaturesNoYes
FormsNoYes
Docker SupportComplexSimple
Cloud FunctionsDifficultEasy

IronPDF provides an alternative with its .NET native capabilities, extending beyond mere HTML-to-PDF conversion to include advanced PDF manipulation tasks, such as editing, merging, and digital signatures. IronPDF's API is designed for simplicity and ease of use, letting developers perform conversions and manipulations with minimal boilerplate code.

For teams planning .NET 10 and C# 14 adoption through 2025 and 2026, IronPDF's seamless deployment requires no external dependencies or server processes and thus eases the burden of integration into the .NET framework.


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

# Install IronPDF
dotnet add package IronPdf

# Remove Prince wrapper if using one
dotnet remove package PrinceXMLWrapper
# Install IronPDF
dotnet add package IronPdf

# Remove Prince wrapper if using one
dotnet remove package PrinceXMLWrapper
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

Search for PrinceXML Usage

# Find Prince process calls
grep -r "prince" --include="*.cs" .
grep -r "Process.Start" --include="*.cs" . | grep -i prince
grep -r "@page" --include="*.css" .
grep -r "prince-" --include="*.css" .
# Find Prince process calls
grep -r "prince" --include="*.cs" .
grep -r "Process.Start" --include="*.cs" . | grep -i prince
grep -r "@page" --include="*.css" .
grep -r "prince-" --include="*.css" .
SHELL

Complete API Reference

Namespace Changes

// Before: PrinceXML
using PrinceXMLWrapper;
using System.Diagnostics;
using System.IO;

// After: IronPDF
using IronPdf;
// Before: PrinceXML
using PrinceXMLWrapper;
using System.Diagnostics;
using System.IO;

// After: IronPDF
using IronPdf;
$vbLabelText   $csharpLabel

Command-Line to Method Mapping

Prince CommandIronPDF Equivalent
prince input.html -o output.pdfrenderer.RenderHtmlFileAsPdf("input.html").SaveAs("output.pdf")
prince --style=custom.css input.htmlInclude CSS in HTML or use RenderingOptions
prince --javascriptrenderer.RenderingOptions.EnableJavaScript = true
prince --no-javascriptrenderer.RenderingOptions.EnableJavaScript = false
prince --page-size=Letterrenderer.RenderingOptions.PaperSize = PdfPaperSize.Letter
prince --page-margin=1inrenderer.RenderingOptions.MarginTop = 72 (72 points = 1 inch)
prince --encryptpdf.SecuritySettings.OwnerPassword = "..."
prince --user-password=pwpdf.SecuritySettings.UserPassword = "pw"
prince --disallow-printpdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.NoPrint
prince --disallow-copypdf.SecuritySettings.AllowUserCopyPasteContent = false
prince --baseurl=http://...renderer.RenderingOptions.BaseUrl = new Uri("http://...")
prince --media=printrenderer.RenderingOptions.CssMediaType = PdfCssMediaType.Print
prince --media=screenrenderer.RenderingOptions.CssMediaType = PdfCssMediaType.Screen

CSS @page to RenderingOptions Mapping

CSS @page PropertyIronPDF Equivalent
size: A4PaperSize = PdfPaperSize.A4
size: LetterPaperSize = PdfPaperSize.Letter
size: A4 landscapePaperSize = PdfPaperSize.A4 + PaperOrientation = Landscape
margin: 2cmMarginTop/Bottom/Left/Right = 56
margin-top: 1inMarginTop = 72
@top-center { content: "..." }HtmlHeader with centered div
@bottom-right { content: counter(page) }HtmlFooter with {page} placeholder

Page Size Conversions

SizePointsMillimeters
Letter612 x 792216 x 279
A4595 x 842210 x 297
Legal612 x 1008216 x 356
1 inch7225.4
1 cm28.3510

Code Migration Examples

Example 1: HTML File to PDF Conversion

Before (PrinceXML):

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

class Program
{
    static void Main()
    {
        Prince prince = new Prince("C:\\Program Files\\Prince\\engine\\bin\\prince.exe");
        prince.Convert("input.html", "output.pdf");
        Console.WriteLine("PDF created successfully");
    }
}
// NuGet: Install-Package PrinceXMLWrapper
using PrinceXMLWrapper;
using System;

class Program
{
    static void Main()
    {
        Prince prince = new Prince("C:\\Program Files\\Prince\\engine\\bin\\prince.exe");
        prince.Convert("input.html", "output.pdf");
        Console.WriteLine("PDF created successfully");
    }
}
$vbLabelText   $csharpLabel

After (IronPDF):

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

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlFileAsPdf("input.html");
        pdf.SaveAs("output.pdf");
        Console.WriteLine("PDF created successfully");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlFileAsPdf("input.html");
        pdf.SaveAs("output.pdf");
        Console.WriteLine("PDF created successfully");
    }
}
$vbLabelText   $csharpLabel

This example demonstrates the fundamental architectural difference. PrinceXML requires instantiating a Prince object with the full path to the executable ("C:\\Program Files\\Prince\\engine\\bin\\prince.exe"), then calling Convert() with input and output paths.

IronPDF eliminates path dependencies entirely: create a ChromePdfRenderer, call RenderHtmlFileAsPdf() with the HTML file path, and SaveAs() to write the result. No executable paths, no process management, no path dependencies. See the HTML to PDF documentation for comprehensive examples.

Example 2: URL to PDF Conversion with Options

Before (PrinceXML):

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

class Program
{
    static void Main()
    {
        Prince prince = new Prince("C:\\Program Files\\Prince\\engine\\bin\\prince.exe");
        prince.SetJavaScript(true);
        prince.SetEncrypt(true);
        prince.SetPDFTitle("Website Export");
        prince.Convert("https://example.com", "webpage.pdf");
        Console.WriteLine("URL converted to PDF");
    }
}
// NuGet: Install-Package PrinceXMLWrapper
using PrinceXMLWrapper;
using System;

class Program
{
    static void Main()
    {
        Prince prince = new Prince("C:\\Program Files\\Prince\\engine\\bin\\prince.exe");
        prince.SetJavaScript(true);
        prince.SetEncrypt(true);
        prince.SetPDFTitle("Website Export");
        prince.Convert("https://example.com", "webpage.pdf");
        Console.WriteLine("URL converted to PDF");
    }
}
$vbLabelText   $csharpLabel

After (IronPDF):

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

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.EnableJavaScript = true;
        renderer.RenderingOptions.PdfTitle = "Website Export";

        var pdf = renderer.RenderUrlAsPdf("https://example.com");
        pdf.Encrypt("password");
        pdf.SaveAs("webpage.pdf");
        Console.WriteLine("URL converted to PDF");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.EnableJavaScript = true;
        renderer.RenderingOptions.PdfTitle = "Website Export";

        var pdf = renderer.RenderUrlAsPdf("https://example.com");
        pdf.Encrypt("password");
        pdf.SaveAs("webpage.pdf");
        Console.WriteLine("URL converted to PDF");
    }
}
$vbLabelText   $csharpLabel

This example shows how PrinceXML options map to IronPDF properties. PrinceXML uses setter methods (SetJavaScript(), SetEncrypt(), SetPDFTitle()) before conversion. IronPDF uses RenderingOptions properties for pre-render settings, and post-render methods like Encrypt() on the PdfDocument object.

Key mappings:

  • prince.SetJavaScript(true)renderer.RenderingOptions.EnableJavaScript = true
  • prince.SetPDFTitle("...")renderer.RenderingOptions.PdfTitle = "..."
  • prince.SetEncrypt(true)pdf.Encrypt("password") (IronPDF requires a password)

Learn more in our tutorials.

Example 3: HTML String to PDF Conversion

Before (PrinceXML):

// NuGet: Install-Package PrinceXMLWrapper
using PrinceXMLWrapper;
using System;
using System.IO;

class Program
{
    static void Main()
    {
        string html = "<html><head><style>body { font-family: Arial; color: blue; }</style></head><body><h1>Hello World</h1></body></html>";
        File.WriteAllText("temp.html", html);

        Prince prince = new Prince("C:\\Program Files\\Prince\\engine\\bin\\prince.exe");
        prince.Convert("temp.html", "styled-output.pdf");
        Console.WriteLine("Styled PDF created");
    }
}
// NuGet: Install-Package PrinceXMLWrapper
using PrinceXMLWrapper;
using System;
using System.IO;

class Program
{
    static void Main()
    {
        string html = "<html><head><style>body { font-family: Arial; color: blue; }</style></head><body><h1>Hello World</h1></body></html>";
        File.WriteAllText("temp.html", html);

        Prince prince = new Prince("C:\\Program Files\\Prince\\engine\\bin\\prince.exe");
        prince.Convert("temp.html", "styled-output.pdf");
        Console.WriteLine("Styled PDF created");
    }
}
$vbLabelText   $csharpLabel

After (IronPDF):

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

class Program
{
    static void Main()
    {
        string html = "<html><head><style>body { font-family: Arial; color: blue; }</style></head><body><h1>Hello World</h1></body></html>";

        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf(html);
        pdf.SaveAs("styled-output.pdf");
        Console.WriteLine("Styled PDF created");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        string html = "<html><head><style>body { font-family: Arial; color: blue; }</style></head><body><h1>Hello World</h1></body></html>";

        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf(html);
        pdf.SaveAs("styled-output.pdf");
        Console.WriteLine("Styled PDF created");
    }
}
$vbLabelText   $csharpLabel

This example highlights a critical difference: PrinceXML requires file input, so you must create a temporary file (File.WriteAllText("temp.html", html)) before conversion. IronPDF's RenderHtmlAsPdf() accepts HTML strings directly—no temporary files, no cleanup code, no disk I/O overhead.


Migrating CSS Paged Media

While PrinceXML's CSS Paged Media support is powerful, it creates vendor lock-in with Prince-specific CSS that won't work elsewhere:

PrinceXML CSS:

@page {
    size: A4;
    margin: 2cm;
    @top-center {
        content: "Document Title";
    }
    @bottom-right {
        content: counter(page);
    }
}

/* Prince-specific extensions */
prince-pdf-page-label: "Chapter " counter(chapter);
prince-pdf-destination: attr(id);

IronPDF C# (equivalent):

renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.MarginTop = 56;    // ~2cm
renderer.RenderingOptions.MarginBottom = 56;
renderer.RenderingOptions.MarginLeft = 56;
renderer.RenderingOptions.MarginRight = 56;

renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='text-align:center;'>Document Title</div>",
    MaxHeight = 40
};

renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='text-align:right;'>Page {page} of {total-pages}</div>",
    MaxHeight = 25
};
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.MarginTop = 56;    // ~2cm
renderer.RenderingOptions.MarginBottom = 56;
renderer.RenderingOptions.MarginLeft = 56;
renderer.RenderingOptions.MarginRight = 56;

renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='text-align:center;'>Document Title</div>",
    MaxHeight = 40
};

renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='text-align:right;'>Page {page} of {total-pages}</div>",
    MaxHeight = 25
};
$vbLabelText   $csharpLabel

Common CSS Migration Issues

Issue 1: CSS @page Not Working

IronPDF uses Chromium, which has limited @page support. Convert CSS rules to RenderingOptions.

Issue 2: Page Margin Boxes Missing

CSS margin boxes (@top-center, @bottom-right) are Prince-specific. Use HtmlHeader/HtmlFooter instead.

Issue 3: string-set/content Not Working

The string-set CSS property is Prince-specific. Use {html-title} placeholder from the <title> tag:

<title>Chapter 1: Introduction</title>
<title>Chapter 1: Introduction</title>
HTML
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
    HtmlFragment = "<div>{html-title}</div>"
};
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
    HtmlFragment = "<div>{html-title}</div>"
};
$vbLabelText   $csharpLabel

Issue 4: counter(pages) Incorrect

Use IronPDF's {total-pages} placeholder instead of CSS counters.


Performance Comparison

OperationPrinceXMLIronPDFNotes
Simple HTML~400ms~300msIronPDF in-process
Complex CSS~600ms~400msNo process overhead
JavaScript pagesLimited~500msFull JS support
Large documents~1500ms~1000msBetter memory
Concurrent (10)~4000ms~1500msThread pool
Startup overhead~200ms~50msNo process spawn

New Capabilities After Migration

After migrating to IronPDF, you gain capabilities that PrinceXML cannot provide:

PDF Merging

var pdf1 = PdfDocument.FromFile("chapter1.pdf");
var pdf2 = PdfDocument.FromFile("chapter2.pdf");
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("complete_book.pdf");
var pdf1 = PdfDocument.FromFile("chapter1.pdf");
var pdf2 = PdfDocument.FromFile("chapter2.pdf");
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("complete_book.pdf");
$vbLabelText   $csharpLabel

Watermarks

pdf.ApplyWatermark("<h1 style='color:red; opacity:0.3;'>DRAFT</h1>");
pdf.ApplyWatermark("<h1 style='color:red; opacity:0.3;'>DRAFT</h1>");
$vbLabelText   $csharpLabel

Digital Signatures

var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);
var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);
$vbLabelText   $csharpLabel

Form Filling

var pdf = PdfDocument.FromFile("form.pdf");
pdf.Form.GetFieldByName("Name").Value = "John Doe";
pdf.SaveAs("filled_form.pdf");
var pdf = PdfDocument.FromFile("form.pdf");
pdf.Form.GetFieldByName("Name").Value = "John Doe";
pdf.SaveAs("filled_form.pdf");
$vbLabelText   $csharpLabel

Feature Comparison Summary

FeaturePrinceXMLIronPDF
Native .NETNoYes
External ProcessRequiredNo
Async SupportManual wrappingNative async/await
CSS Paged MediaFull supportVia RenderingOptions
CSS GridYesYes
FlexboxYesYes
JavaScriptLimitedFull ES2024
GenerationYesYes
MergeNoYes
SplitNoYes
EditNoYes
WatermarksCSS onlyHTML/CSS + API
Digital SignaturesNoYes
PDF/AYesYes
EncryptionYesYes
FormsNoYes
NuGet PackageNoYes
Server InstallRequiredNo

Migration Checklist

Pre-Migration

  • Identify all Prince command-line invocations
  • Document CSS @page rules used
  • List Prince-specific CSS properties (prince-*, string-set)
  • Note any Prince JavaScript functions
  • Identify PDF features used (encryption, metadata)
  • Obtain IronPDF license key from ironpdf.com

Code Changes

  • Remove PrinceXMLWrapper NuGet package
  • Install IronPdf NuGet package
  • Update namespace imports
  • Replace Prince instantiation with ChromePdfRenderer
  • Replace prince.Convert() with RenderHtmlFileAsPdf() or RenderHtmlAsPdf()
  • Convert setter methods to RenderingOptions properties
  • Migrate @page CSS to RenderingOptions
  • Replace margin boxes with HtmlHeader/HtmlFooter
  • Convert CSS counters to {page}/{total-pages} placeholders
  • Remove temporary file handling for HTML strings
  • Add license initialization at application startup

Post-Migration

  • Test HTML file conversion
  • Test HTML string conversion
  • Test URL conversion
  • Verify page sizes match
  • Verify margins match
  • Test headers and footers
  • Verify page numbers
  • Test encryption/security
  • Remove Prince installation from servers
  • Update deployment scripts

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