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:
Process Management Overhead: Must spawn, monitor, and terminate external processes.
No Native .NET Integration: Communicate via stdin/stdout or temporary files.
Deployment Complexity: Requires Prince installation on every server.
Licensing Per Server: Each deployment needs a separate license ($495+).
Error Handling Difficulty: Parse text output for error detection.
No Async/Await: Blocking calls or complex async wrappers required.
- Path Dependencies: Must locate Prince executable on PATH or absolute path.
PrinceXML vs IronPDF Comparison
| Aspect | PrinceXML | IronPDF |
|---|---|---|
| Architecture | External Process | Native .NET Library |
| Integration | Command-line | Direct API |
| Deployment | Install on every server | Single NuGet package |
| Error Handling | Parse text output | .NET exceptions |
| Async Support | Manual wrappers | Native async/await |
| PDF Manipulation | Generation only | Full manipulation (merge, split, edit) |
| Licensing | Per server ($495+) | Per developer |
| Updates | Manual reinstall | NuGet update |
| Debugging | Difficult | Full debugger support |
| Digital Signatures | No | Yes |
| Forms | No | Yes |
| Docker Support | Complex | Simple |
| Cloud Functions | Difficult | Easy |
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
- .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
# 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 PrinceXMLWrapperLicense Configuration
// Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";// Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";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" .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;Command-Line to Method Mapping
| Prince Command | IronPDF Equivalent |
|---|---|
prince input.html -o output.pdf | renderer.RenderHtmlFileAsPdf("input.html").SaveAs("output.pdf") |
prince --style=custom.css input.html | Include CSS in HTML or use RenderingOptions |
prince --javascript | renderer.RenderingOptions.EnableJavaScript = true |
prince --no-javascript | renderer.RenderingOptions.EnableJavaScript = false |
prince --page-size=Letter | renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter |
prince --page-margin=1in | renderer.RenderingOptions.MarginTop = 72 (72 points = 1 inch) |
prince --encrypt | pdf.SecuritySettings.OwnerPassword = "..." |
prince --user-password=pw | pdf.SecuritySettings.UserPassword = "pw" |
prince --disallow-print | pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.NoPrint |
prince --disallow-copy | pdf.SecuritySettings.AllowUserCopyPasteContent = false |
prince --baseurl=http://... | renderer.RenderingOptions.BaseUrl = new Uri("http://...") |
prince --media=print | renderer.RenderingOptions.CssMediaType = PdfCssMediaType.Print |
prince --media=screen | renderer.RenderingOptions.CssMediaType = PdfCssMediaType.Screen |
CSS @page to RenderingOptions Mapping
| CSS @page Property | IronPDF Equivalent |
|---|---|
size: A4 | PaperSize = PdfPaperSize.A4 |
size: Letter | PaperSize = PdfPaperSize.Letter |
size: A4 landscape | PaperSize = PdfPaperSize.A4 + PaperOrientation = Landscape |
margin: 2cm | MarginTop/Bottom/Left/Right = 56 |
margin-top: 1in | MarginTop = 72 |
@top-center { content: "..." } | HtmlHeader with centered div |
@bottom-right { content: counter(page) } | HtmlFooter with {page} placeholder |
Page Size Conversions
| Size | Points | Millimeters |
|---|---|---|
| Letter | 612 x 792 | 216 x 279 |
| A4 | 595 x 842 | 210 x 297 |
| Legal | 612 x 1008 | 216 x 356 |
| 1 inch | 72 | 25.4 |
| 1 cm | 28.35 | 10 |
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");
}
}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");
}
}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");
}
}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");
}
}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 = trueprince.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");
}
}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");
}
}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
};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>renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
HtmlFragment = "<div>{html-title}</div>"
};renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
HtmlFragment = "<div>{html-title}</div>"
};Issue 4: counter(pages) Incorrect
Use IronPDF's {total-pages} placeholder instead of CSS counters.
Performance Comparison
| Operation | PrinceXML | IronPDF | Notes |
|---|---|---|---|
| Simple HTML | ~400ms | ~300ms | IronPDF in-process |
| Complex CSS | ~600ms | ~400ms | No process overhead |
| JavaScript pages | Limited | ~500ms | Full JS support |
| Large documents | ~1500ms | ~1000ms | Better memory |
| Concurrent (10) | ~4000ms | ~1500ms | Thread pool |
| Startup overhead | ~200ms | ~50ms | No 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");Watermarks
pdf.ApplyWatermark("<h1 style='color:red; opacity:0.3;'>DRAFT</h1>");pdf.ApplyWatermark("<h1 style='color:red; opacity:0.3;'>DRAFT</h1>");Digital Signatures
var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);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");Feature Comparison Summary
| Feature | PrinceXML | IronPDF |
|---|---|---|
| Native .NET | No | Yes |
| External Process | Required | No |
| Async Support | Manual wrapping | Native async/await |
| CSS Paged Media | Full support | Via RenderingOptions |
| CSS Grid | Yes | Yes |
| Flexbox | Yes | Yes |
| JavaScript | Limited | Full ES2024 |
| Generation | Yes | Yes |
| Merge | No | Yes |
| Split | No | Yes |
| Edit | No | Yes |
| Watermarks | CSS only | HTML/CSS + API |
| Digital Signatures | No | Yes |
| PDF/A | Yes | Yes |
| Encryption | Yes | Yes |
| Forms | No | Yes |
| NuGet Package | No | Yes |
| Server Install | Required | No |
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
PrinceXMLWrapperNuGet package - Install
IronPdfNuGet package - Update namespace imports
- Replace
Princeinstantiation withChromePdfRenderer - Replace
prince.Convert()withRenderHtmlFileAsPdf()orRenderHtmlAsPdf() - Convert setter methods to
RenderingOptionsproperties - 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






