Skip to footer content
MIGRATION GUIDES

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

  1. Massive 126MB Package Size: EO.Pdf bundles its own Chromium engine, resulting in a 126MB deployment footprint. This inflates Docker images, slows CI/CD pipelines, and increases infrastructure costs.

  2. Legacy Architecture Baggage: EO.Pdf was originally built on Internet Explorer's rendering engine before migrating to Chromium. This legacy introduces compatibility issues from the IE era, technical debt in the API design, and inconsistent behavior between versions.

  3. Windows-Centric Design: Despite marketing as "cross-platform," EO.Pdf's Linux and macOS support is limited. Many developers report issues with non-Windows deployments.

  4. Static Global Options: EO.Pdf uses static HtmlToPdf.Options for configuration, which is not thread-safe and problematic in multi-tenant web applications.

  5. $799 Per License: At $799 per developer license, EO.Pdf is expensive compared to alternatives offering similar or better functionality.

Architecture Comparison

AspectEO.PdfIronPDF
Package Size126MBOptimized (~50MB)
Legacy IssuesIE migration baggageClean, modern codebase
Platform SupportWindows-focusedTrue cross-platform
ConfigurationStatic/global (not thread-safe)Instance-based, thread-safe
API DesignMixed (HtmlToPdf + ACM)Unified, consistent
DocumentationLimitedComprehensive tutorials
Modern .NET.NET Standard.NET 6/7/8/9+ native
Async SupportLimitedFull async/await

Key Migration Benefits

  1. 50% Smaller Footprint: IronPDF's optimized Chromium packaging
  2. True Cross-Platform: Works identically on Windows, Linux, macOS, Docker
  3. Thread-Safe Configuration: Instance-based renderer options
  4. Modern API: Consistent, intuitive method names
  5. Better Documentation: Extensive tutorials and examples

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

Common EO.Pdf namespaces to look for:

  • EO.Pdf - Core HTML to PDF
  • EO.Pdf.Acm - Advanced Content Model (ACM)
  • EO.Pdf.Contents - Low-level content manipulation
  • EO.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
SHELL

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

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

Complete API Migration Reference

Core Class Mapping

EO.Pdf ClassIronPDF EquivalentNotes
HtmlToPdfChromePdfRendererInstance-based
PdfDocumentPdfDocumentSimilar but different methods
HtmlToPdfOptionsChromePdfRenderOptionsVia RenderingOptions
AcmRenderNot neededUse HTML/CSS instead
AcmTextHTML <span>, <p>
AcmBlockHTML <div>

Method Mapping

EO.Pdf MethodIronPDF MethodNotes
HtmlToPdf.ConvertHtml(html, path)renderer.RenderHtmlAsPdf(html) then SaveAs(path)Two-step in IronPDF
HtmlToPdf.ConvertUrl(url, path)renderer.RenderUrlAsPdf(url) then SaveAs(path)
PdfDocument.Save(path)pdf.SaveAs(path)
new PdfDocument(path)PdfDocument.FromFile(path)Static factory
doc.Append(other)PdfDocument.Merge(doc1, doc2)Static merge method

Options Mapping

EO.Pdf OptionIronPDF RenderingOptionsNotes
Options.PageSize = PdfPageSizes.A4PaperSize = PdfPaperSize.A4
Options.OutputArea (RectangleF)MarginTop, MarginBottom, etc.Individual properties in mm

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

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

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

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

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

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

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

PDF merging demonstrates the difference between EO.Pdf's Append loop pattern and IronPDF's static Merge method.

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");

        PdfDocument mergedDoc = new PdfDocument();
        mergedDoc.Append(doc1);
        mergedDoc.Append(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");

        PdfDocument mergedDoc = new PdfDocument();
        mergedDoc.Append(doc1);
        mergedDoc.Append(doc2);

        mergedDoc.Save("merged.pdf");

        Console.WriteLine("PDFs merged successfully!");
    }
}
$vbLabelText   $csharpLabel

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

IronPDF's static Merge method accepts a collection of documents, simplifying multi-document merging. 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;
$vbLabelText   $csharpLabel

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

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

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

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

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

Future-Proofing Your PDF Infrastructure

With .NET 10 on the horizon and C# 14 introducing new language features, choosing a PDF library with modern .NET native support ensures long-term compatibility. IronPDF's instance-based, thread-safe architecture aligns with contemporary web application patterns—particularly important for multi-tenant SaaS applications where EO.Pdf's static global options create concurrency issues.

Additional Resources


Migrating from EO.Pdf to IronPDF eliminates the 126MB package bloat, legacy IE-era baggage, and thread-safety concerns from static global options. The transition to instance-based configuration ensures your PDF generation code works reliably in multi-threaded web applications while providing true cross-platform deployment support.

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