How to Migrate from EO.Pdf to IronPDF in C#
EO.Pdf presents several architectural challenges that drive development teams to evaluate alternatives. Understanding these issues is essential for planning your migration strategy.
The EO.Pdf Problems
-
Bundled Chromium Footprint: EO.Pdf (current NuGet version 26.1.34, March 2026) ships its own Chromium-based renderer, which increases the install footprint relative to non-Chromium libraries and adds weight to Docker images and CI/CD pipelines.
-
Legacy Architecture Baggage: EO.Pdf's HTML-to-PDF converter was originally built on an embedded Internet Explorer / Trident engine before the project moved to a Chromium-based renderer. The transition has left behind some API quirks and behavior differences between versions.
-
Windows-Only on .NET Core: Despite marketing as "cross-platform," Essential Objects' own .NET Core documentation states that EO.Pdf supports .NET Core 3.1+ and .NET 5/6 on Windows only — Linux and macOS are not officially supported.
-
Static Global Options: EO.Pdf's primary HTML-to-PDF entry point is the static
HtmlToPdfclass with sharedHtmlToPdf.Options. Mutating that global state from multiple threads is not safe and is awkward in multi-tenant web applications. - Paid Commercial License: EO.Pdf is sold as Single, 3-License Bundle, Corporate, and Corporate Plus tiers (no permanent free tier — only a 30-day watermarked trial). Exact prices appear on the order page.
Architecture Comparison
| Aspect | EO.Pdf | IronPDF |
|---|---|---|
| Renderer | Bundled Chromium (transitioned from IE/Trident) | Embedded Chromium |
| Legacy Issues | IE/Trident migration baggage | Built on Chromium from the start |
| Platform Support | Windows-only on .NET Core | Windows, Linux, macOS, Docker, Azure |
| Configuration | Static HtmlToPdf.Options (not thread-safe) |
Instance-based ChromePdfRenderer (thread-safe) |
| API Design | Mixed (HtmlToPdf static + ACM object model) |
Unified ChromePdfRenderer + HTML/CSS |
| License model | Single / 3-License / Corporate / Corporate Plus (30-day trial) | Per-developer commercial; free dev trial |
| Modern .NET | .NET Framework + .NET Core 3.1+ (Windows only) | .NET Framework, .NET 6/7/8/9 cross-platform |
| Async Support | Limited | Full RenderHtmlAsPdfAsync / RenderUrlAsPdfAsync |
Key Migration Benefits
- Cross-platform on .NET Core / .NET 6+: Works on Linux, macOS, and Docker — not just Windows
- Thread-Safe Configuration: Instance-based renderer options instead of static globals
- Modern API: Consistent method names —
RenderHtmlAsPdf,RenderUrlAsPdf,PdfDocument.Merge - Full Async Support:
RenderHtmlAsPdfAsyncandRenderUrlAsPdfAsyncfor non-blocking pipelines - Documentation: Extensive tutorials, how-to guides, and an active object reference
Pre-Migration Preparation
Prerequisites
Ensure your environment meets these requirements:
- .NET Framework 4.6.2+ or .NET Core 3.1 / .NET 5-9
- Visual Studio 2019+ or VS Code with C# extension
- NuGet Package Manager access
- IronPDF license key (free trial available at ironpdf.com)
Audit EO.Pdf Usage
Run these commands in your solution directory to identify all EO.Pdf references:
# Find all EO.Pdf references
grep -r "EO.Pdf\|HtmlToPdf\|AcmRender\|PdfDocument" --include="*.cs" .
# Check NuGet packages
dotnet list package | grep -i "EO.Pdf"
# Find all EO.Pdf references
grep -r "EO.Pdf\|HtmlToPdf\|AcmRender\|PdfDocument" --include="*.cs" .
# Check NuGet packages
dotnet list package | grep -i "EO.Pdf"
Common EO.Pdf namespaces to look for:
EO.Pdf- Core HTML to PDFEO.Pdf.Acm- Advanced Content Model (ACM)EO.Pdf.Contents- Low-level content manipulationEO.Pdf.Drawing- Graphics operations
Understanding the Core Pattern Change
The most significant architectural difference between EO.Pdf and IronPDF is configuration scope. EO.Pdf uses static methods with global options that affect all conversions—a pattern that causes thread-safety issues in web applications. IronPDF uses instance-based renderers with local options, ensuring each conversion is isolated.
Step-by-Step Migration Process
Step 1: Update NuGet Packages
Remove EO.Pdf and install IronPDF:
# Remove EO.Pdf
dotnet remove package EO.Pdf
# Install IronPDF
dotnet add package IronPdf
# Remove EO.Pdf
dotnet remove package EO.Pdf
# Install IronPDF
dotnet add package IronPdf
Step 2: Update Namespace References
Replace EO.Pdf namespaces with IronPDF:
// Remove these
using EO.Pdf;
using EO.Pdf.Acm;
// Add this
using IronPdf;
// Remove these
using EO.Pdf;
using EO.Pdf.Acm;
// Add this
using IronPdf;
Imports IronPdf
Step 3: Configure License
// Add at application startup (Program.cs or Startup.cs)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Add at application startup (Program.cs or Startup.cs)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
' Add at application startup (Program.vb or Startup.vb)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
Complete API Migration Reference
Core Class Mapping
| EO.Pdf Class | IronPDF Equivalent |
|---|---|
HtmlToPdf |
ChromePdfRenderer |
PdfDocument |
PdfDocument |
HtmlToPdfOptions |
ChromePdfRenderOptions |
AcmRender |
Not needed |
AcmText |
HTML <span>, <p> |
AcmBlock |
HTML <div> |
Method Mapping
| EO.Pdf Method | IronPDF Method |
|---|---|
HtmlToPdf.ConvertHtml(html, path) |
renderer.RenderHtmlAsPdf(html) then SaveAs(path) |
HtmlToPdf.ConvertUrl(url, path) |
renderer.RenderUrlAsPdf(url) then SaveAs(path) |
PdfDocument.Save(path) |
pdf.SaveAs(path) |
new PdfDocument(path) |
PdfDocument.FromFile(path) |
PdfDocument.Merge(doc1, doc2) (static) |
PdfDocument.Merge(doc1, doc2) (static) |
Options Mapping
| EO.Pdf Option | IronPDF RenderingOptions |
|---|---|
Options.PageSize = PdfPageSizes.A4 |
PaperSize = PdfPaperSize.A4 |
Options.OutputArea (RectangleF) |
MarginTop, MarginBottom, etc. |
Code Migration Examples
HTML to PDF Conversion
The fundamental HTML to PDF conversion demonstrates the shift from static methods to instance-based rendering.
EO.Pdf Implementation:
// NuGet: Install-Package EO.Pdf
using EO.Pdf;
using System;
class Program
{
static void Main()
{
string html = "<html><body><h1>Hello World</h1><p>This is a PDF generated from HTML.</p></body></html>";
HtmlToPdf.ConvertHtml(html, "output.pdf");
Console.WriteLine("PDF created successfully!");
}
}
// NuGet: Install-Package EO.Pdf
using EO.Pdf;
using System;
class Program
{
static void Main()
{
string html = "<html><body><h1>Hello World</h1><p>This is a PDF generated from HTML.</p></body></html>";
HtmlToPdf.ConvertHtml(html, "output.pdf");
Console.WriteLine("PDF created successfully!");
}
}
Imports EO.Pdf
Imports System
Class Program
Shared Sub Main()
Dim html As String = "<html><body><h1>Hello World</h1><p>This is a PDF generated from HTML.</p></body></html>"
HtmlToPdf.ConvertHtml(html, "output.pdf")
Console.WriteLine("PDF created successfully!")
End Sub
End Class
IronPDF Implementation:
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
string html = "<html><body><h1>Hello World</h1><p>This is a PDF generated from HTML.</p></body></html>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
Console.WriteLine("PDF created successfully!");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
string html = "<html><body><h1>Hello World</h1><p>This is a PDF generated from HTML.</p></body></html>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
Console.WriteLine("PDF created successfully!");
}
}
Imports IronPdf
Imports System
Class Program
Shared Sub Main()
Dim html As String = "<html><body><h1>Hello World</h1><p>This is a PDF generated from HTML.</p></body></html>"
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
Console.WriteLine("PDF created successfully!")
End Sub
End Class
IronPDF's two-step pattern (render, then save) provides access to the PdfDocument object for additional manipulation before saving. For more options, see the HTML to PDF documentation.
URL to PDF Conversion
EO.Pdf Implementation:
// NuGet: Install-Package EO.Pdf
using EO.Pdf;
using System;
class Program
{
static void Main()
{
string url = "https://www.example.com";
HtmlToPdf.ConvertUrl(url, "webpage.pdf");
Console.WriteLine("PDF from URL created successfully!");
}
}
// NuGet: Install-Package EO.Pdf
using EO.Pdf;
using System;
class Program
{
static void Main()
{
string url = "https://www.example.com";
HtmlToPdf.ConvertUrl(url, "webpage.pdf");
Console.WriteLine("PDF from URL created successfully!");
}
}
Imports EO.Pdf
Imports System
Module Program
Sub Main()
Dim url As String = "https://www.example.com"
HtmlToPdf.ConvertUrl(url, "webpage.pdf")
Console.WriteLine("PDF from URL created successfully!")
End Sub
End Module
IronPDF Implementation:
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
string url = "https://www.example.com";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf(url);
pdf.SaveAs("webpage.pdf");
Console.WriteLine("PDF from URL created successfully!");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
string url = "https://www.example.com";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf(url);
pdf.SaveAs("webpage.pdf");
Console.WriteLine("PDF from URL created successfully!");
}
}
Imports IronPdf
Imports System
Class Program
Shared Sub Main()
Dim url As String = "https://www.example.com"
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderUrlAsPdf(url)
pdf.SaveAs("webpage.pdf")
Console.WriteLine("PDF from URL created successfully!")
End Sub
End Class
IronPDF's RenderUrlAsPdf provides full JavaScript execution and modern CSS support. For more options, see the URL to PDF documentation.
HTML File with Custom Settings
This example demonstrates the critical difference in configuration patterns—EO.Pdf's OutputArea with inches versus IronPDF's individual margin properties in millimeters.
EO.Pdf Implementation:
// NuGet: Install-Package EO.Pdf
using EO.Pdf;
using System;
class Program
{
static void Main()
{
HtmlToPdfOptions options = new HtmlToPdfOptions();
options.PageSize = PdfPageSizes.A4;
options.OutputArea = new RectangleF(0.5f, 0.5f, 7.5f, 10.5f);
HtmlToPdf.ConvertUrl("file:///C:/input.html", "output.pdf", options);
Console.WriteLine("PDF with custom settings created.");
}
}
// NuGet: Install-Package EO.Pdf
using EO.Pdf;
using System;
class Program
{
static void Main()
{
HtmlToPdfOptions options = new HtmlToPdfOptions();
options.PageSize = PdfPageSizes.A4;
options.OutputArea = new RectangleF(0.5f, 0.5f, 7.5f, 10.5f);
HtmlToPdf.ConvertUrl("file:///C:/input.html", "output.pdf", options);
Console.WriteLine("PDF with custom settings created.");
}
}
Imports EO.Pdf
Imports System
Class Program
Shared Sub Main()
Dim options As New HtmlToPdfOptions()
options.PageSize = PdfPageSizes.A4
options.OutputArea = New RectangleF(0.5F, 0.5F, 7.5F, 10.5F)
HtmlToPdf.ConvertUrl("file:///C:/input.html", "output.pdf", options)
Console.WriteLine("PDF with custom settings created.")
End Sub
End Class
IronPDF Implementation:
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.MarginTop = 20;
renderer.RenderingOptions.MarginBottom = 20;
renderer.RenderingOptions.MarginLeft = 20;
renderer.RenderingOptions.MarginRight = 20;
var pdf = renderer.RenderHtmlFileAsPdf("C:/input.html");
pdf.SaveAs("output.pdf");
Console.WriteLine("PDF with custom settings created.");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.MarginTop = 20;
renderer.RenderingOptions.MarginBottom = 20;
renderer.RenderingOptions.MarginLeft = 20;
renderer.RenderingOptions.MarginRight = 20;
var pdf = renderer.RenderHtmlFileAsPdf("C:/input.html");
pdf.SaveAs("output.pdf");
Console.WriteLine("PDF with custom settings created.");
}
}
Imports IronPdf
Imports IronPdf.Rendering
Imports System
Class Program
Shared Sub Main()
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
renderer.RenderingOptions.MarginTop = 20
renderer.RenderingOptions.MarginBottom = 20
renderer.RenderingOptions.MarginLeft = 20
renderer.RenderingOptions.MarginRight = 20
Dim pdf = renderer.RenderHtmlFileAsPdf("C:/input.html")
pdf.SaveAs("output.pdf")
Console.WriteLine("PDF with custom settings created.")
End Sub
End Class
Note the unit conversion: EO.Pdf uses inches in OutputArea, while IronPDF uses millimeters. Convert using: inches × 25.4 = mm. For more options, see the rendering options documentation.
Merging Multiple PDFs
Both libraries expose a static PdfDocument.Merge for combining documents — EO.Pdf has no instance Append method, so any code using doc.Append(other) is invalid and needs to move to Merge.
EO.Pdf Implementation:
// NuGet: Install-Package EO.Pdf
using EO.Pdf;
using System;
class Program
{
static void Main()
{
PdfDocument doc1 = new PdfDocument("file1.pdf");
PdfDocument doc2 = new PdfDocument("file2.pdf");
// EO.Pdf has no Append; merge is a static method that returns a new PdfDocument.
PdfDocument mergedDoc = PdfDocument.Merge(doc1, doc2);
mergedDoc.Save("merged.pdf");
Console.WriteLine("PDFs merged successfully!");
}
}
// NuGet: Install-Package EO.Pdf
using EO.Pdf;
using System;
class Program
{
static void Main()
{
PdfDocument doc1 = new PdfDocument("file1.pdf");
PdfDocument doc2 = new PdfDocument("file2.pdf");
// EO.Pdf has no Append; merge is a static method that returns a new PdfDocument.
PdfDocument mergedDoc = PdfDocument.Merge(doc1, doc2);
mergedDoc.Save("merged.pdf");
Console.WriteLine("PDFs merged successfully!");
}
}
Imports EO.Pdf
Imports System
Module Program
Sub Main()
Dim doc1 As New PdfDocument("file1.pdf")
Dim doc2 As New PdfDocument("file2.pdf")
' EO.Pdf has no Append; merge is a static method that returns a new PdfDocument.
Dim mergedDoc As PdfDocument = PdfDocument.Merge(doc1, doc2)
mergedDoc.Save("merged.pdf")
Console.WriteLine("PDFs merged successfully!")
End Sub
End Module
IronPDF Implementation:
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
var pdf1 = PdfDocument.FromFile("file1.pdf");
var pdf2 = PdfDocument.FromFile("file2.pdf");
var merged = PdfDocument.Merge(new List<PdfDocument> { pdf1, pdf2 });
merged.SaveAs("merged.pdf");
Console.WriteLine("PDFs merged successfully!");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
var pdf1 = PdfDocument.FromFile("file1.pdf");
var pdf2 = PdfDocument.FromFile("file2.pdf");
var merged = PdfDocument.Merge(new List<PdfDocument> { pdf1, pdf2 });
merged.SaveAs("merged.pdf");
Console.WriteLine("PDFs merged successfully!");
}
}
Imports IronPdf
Imports System
Imports System.Collections.Generic
Module Program
Sub Main()
Dim pdf1 = PdfDocument.FromFile("file1.pdf")
Dim pdf2 = PdfDocument.FromFile("file2.pdf")
Dim merged = PdfDocument.Merge(New List(Of PdfDocument) From {pdf1, pdf2})
merged.SaveAs("merged.pdf")
Console.WriteLine("PDFs merged successfully!")
End Sub
End Module
IronPDF's static Merge accepts either a params list of documents or a List<PdfDocument>. Note the change from constructor (new PdfDocument(path)) to static factory (PdfDocument.FromFile(path)). For more options, see the PDF merging documentation.
Critical Migration Notes
Margin Unit Conversion
EO.Pdf uses inches in OutputArea. IronPDF uses millimeters. Convert using: inches × 25.4 = mm
// EO.Pdf - 0.5 inch margins
options.OutputArea = new RectangleF(0.5f, 0.5f, 7.5f, 10.5f);
// IronPDF - equivalent in millimeters (0.5" = 12.7mm)
renderer.RenderingOptions.MarginTop = 12.7;
renderer.RenderingOptions.MarginBottom = 12.7;
renderer.RenderingOptions.MarginLeft = 12.7;
renderer.RenderingOptions.MarginRight = 12.7;
// EO.Pdf - 0.5 inch margins
options.OutputArea = new RectangleF(0.5f, 0.5f, 7.5f, 10.5f);
// IronPDF - equivalent in millimeters (0.5" = 12.7mm)
renderer.RenderingOptions.MarginTop = 12.7;
renderer.RenderingOptions.MarginBottom = 12.7;
renderer.RenderingOptions.MarginLeft = 12.7;
renderer.RenderingOptions.MarginRight = 12.7;
' EO.Pdf - 0.5 inch margins
options.OutputArea = New RectangleF(0.5F, 0.5F, 7.5F, 10.5F)
' IronPDF - equivalent in millimeters (0.5" = 12.7mm)
renderer.RenderingOptions.MarginTop = 12.7
renderer.RenderingOptions.MarginBottom = 12.7
renderer.RenderingOptions.MarginLeft = 12.7
renderer.RenderingOptions.MarginRight = 12.7
Static to Instance-Based Configuration
Replace all HtmlToPdf.Options.X with renderer.RenderingOptions.X:
// EO.Pdf - static options (NOT thread-safe!)
HtmlToPdf.Options.PageSize = PdfPageSizes.A4;
// IronPDF - instance options (thread-safe)
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
// EO.Pdf - static options (NOT thread-safe!)
HtmlToPdf.Options.PageSize = PdfPageSizes.A4;
// IronPDF - instance options (thread-safe)
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
ACM to HTML Migration
If using EO.Pdf's Advanced Content Model (AcmRender, AcmText, AcmBlock), migrate to standard HTML/CSS:
// EO.Pdf ACM approach
var acmContent = new AcmContent();
acmContent.Add(new AcmText("Sample Text"));
// IronPDF HTML approach
var html = "<div>Sample Text</div>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
// EO.Pdf ACM approach
var acmContent = new AcmContent();
acmContent.Add(new AcmText("Sample Text"));
// IronPDF HTML approach
var html = "<div>Sample Text</div>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
' EO.Pdf ACM approach
Dim acmContent = New AcmContent()
acmContent.Add(New AcmText("Sample Text"))
' IronPDF HTML approach
Dim html = "<div>Sample Text</div>"
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
Two-Step Save Pattern
EO.Pdf saves directly in ConvertHtml(). IronPDF returns a PdfDocument object, then you call SaveAs():
// EO.Pdf - one step
HtmlToPdf.ConvertHtml(html, "output.pdf");
// IronPDF - two steps (enables manipulation before save)
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
// EO.Pdf - one step
HtmlToPdf.ConvertHtml(html, "output.pdf");
// IronPDF - two steps (enables manipulation before save)
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
' EO.Pdf - one step
HtmlToPdf.ConvertHtml(html, "output.pdf")
' IronPDF - two steps (enables manipulation before save)
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
Constructor to Static Factory
Replace new PdfDocument(path) with PdfDocument.FromFile(path):
// EO.Pdf
var doc = new PdfDocument("file.pdf");
// IronPDF
var doc = PdfDocument.FromFile("file.pdf");
// EO.Pdf
var doc = new PdfDocument("file.pdf");
// IronPDF
var doc = PdfDocument.FromFile("file.pdf");
' EO.Pdf
Dim doc = New PdfDocument("file.pdf")
' IronPDF
Dim doc = PdfDocument.FromFile("file.pdf")
Post-Migration Checklist
After completing the code migration, verify the following:
- Visual comparison of generated PDFs
- Verify headers/footers render correctly
- Test security/encryption settings
- Validate merging operations
- Performance benchmarking
- Cross-platform testing (Windows, Linux, macOS)
- Remove EO.Pdf license files
- Update documentation
Additional Resources
Migrating from EO.Pdf to IronPDF addresses legacy IE/Trident-era baggage and the thread-safety concerns of EO.Pdf's static global options. The transition to instance-based configuration ensures your PDF generation code works reliably under concurrent load, while IronPDF's cross-platform support extends deployment beyond Windows to Linux, macOS, and Docker.

