IRONSOFTWAREHOME
MIGRATION GUIDES

How to Migrate from NReco PDF Generator to IronPDF in C#

Curtis Chau
Curtis Chau
Updated: July 19, 2026

Why Migrate from NReco PDF Generator to IronPDF

Critical Security Issues with NReco PDF Generator

NReco PDF Generator wraps the wkhtmltopdf binary, inheriting its known security vulnerabilities. The wkhtmltopdf project's last stable release was 0.12.6 (June 2020) and the upstream repository was archived on January 2, 2023, so no patches are coming:

  • CVE-2020-21365: Directory traversal / local file read via crafted HTML (same-origin policy weakness)
  • CVE-2022-35583: Server-side request forgery (SSRF) via injected <iframe> in 0.12.6 (CVSS 9.8)

Additional NReco PDF Generator Limitations

  1. Licensing friction at scale: Free for non-SaaS single-server production deployments; SaaS, multi-server, or redistribution scenarios require the $199 enterprise source-code pack from nrecosite.com.
  2. Deprecated Rendering Engine: WebKit Qt (circa 2012) with limited CSS3/JS support:
    • No CSS Grid or Flexbox
    • No modern JavaScript (ES6+)
    • Poor web font support
    • No CSS variables or custom properties
  3. External Binary Dependency: Requires managing wkhtmltopdf binaries per platform (wkhtmltopdf.exe, wkhtmltox.dll).
  4. Stalled maintenance: NReco.PdfGenerator 1.2.1 was published Jan 8, 2023 and has had no further releases on nuget.org; the underlying wkhtmltopdf engine is no longer updated.
  5. Limited Async Support: Synchronous API blocks threads in web applications.

NReco PDF Generator vs IronPDF Comparison

AspectNReco PDF GeneratorIronPDF
Rendering EngineWebKit Qt (2012)Chromium (current)
SecurityMultiple unpatched CVEs (e.g., CVE-2020-21365, CVE-2022-35583); engine archived Jan 2, 2023Active security updates
CSS SupportCSS2.1, limited CSS3Full CSS3, Grid, Flexbox
JavaScriptBasic ES5Full ES6+, async/await
DependenciesExternal wkhtmltopdf binarySelf-contained
Async SupportSynchronous onlyFull async/await
Web FontsLimitedFull Google Fonts, @font-face
LicensingFree for non-SaaS single-server; $199 enterprise pack for SaaS / multi-serverTransparent commercial pricing
Free TierFree under non-SaaS single-server licenseTrial requires no watermark

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

# Remove NReco.PdfGenerator
dotnet remove package NReco.PdfGenerator

# Install IronPDF
dotnet add package IronPdf
SHELL

Also remove wkhtmltopdf binaries from your deployment:

  • Delete wkhtmltopdf.exe, wkhtmltox.dll from project
  • Remove any wkhtmltopdf installation scripts
  • Delete platform-specific binary folders

License Configuration

// Add at application startup (Program.cs or Startup.cs)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";

Identify NReco PDF Generator Usage

# Find all NReco.PdfGenerator references
grep -r "NReco.PdfGenerator\|HtmlToPdfConverter\|GeneratePdf" --include="*.cs" .
SHELL

Complete API Reference

Core Class Mappings

NReco PDF GeneratorIronPDF
HtmlToPdfConverterChromePdfRenderer
PageMarginsIndividual margin properties
PageOrientationPdfPaperOrientation
PageSizePdfPaperSize

Rendering Method Mappings

NReco PDF GeneratorIronPDF
GeneratePdf(html)RenderHtmlAsPdf(html)
GeneratePdfFromFile(url, output)RenderUrlAsPdf(url)
GeneratePdfFromFile(htmlPath, output)RenderHtmlFileAsPdf(path)
(async not supported)RenderHtmlAsPdfAsync(html)
(async not supported)RenderUrlAsPdfAsync(url)

Page Configuration Mappings

