How to Migrate from PDFreactor to IronPDF in C#
Migrating from PDFreactor to IronPDF eliminates Java dependencies and server infrastructure while providing equivalent HTML-to-PDF conversion capabilities through a native .NET library. This guide provides a complete, step-by-step migration path that replaces your Java-based server architecture with an in-process library that integrates seamlessly into .NET applications.
Why Migrate from PDFreactor to IronPDF
Understanding PDFreactor
PDFreactor is a powerful HTML-to-PDF conversion server that integrates across various platforms. As a commercial solution, PDFreactor leverages its proprietary technology to convert HTML and CSS content into high-quality PDF documents. Among its notable attributes, PDFreactor supports a wide array of CSS properties which makes it a strong candidate for complex layout rendering.
However, PDFreactor's reliance on Java presents certain challenges in .NET environments where its non-native nature may complicate deployment and integration. Its dependency on Java creates extra overhead in .NET applications, often requiring additional integration work.
The Java Dependency Problem
PDFreactor's architecture creates several challenges in .NET environments:
Java Runtime Required: Requires JRE/JDK installation on all servers.
Server Architecture: Runs as a separate service requiring additional infrastructure. As a server-based solution, PDFreactor requires REST API calls for every conversion.
Complex Deployment: Managing Java dependencies in a primarily .NET ecosystem can complicate the setup and increase maintenance costs. Two runtimes (Java + .NET) to manage in CI/CD pipelines.
Inter-Process Communication: REST API or socket communication adds latency. Every PDF conversion requires HTTP round-trip to server.
Separate License Management: License bound to server instance, not application. Per-server licensing tied to Java service instance.
- Resource Isolation: Separate process memory and CPU management. Additional server to monitor, scale, and maintain.
PDFreactor vs IronPDF Comparison
| Feature/Aspect | PDFreactor | IronPDF |
|---|---|---|
| Native .NET Library | No (Java-based) | Yes |
| Runtime | Java (external server) | Native .NET (in-process) |
| Architecture | REST API service | NuGet library |
| Deployment | Java + server config | Single NuGet package |
| Dependencies | JRE + HTTP client | Self-contained |
| Latency | Network round-trip | Direct method calls |
| Cross-Platform Capability | Yes (Java-dependent) | Yes (Bundled Chromium) |
| CSS Support | Advanced support for CSS3, CSS Paged Media | Comprehensive HTML5/CSS3 support |
| Deployment Complexity | More complex due to Java | Simple, directly integrates with .NET |
| PDF Manipulation Features | Basic (Generation only) | Extensive, including merge, split, edit, and annotate |
In contrast to PDFreactor, IronPDF presents itself as a native .NET library, specifically designed to integrate seamlessly into .NET projects without external dependencies like Java. IronPDF uses a bundled Chromium rendering engine, allowing it to convert HTML to PDF with just a few lines of code.
For teams planning .NET 10 and C# 14 adoption through 2025 and 2026, IronPDF provides a native .NET solution that eliminates Java server complexity while offering comprehensive PDF lifecycle management.
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 PDFreactor NuGet packages
dotnet remove package PDFreactor.NET
dotnet remove package PDFreactor.Native.Windows.x64
# Stop PDFreactor server service (if running locally)
# Windows: net stop PDFreactor
# Linux: sudo systemctl stop pdfreactor
# Install IronPDF
dotnet add package IronPdf# Remove PDFreactor NuGet packages
dotnet remove package PDFreactor.NET
dotnet remove package PDFreactor.Native.Windows.x64
# Stop PDFreactor server service (if running locally)
# Windows: net stop PDFreactor
# Linux: sudo systemctl stop pdfreactor
# Install IronPDF
dotnet add package IronPdfLicense Configuration
PDFreactor (server-based):
// License configured on server via config file or command line
// Client connects to licensed server
var pdfReactor = new PDFreactor("http://pdfreactor-server:9423");// License configured on server via config file or command line
// Client connects to licensed server
var pdfReactor = new PDFreactor("http://pdfreactor-server:9423");IronPDF (application-level):
// One-time setup at application startup
IronPdf.License.LicenseKey = "YOUR-IRONPDF-LICENSE-KEY";// One-time setup at application startup
IronPdf.License.LicenseKey = "YOUR-IRONPDF-LICENSE-KEY";Identify PDFreactor Usage
# Find PDFreactor usage
grep -r "PDFreactor\|RealObjects\|Configuration.*Document" --include="*.cs" .
# Find CSS Paged Media rules to convert
grep -r "@page\|counter(page)\|counter(pages)" --include="*.cs" --include="*.css" .# Find PDFreactor usage
grep -r "PDFreactor\|RealObjects\|Configuration.*Document" --include="*.cs" .
# Find CSS Paged Media rules to convert
grep -r "@page\|counter(page)\|counter(pages)" --include="*.cs" --include="*.css" .Complete API Reference
Namespace Changes
// Before: PDFreactor
using RealObjects.PDFreactor;
using System.IO;
// After: IronPDF
using IronPdf;
using IronPdf.Rendering;// Before: PDFreactor
using RealObjects.PDFreactor;
using System.IO;
// After: IronPDF
using IronPdf;
using IronPdf.Rendering;Core Class Mappings
| PDFreactor | IronPDF | Notes |
|---|---|---|
PDFreactor | ChromePdfRenderer | Main conversion class |
Configuration | ChromePdfRenderOptions | PDF settings |
Result | PdfDocument | Output document |
config.Document = html | renderer.RenderHtmlAsPdf(html) | HTML input |
result.Document (byte[]) | pdf.BinaryData | Raw bytes |
Configuration Property Mappings
| PDFreactor Configuration | IronPDF RenderingOptions | Notes |
|---|---|---|
config.Document = html | renderer.RenderHtmlAsPdf(html) | HTML content |
config.Document = url | renderer.RenderUrlAsPdf(url) | URL conversion |
config.PageFormat = PageFormat.A4 | RenderingOptions.PaperSize = PdfPaperSize.A4 | Paper size |
config.PageOrientation | RenderingOptions.PaperOrientation | Orientation |
config.PageMargins | RenderingOptions.MarginTop/Bottom/Left/Right | Margins (mm) |
config.EnableJavaScript = true | RenderingOptions.EnableJavaScript = true | JS execution |
config.AddUserStyleSheet(css) | Embed CSS in HTML | CSS injection |
config.Title | pdf.MetaData.Title | Metadata |
config.Encryption | pdf.SecuritySettings | Security |
New Features Not Available in PDFreactor
| IronPDF Feature | Description |
|---|---|
PdfDocument.Merge() | Merge multiple PDFs |
pdf.ApplyWatermark() | Add watermarks |
pdf.ExtractAllText() | Text extraction |
pdf.Form | Form filling |
pdf.Sign() | Digital signatures |
Code Migration Examples
Example 1: HTML String to PDF Conversion
Before (PDFreactor):
// NuGet: Install-Package PDFreactor.Native.Windows.x64
using RealObjects.PDFreactor;
using System.IO;
class Program
{
static void Main()
{
PDFreactor pdfReactor = new PDFreactor();
string html = "<html><body><h1>Hello World</h1></body></html>";
Configuration config = new Configuration();
config.Document = html;
Result result = pdfReactor.Convert(config);
File.WriteAllBytes("output.pdf", result.Document);
}
}// NuGet: Install-Package PDFreactor.Native.Windows.x64
using RealObjects.PDFreactor;
using System.IO;
class Program
{
static void Main()
{
PDFreactor pdfReactor = new PDFreactor();
string html = "<html><body><h1>Hello World</h1></body></html>";
Configuration config = new Configuration();
config.Document = html;
Result result = pdfReactor.Convert(config);
File.WriteAllBytes("output.pdf", result.Document);
}
}After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
string html = "<html><body><h1>Hello World</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
string html = "<html><body><h1>Hello World</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
}
}The fundamental difference is the architectural pattern. PDFreactor requires creating a PDFreactor instance (which connects to the Java server), a separate Configuration object to hold settings and HTML content, calling Convert() which returns a Result object, and finally writing the result.Document bytes to file using File.WriteAllBytes().
IronPDF simplifies this to creating a ChromePdfRenderer, calling RenderHtmlAsPdf() directly with the HTML string, and using the built-in SaveAs() method on the returned PdfDocument. No server connection, no configuration object, no manual byte handling. See the HTML to PDF documentation for comprehensive examples.
Example 2: URL to PDF Conversion
Before (PDFreactor):
// NuGet: Install-Package PDFreactor.Native.Windows.x64
using RealObjects.PDFreactor;
using System.IO;
class Program
{
static void Main()
{
PDFreactor pdfReactor = new PDFreactor();
Configuration config = new Configuration();
config.Document = "https://www.example.com";
Result result = pdfReactor.Convert(config);
File.WriteAllBytes("webpage.pdf", result.Document);
}
}// NuGet: Install-Package PDFreactor.Native.Windows.x64
using RealObjects.PDFreactor;
using System.IO;
class Program
{
static void Main()
{
PDFreactor pdfReactor = new PDFreactor();
Configuration config = new Configuration();
config.Document = "https://www.example.com";
Result result = pdfReactor.Convert(config);
File.WriteAllBytes("webpage.pdf", result.Document);
}
}After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
pdf.SaveAs("webpage.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
pdf.SaveAs("webpage.pdf");
}
}PDFreactor uses the same config.Document property for both HTML strings and URLs, determining the type automatically. IronPDF provides explicit methods: RenderHtmlAsPdf() for HTML strings and RenderUrlAsPdf() for URLs. This explicit approach improves code clarity and IntelliSense support. Learn more in our tutorials.
Example 3: Headers and Footers with Page Numbers
Before (PDFreactor):
// NuGet: Install-Package PDFreactor.Native.Windows.x64
using RealObjects.PDFreactor;
using System.IO;
class Program
{
static void Main()
{
PDFreactor pdfReactor = new PDFreactor();
string html = "<html><body><h1>Document with Headers</h1><p>Content here</p></body></html>";
Configuration config = new Configuration();
config.Document = html;
config.AddUserStyleSheet("@page { @top-center { content: 'Header Text'; } @bottom-center { content: 'Page ' counter(page); } }");
Result result = pdfReactor.Convert(config);
File.WriteAllBytes("document.pdf", result.Document);
}
}// NuGet: Install-Package PDFreactor.Native.Windows.x64
using RealObjects.PDFreactor;
using System.IO;
class Program
{
static void Main()
{
PDFreactor pdfReactor = new PDFreactor();
string html = "<html><body><h1>Document with Headers</h1><p>Content here</p></body></html>";
Configuration config = new Configuration();
config.Document = html;
config.AddUserStyleSheet("@page { @top-center { content: 'Header Text'; } @bottom-center { content: 'Page ' counter(page); } }");
Result result = pdfReactor.Convert(config);
File.WriteAllBytes("document.pdf", result.Document);
}
}After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.TextHeader = new TextHeaderFooter()
{
CenterText = "Header Text"
};
renderer.RenderingOptions.TextFooter = new TextHeaderFooter()
{
CenterText = "Page {page}"
};
string html = "<html><body><h1>Document with Headers</h1><p>Content here</p></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("document.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.TextHeader = new TextHeaderFooter()
{
CenterText = "Header Text"
};
renderer.RenderingOptions.TextFooter = new TextHeaderFooter()
{
CenterText = "Page {page}"
};
string html = "<html><body><h1>Document with Headers</h1><p>Content here</p></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("document.pdf");
}
}This example shows the most significant syntax difference. PDFreactor uses CSS Paged Media syntax with @page rules, @top-center/@bottom-center regions, and counter(page) for page numbers injected via AddUserStyleSheet().
IronPDF uses a native .NET API with TextHeaderFooter objects assigned to RenderingOptions.TextHeader and RenderingOptions.TextFooter. Page numbers use the {page} placeholder instead of CSS counter(page). Note that IronPDF also requires importing the IronPdf.Rendering namespace for header/footer classes.
Critical Migration Notes
No Server Required
IronPDF runs in-process—no Java server to configure:
// PDFreactor: Requires server connection
var pdfReactor = new PDFreactor("http://localhost:9423");
// IronPDF: No server URL needed
var renderer = new ChromePdfRenderer();// PDFreactor: Requires server connection
var pdfReactor = new PDFreactor("http://localhost:9423");
// IronPDF: No server URL needed
var renderer = new ChromePdfRenderer();CSS Paged Media to IronPDF API
Replace CSS @page rules with RenderingOptions:
// PDFreactor CSS: @page { @bottom-center { content: 'Page ' counter(page); } }
// IronPDF equivalent:
renderer.RenderingOptions.TextFooter = new TextHeaderFooter
{
CenterText = "Page {page}"
};// PDFreactor CSS: @page { @bottom-center { content: 'Page ' counter(page); } }
// IronPDF equivalent:
renderer.RenderingOptions.TextFooter = new TextHeaderFooter
{
CenterText = "Page {page}"
};Page Number Placeholder Syntax
// PDFreactor CSS: counter(page)
// IronPDF: {page}
// PDFreactor CSS: counter(pages)
// IronPDF: {total-pages}// PDFreactor CSS: counter(page)
// IronPDF: {page}
// PDFreactor CSS: counter(pages)
// IronPDF: {total-pages}Result Handling Change
Configuration + Result pattern becomes direct PdfDocument:
// PDFreactor: Configuration → Convert → Result → bytes
Result result = pdfReactor.Convert(config);
byte[] bytes = result.Document;
File.WriteAllBytes("output.pdf", bytes);
// IronPDF: Direct PdfDocument with built-in methods
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
// Or: byte[] bytes = pdf.BinaryData;// PDFreactor: Configuration → Convert → Result → bytes
Result result = pdfReactor.Convert(config);
byte[] bytes = result.Document;
File.WriteAllBytes("output.pdf", bytes);
// IronPDF: Direct PdfDocument with built-in methods
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
// Or: byte[] bytes = pdf.BinaryData;Margin Units Change
PDFreactor uses strings; IronPDF uses millimeters:
// PDFreactor: config.PageMargins.Top = "1in"
// IronPDF: renderer.RenderingOptions.MarginTop = 25.4 // 1 inch in mm// PDFreactor: config.PageMargins.Top = "1in"
// IronPDF: renderer.RenderingOptions.MarginTop = 25.4 // 1 inch in mmNew Capabilities After Migration
After migrating to IronPDF, you gain capabilities that PDFreactor cannot provide:
PDF Merging
var pdf1 = PdfDocument.FromFile("document1.pdf");
var pdf2 = PdfDocument.FromFile("document2.pdf");
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("merged.pdf");var pdf1 = PdfDocument.FromFile("document1.pdf");
var pdf2 = PdfDocument.FromFile("document2.pdf");
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("merged.pdf");Watermarks
pdf.ApplyWatermark("<h2 style='color:red;'>CONFIDENTIAL</h2>");pdf.ApplyWatermark("<h2 style='color:red;'>CONFIDENTIAL</h2>");Text Extraction
string text = pdf.ExtractAllText();string text = pdf.ExtractAllText();Password Protection
pdf.SecuritySettings.UserPassword = "userpassword";
pdf.SecuritySettings.OwnerPassword = "ownerpassword";pdf.SecuritySettings.UserPassword = "userpassword";
pdf.SecuritySettings.OwnerPassword = "ownerpassword";Feature Comparison Summary
| Feature | PDFreactor | IronPDF |
|---|---|---|
| HTML to PDF | ✓ | ✓ |
| URL to PDF | ✓ | ✓ |
| Headers/Footers | CSS Paged Media | Native API |
| Page Settings | ✓ | ✓ |
| JavaScript Support | ✓ | ✓ |
| Native .NET | ✗ | ✓ |
| In-Process | ✗ | ✓ |
| Merge PDFs | ✗ | ✓ |
| Split PDFs | ✗ | ✓ |
| Watermarks | ✗ | ✓ |
| Text Extraction | ✗ | ✓ |
| Form Filling | ✗ | ✓ |
| Digital Signatures | ✗ | ✓ |
Migration Checklist
Pre-Migration
- Inventory all PDFreactor usage in codebase
- Document all CSS Paged Media rules used
- Note all configuration settings (margins, page size, JavaScript)
- Plan IronPDF license key storage (environment variables recommended)
- Test with IronPDF trial license first
Package Changes
- Remove
PDFreactor.NETNuGet package - Remove
PDFreactor.Native.Windows.x64NuGet package - Install
IronPdfNuGet package:dotnet add package IronPdf
Code Changes
- Update namespace imports (
using RealObjects.PDFreactor;→using IronPdf;) - Add
using IronPdf.Rendering;for header/footer classes - Replace
PDFreactorclass withChromePdfRenderer - Convert
Configurationobjects toRenderingOptionsproperties - Replace
config.Document = htmlwithrenderer.RenderHtmlAsPdf(html) - Replace
config.Document = urlwithrenderer.RenderUrlAsPdf(url) - Replace
File.WriteAllBytes(path, result.Document)withpdf.SaveAs(path) - Convert CSS
@pagerules toTextHeader/TextFooterobjects - Update page number placeholders (
counter(page)→{page}) - Convert margin units from strings to millimeters
Infrastructure Migration
- Remove Java runtime requirement
- Decommission PDFreactor server
- Update Docker/deployment configurations
- Update CI/CD pipelines
Post-Migration
- Test PDF output quality matches expectations
- Verify header/footer rendering
- Verify JavaScript execution if used
- Add new capabilities (merging, watermarks, security) as needed