NReco PDF GeneratorIronPDF
PageWidth = 210RenderingOptions.PaperSize = PdfPaperSize.A4
PageHeight = 297RenderingOptions.SetCustomPaperSizeinMilimeters(w, h)
Orientation = PageOrientation.LandscapeRenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape
Size = PageSize.A4RenderingOptions.PaperSize = PdfPaperSize.A4

Margin Mappings

NReco PDF GeneratorIronPDF
Margins.Top = 10RenderingOptions.MarginTop = 10
Margins.Bottom = 10RenderingOptions.MarginBottom = 10
Margins.Left = 10RenderingOptions.MarginLeft = 10
Margins.Right = 10RenderingOptions.MarginRight = 10
new PageMargins { ... }Individual properties

Header/Footer Placeholder Mappings

NReco PDF Generator (wkhtmltopdf)IronPDF
[page]{page}
[topage]{total-pages}
[date]{date}
[time]{time}
[title]{html-title}

Output Handling Mappings

NReco PDF GeneratorIronPDF
byte[] pdfBytes = GeneratePdf(html)PdfDocument pdf = RenderHtmlAsPdf(html)
File.WriteAllBytes(path, bytes)pdf.SaveAs(path)
return pdfBytesreturn pdf.BinaryData
new MemoryStream(pdfBytes)new MemoryStream(pdf.BinaryData)

Code Migration Examples

Example 1: Basic HTML to PDF

Before (NReco PDF Generator):

// NuGet: Install-Package NReco.PdfGenerator
using NReco.PdfGenerator;
using System.IO;

class Program
{
    static void Main()
    {
        var htmlToPdf = new HtmlToPdfConverter();
        var htmlContent = "<html><body><h1>Hello World</h1><p>This is a PDF document.</p></body></html>";
        var pdfBytes = htmlToPdf.GeneratePdf(htmlContent);
        File.WriteAllBytes("output.pdf", pdfBytes);
    }
}

After (IronPDF):

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

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var htmlContent = "<html><body><h1>Hello World</h1><p>This is a PDF document.</p></body></html>";
        var pdf = renderer.RenderHtmlAsPdf(htmlContent);
        pdf.SaveAs("output.pdf");
    }
}

The fundamental difference is in the return type and save pattern. NReco PDF Generator's HtmlToPdfConverter.GeneratePdf() returns a byte[] that you must manually write to disk using File.WriteAllBytes(). IronPDF's ChromePdfRenderer.RenderHtmlAsPdf() returns a PdfDocument object with a built-in SaveAs() method.

This object-oriented approach provides additional benefits: you can manipulate the PDF (add watermarks, merge documents, add security) before saving. If you need the raw bytes for compatibility with existing code, use pdf.BinaryData. See the HTML to PDF documentation for additional rendering options.

Example 2: Custom Page Size with Margins

Before (NReco PDF Generator):

// NuGet: Install-Package NReco.PdfGenerator
using NReco.PdfGenerator;
using System.IO;

class Program
{
    static void Main()
    {
        var htmlToPdf = new HtmlToPdfConverter();
        htmlToPdf.PageWidth = 210;
        htmlToPdf.PageHeight = 297;
        htmlToPdf.Margins = new PageMargins { Top = 10, Bottom = 10, Left = 10, Right = 10 };
        var htmlContent = "<html><body><h1>Custom Page Size</h1><p>A4 size document with margins.</p></body></html>";
        var pdfBytes = htmlToPdf.GeneratePdf(htmlContent);
        File.WriteAllBytes("custom-size.pdf", pdfBytes);
    }
}

After (IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
        renderer.RenderingOptions.MarginTop = 10;
        renderer.RenderingOptions.MarginBottom = 10;
        renderer.RenderingOptions.MarginLeft = 10;
        renderer.RenderingOptions.MarginRight = 10;
        var htmlContent = "<html><body><h1>Custom Page Size</h1><p>A4 size document with margins.</p></body></html>";
        var pdf = renderer.RenderHtmlAsPdf(htmlContent);
        pdf.SaveAs("custom-size.pdf");
    }
}

NReco PDF Generator uses numeric dimensions (PageWidth = 210, PageHeight = 297) and a PageMargins object. IronPDF uses the PdfPaperSize enum (which includes standard sizes like A4, Letter, Legal) and individual margin properties on the RenderingOptions object.

The key migration changes:

  • PageWidth/PageHeightRenderingOptions.PaperSize = PdfPaperSize.A4
  • new PageMargins { Top = 10, ... } → Individual properties: RenderingOptions.MarginTop = 10

For custom paper sizes not covered by the enum, use RenderingOptions.SetCustomPaperSizeinMilimeters(width, height). Learn more about page configuration options.

Example 3: URL to PDF Conversion

Before (NReco PDF Generator):

// NuGet: Install-Package NReco.PdfGenerator
using NReco.PdfGenerator;
using System.IO;

class Program
{
    static void Main()
    {
        var htmlToPdf = new HtmlToPdfConverter();
        var pdfBytes = htmlToPdf.GeneratePdfFromFile("https://www.example.com", null);
        File.WriteAllBytes("webpage.pdf", pdfBytes);
    }
}

After (IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
        pdf.SaveAs("webpage.pdf");
    }
}

NReco PDF Generator uses the confusingly named GeneratePdfFromFile() method for both local files and URLs, with a nullable second parameter. IronPDF provides dedicated methods: RenderUrlAsPdf() for URLs and RenderHtmlFileAsPdf() for local HTML files.

The IronPDF approach is cleaner and more intuitive. For async web applications, use await renderer.RenderUrlAsPdfAsync(url) to avoid blocking threads - something NReco PDF Generator simply cannot do.


Critical Migration Notes

Zoom Value Conversion

NReco PDF Generator uses float values (0.0-2.0), while IronPDF uses percentage integers:

// NReco PDF Generator: Zoom = 0.9f (90%)
// IronPDF: Zoom = 90

// Conversion formula:
int ironPdfZoom = (int)(nrecoZoom * 100);

Placeholder Syntax Update

All header/footer placeholders must be updated:

NReco PDF GeneratorIronPDF
[page]{page}
[topage]{total-pages}
[date]{date}
[title]{html-title}
// NReco PDF Generator:
converter.PageFooterHtml = "<div>Page [page] of [topage]</div>";

// IronPDF:
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
    HtmlFragment = "<div>Page {page} of {total-pages}</div>",
    MaxHeight = 20
};

Return Type Change

NReco PDF Generator returns byte[] directly; IronPDF returns PdfDocument:

// NReco PDF Generator pattern:
byte[] pdfBytes = converter.GeneratePdf(html);
File.WriteAllBytes("output.pdf", pdfBytes);

// IronPDF pattern:
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");

// Or if you need bytes:
byte[] pdfBytes = renderer.RenderHtmlAsPdf(html).BinaryData;

Thread Safety and Reusability

NReco PDF Generator typically creates a new converter per call. IronPDF's ChromePdfRenderer is thread-safe and can be reused:

// NReco PDF Generator pattern (creates new each time):
public byte[] Generate(string html)
{
    var converter = new HtmlToPdfConverter();
    return converter.GeneratePdf(html);
}

// IronPDF pattern (reuse renderer, thread-safe):
private readonly ChromePdfRenderer _renderer = new ChromePdfRenderer();

public byte[] Generate(string html)
{
    return _renderer.RenderHtmlAsPdf(html).BinaryData;
}

Async Support (New Capability)

IronPDF supports async/await patterns that NReco PDF Generator cannot provide:

// NReco PDF Generator: No async support available

// IronPDF: Full async support
public async Task<byte[]> GenerateAsync(string html)
{
    var pdf = await _renderer.RenderHtmlAsPdfAsync(html);
    return pdf.BinaryData;
}

Troubleshooting

Issue 1: HtmlToPdfConverter Not Found

Problem: HtmlToPdfConverter class doesn't exist in IronPDF.

Solution: Use ChromePdfRenderer:

// NReco PDF Generator
var converter = new HtmlToPdfConverter();

// IronPDF
var renderer = new ChromePdfRenderer();

Issue 2: GeneratePdf Returns Wrong Type

Problem: Code expects byte[] but gets PdfDocument.

Solution: Access .BinaryData property:

// NReco PDF Generator
byte[] pdfBytes = converter.GeneratePdf(html);

// IronPDF
byte[] pdfBytes = renderer.RenderHtmlAsPdf(html).BinaryData;

Issue 3: PageMargins Object Not Found

Problem: PageMargins class doesn't exist in IronPDF.

Solution: Use individual margin properties:

// NReco PDF Generator
converter.Margins = new PageMargins { Top = 10, Bottom = 10, Left = 10, Right = 10 };

// IronPDF
renderer.RenderingOptions.MarginTop = 10;
renderer.RenderingOptions.MarginBottom = 10;
renderer.RenderingOptions.MarginLeft = 10;
renderer.RenderingOptions.MarginRight = 10;

Issue 4: Page Numbers Not Appearing

Problem: [page] and [topage] placeholders don't work.

Solution: Update to IronPDF placeholder syntax:

// NReco PDF Generator
converter.PageFooterHtml = "<div>Page [page] of [topage]</div>";

// IronPDF
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
    HtmlFragment = "<div>Page {page} of {total-pages}</div>",
    MaxHeight = 20
};

Migration Checklist

Pre-Migration

  • Inventory all NReco.PdfGenerator usages in codebase
  • Document all CustomWkHtmlArgs and CustomWkHtmlPageArgs values
  • List all header/footer HTML templates with placeholders
  • Identify async requirements (web controllers, services)
  • Review zoom and margin settings
  • Backup existing PDF outputs for comparison
  • Obtain IronPDF license key

Package Changes

  • Remove NReco.PdfGenerator NuGet package
  • Install IronPdf NuGet package: dotnet add package IronPdf
  • Update namespace imports from using NReco.PdfGenerator; to using IronPdf;

Code Changes

  • Add license key configuration at startup
  • Replace HtmlToPdfConverter with ChromePdfRenderer
  • Replace GeneratePdf(html) with RenderHtmlAsPdf(html)
  • Replace GeneratePdfFromFile(url, null) with RenderUrlAsPdf(url)
  • Convert PageMargins object to individual margin properties
  • Update zoom values from float to percentage
  • Update placeholder syntax: [page]{page}, [topage]{total-pages}
  • Replace File.WriteAllBytes() with pdf.SaveAs()
  • Convert sync calls to async where beneficial

Post-Migration

  • Remove wkhtmltopdf binaries from project/deployment
  • Update Docker files to remove wkhtmltopdf installation
  • Run regression tests comparing PDF output
  • Verify header/footer placeholders render correctly
  • Test on all target platforms (Windows, Linux, macOS)
  • Update CI/CD pipeline to remove wkhtmltopdf steps
  • Update security scanning to confirm CVE removal

Please note: NReco and wkhtmltopdf are registered trademarks of their respective owners. This site is not affiliated with, endorsed by, or sponsored by NReco or wkhtmltopdf. All product names, logos, and brands are property of their respective owners. Comparisons are for informational purposes only and reflect publicly available information at the time of writing.
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

Related Articles

Key in blue circle

Get your free 30-day Trial Key instantly.

Your trial license will be sent to your email address

No limitations. 100% unlocked. No credit card.

bullet_checkedNo credit card or account creation requiredNo limitations. 100% unlocked. No credit card.
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
Book your free Live Demo
Booking Badge

Trusted by Millions of Engineers Worldwide

Iron Software's customer logos
Get Your No-Obligation Consult
Complete the form below or email sales@ironsoftware.com
Your details will always be kept confidential.
Trusted by Millions of Engineers Worldwide
Iron Software's customer logos
Get your free 30-day Trial Key instantly.
No credit card or account creation required