Skip to footer content
MIGRATION GUIDES

How to Migrate from Rotativa to IronPDF in C#

Migrating from Rotativa to IronPDF addresses critical security vulnerabilities while modernizing your PDF generation workflow. This guide provides a complete, step-by-step migration path that eliminates the abandoned wkhtmltopdf dependency, enables support for modern CSS and JavaScript, and provides cross-platform compatibility beyond ASP.NET MVC.

Why Migrate from Rotativa to IronPDF

Understanding Rotativa

Rotativa has long been a popular choice among developers for generating PDFs in C#. It leverages the wkhtmltopdf tool to convert HTML content into PDF format. Rotativa is an open-source library specifically designed for ASP.NET MVC applications. However, while it has attracted a significant audience, Rotativa's reliance on an outdated technology stack presents challenges that might not be immediately evident to every developer.

At its core, Rotativa provides a simple way to integrate PDF generation into ASP.NET MVC projects, taking advantage of wkhtmltopdf for its backend functionalities.

Critical Security Advisory

Rotativa wraps wkhtmltopdf, which has CRITICAL UNPATCHED SECURITY VULNERABILITIES.

AttributeValue
CVE IDCVE-2022-35583
SeverityCRITICAL (9.8/10)
Attack VectorNetwork
StatusWILL NEVER BE PATCHED
AffectedALL Rotativa versions

wkhtmltopdf was officially abandoned in December 2022. The maintainers explicitly stated they will NOT fix security vulnerabilities. Every application using Rotativa is permanently exposed.

How the Attack Works


<iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/"></iframe>
<img src="http://internal-database:5432/admin" />

<iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/"></iframe>
<img src="http://internal-database:5432/admin" />
HTML

Impact:

  • Access AWS/Azure/GCP cloud metadata endpoints
  • Steal internal API data and credentials
  • Port scan internal networks
  • Exfiltrate sensitive configuration

The Technology Crisis

Rotativa wraps wkhtmltopdf, which uses:

  • Qt WebKit 4.8 (from 2012)
  • No Flexbox support
  • No CSS Grid support
  • Broken JavaScript execution
  • No ES6+ support

Rotativa vs IronPDF Comparison

FeatureRotativaIronPDF
Project CompatibilityASP.NET MVC OnlyAny .NET Project Type (MVC, Razor Pages, Blazor, etc.)
MaintenanceAbandonedActively Maintained
SecurityVulnerable due to wkhtmltopdf dependencies (CVE-2022-35583)Regular updates and security patches
HTML RenderingOutdated WebKitModern Chromium
CSS3PartialSupported
Flexbox/GridNot supportedSupported
JavaScriptUnreliableFull ES6+
Razor PagesNot supportedSupported
BlazorNot supportedSupported
PDF ManipulationNot availableFull
Digital SignaturesNot availableFull
PDF/A ComplianceNot availableFull
Async/AwaitSynchronous onlyFull async
Open SourceYes, MIT LicenseNo, Commercial License

For teams planning .NET 10 and C# 14 adoption through 2025 and 2026, IronPDF provides modern Chromium rendering and cross-platform support that Rotativa cannot offer.


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 Rotativa
dotnet remove package Rotativa
dotnet remove package Rotativa.AspNetCore

# Install IronPDF
dotnet add package IronPdf
# Remove Rotativa
dotnet remove package Rotativa
dotnet remove package Rotativa.AspNetCore

# Install IronPDF
dotnet add package IronPdf
SHELL

Remove wkhtmltopdf Binaries

Delete these files from your project:

  • wkhtmltopdf.exe
  • wkhtmltox.dll
  • Any Rotativa/ folders

These are the source of CVE-2022-35583. IronPDF needs no native binaries.

License Configuration

// Add in Program.cs or Startup.cs
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Add in Program.cs or Startup.cs
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
' Add in Program.vb or Startup.vb
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
$vbLabelText   $csharpLabel

Complete API Reference

Namespace Changes

// Before: Rotativa
using Rotativa;
using Rotativa.Options;
using Rotativa.AspNetCore;

// After: IronPDF
using IronPdf;
using IronPdf.Rendering;
// Before: Rotativa
using Rotativa;
using Rotativa.Options;
using Rotativa.AspNetCore;

// After: IronPDF
using IronPdf;
using IronPdf.Rendering;
' Before: Rotativa
Imports Rotativa
Imports Rotativa.Options
Imports Rotativa.AspNetCore

' After: IronPDF
Imports IronPdf
Imports IronPdf.Rendering
$vbLabelText   $csharpLabel

Core Class Mappings

Rotativa ClassIronPDF Equivalent
ViewAsPdfChromePdfRenderer
ActionAsPdfChromePdfRenderer.RenderUrlAsPdf()
UrlAsPdfChromePdfRenderer.RenderUrlAsPdf()
Orientation enumPdfPaperOrientation enum
Size enumPdfPaperSize enum

Page Placeholder Conversion

Rotativa PlaceholderIronPDF Placeholder
[page]{page}
[topage]{total-pages}
[date]{date}
[time]{time}
[title]{html-title}
[sitepage]{url}

Code Migration Examples

Example 1: HTML to PDF Conversion

Before (Rotativa):

// NuGet: Install-Package Rotativa.Core
using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using System.Threading.Tasks;

namespace RotativaExample
{
    public class PdfController : Controller
    {
        public async Task<IActionResult> GeneratePdf()
        {
            var htmlContent = "<h1>Hello World</h1><p>This is a PDF document.</p>";

            // Rotativa requires returning a ViewAsPdf result from MVC controller
            return new ViewAsPdf()
            {
                ViewName = "PdfView",
                PageSize = Rotativa.AspNetCore.Options.Size.A4
            };
        }
    }
}
// NuGet: Install-Package Rotativa.Core
using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using System.Threading.Tasks;

namespace RotativaExample
{
    public class PdfController : Controller
    {
        public async Task<IActionResult> GeneratePdf()
        {
            var htmlContent = "<h1>Hello World</h1><p>This is a PDF document.</p>";

            // Rotativa requires returning a ViewAsPdf result from MVC controller
            return new ViewAsPdf()
            {
                ViewName = "PdfView",
                PageSize = Rotativa.AspNetCore.Options.Size.A4
            };
        }
    }
}
Imports Microsoft.AspNetCore.Mvc
Imports Rotativa.AspNetCore
Imports System.Threading.Tasks

Namespace RotativaExample
    Public Class PdfController
        Inherits Controller

        Public Async Function GeneratePdf() As Task(Of IActionResult)
            Dim htmlContent As String = "<h1>Hello World</h1><p>This is a PDF document.</p>"

            ' Rotativa requires returning a ViewAsPdf result from MVC controller
            Return New ViewAsPdf() With {
                .ViewName = "PdfView",
                .PageSize = Rotativa.AspNetCore.Options.Size.A4
            }
        End Function
    End Class
End Namespace
$vbLabelText   $csharpLabel

After (IronPDF):

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

namespace IronPdfExample
{
    class Program
    {
        static void Main(string[] args)
        {
            var renderer = new ChromePdfRenderer();
            var htmlContent = "<h1>Hello World</h1><p>This is a PDF document.</p>";

            var pdf = renderer.RenderHtmlAsPdf(htmlContent);
            pdf.SaveAs("output.pdf");

            Console.WriteLine("PDF generated successfully!");
        }
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;

namespace IronPdfExample
{
    class Program
    {
        static void Main(string[] args)
        {
            var renderer = new ChromePdfRenderer();
            var htmlContent = "<h1>Hello World</h1><p>This is a PDF document.</p>";

            var pdf = renderer.RenderHtmlAsPdf(htmlContent);
            pdf.SaveAs("output.pdf");

            Console.WriteLine("PDF generated successfully!");
        }
    }
}
Imports IronPdf
Imports System

Namespace IronPdfExample
    Class Program
        Shared Sub Main(ByVal args As String())
            Dim renderer = New ChromePdfRenderer()
            Dim htmlContent = "<h1>Hello World</h1><p>This is a PDF document.</p>"

            Dim pdf = renderer.RenderHtmlAsPdf(htmlContent)
            pdf.SaveAs("output.pdf")

            Console.WriteLine("PDF generated successfully!")
        End Sub
    End Class
End Namespace
$vbLabelText   $csharpLabel

This example demonstrates the fundamental architectural difference. Rotativa requires returning a ViewAsPdf result from an MVC controller action, tying you to the ASP.NET MVC framework. The pattern only works within the MVC request pipeline and requires a Razor view to render.

IronPDF works anywhere: console applications, web APIs, Blazor, Razor Pages, or any .NET project type. You call RenderHtmlAsPdf() with an HTML string and save the result. No MVC controller required, no view dependency. See the HTML to PDF documentation for comprehensive examples.

Example 2: URL to PDF Conversion

Before (Rotativa):

// NuGet: Install-Package Rotativa.Core
using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using System.Threading.Tasks;

namespace RotativaExample
{
    public class UrlPdfController : Controller
    {
        public async Task<IActionResult> ConvertUrlToPdf()
        {
            // Rotativa works within MVC framework and returns ActionResult
            return new UrlAsPdf("https://www.example.com")
            {
                FileName = "webpage.pdf",
                PageSize = Rotativa.AspNetCore.Options.Size.A4,
                PageOrientation = Rotativa.AspNetCore.Options.Orientation.Portrait
            };
        }
    }
}
// NuGet: Install-Package Rotativa.Core
using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using System.Threading.Tasks;

namespace RotativaExample
{
    public class UrlPdfController : Controller
    {
        public async Task<IActionResult> ConvertUrlToPdf()
        {
            // Rotativa works within MVC framework and returns ActionResult
            return new UrlAsPdf("https://www.example.com")
            {
                FileName = "webpage.pdf",
                PageSize = Rotativa.AspNetCore.Options.Size.A4,
                PageOrientation = Rotativa.AspNetCore.Options.Orientation.Portrait
            };
        }
    }
}
' NuGet: Install-Package Rotativa.Core
Imports Microsoft.AspNetCore.Mvc
Imports Rotativa.AspNetCore
Imports System.Threading.Tasks

Namespace RotativaExample
    Public Class UrlPdfController
        Inherits Controller

        Public Async Function ConvertUrlToPdf() As Task(Of IActionResult)
            ' Rotativa works within MVC framework and returns ActionResult
            Return New UrlAsPdf("https://www.example.com") With {
                .FileName = "webpage.pdf",
                .PageSize = Rotativa.AspNetCore.Options.Size.A4,
                .PageOrientation = Rotativa.AspNetCore.Options.Orientation.Portrait
            }
        End Function
    End Class
End Namespace
$vbLabelText   $csharpLabel

After (IronPDF):

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

namespace IronPdfExample
{
    class Program
    {
        static void Main(string[] args)
        {
            var renderer = new ChromePdfRenderer();

            var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
            pdf.SaveAs("webpage.pdf");

            Console.WriteLine("URL converted to PDF successfully!");
        }
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;

namespace IronPdfExample
{
    class Program
    {
        static void Main(string[] args)
        {
            var renderer = new ChromePdfRenderer();

            var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
            pdf.SaveAs("webpage.pdf");

            Console.WriteLine("URL converted to PDF successfully!");
        }
    }
}
Imports IronPdf
Imports System

Namespace IronPdfExample
    Class Program
        Shared Sub Main(ByVal args As String())
            Dim renderer = New ChromePdfRenderer()

            Dim pdf = renderer.RenderUrlAsPdf("https://www.example.com")
            pdf.SaveAs("webpage.pdf")

            Console.WriteLine("URL converted to PDF successfully!")
        End Sub
    End Class
End Namespace
$vbLabelText   $csharpLabel

Rotativa's UrlAsPdf class requires returning an ActionResult from an MVC controller. IronPDF's RenderUrlAsPdf() method can be called from any context and returns a PdfDocument object directly. The URL rendering uses modern Chromium instead of wkhtmltopdf's vulnerable and outdated WebKit engine. Learn more in our tutorials.

Example 3: Headers and Footers with Page Numbers

Before (Rotativa):

// NuGet: Install-Package Rotativa.Core
using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using Rotativa.AspNetCore.Options;
using System.Threading.Tasks;

namespace RotativaExample
{
    public class HeaderFooterController : Controller
    {
        public async Task<IActionResult> GeneratePdfWithHeaderFooter()
        {
            return new ViewAsPdf("Report")
            {
                PageSize = Size.A4,
                PageMargins = new Margins(20, 10, 20, 10),
                CustomSwitches = "--header-center \"Page Header\" --footer-center \"Page [page] of [toPage]\""
            };
        }
    }
}
// NuGet: Install-Package Rotativa.Core
using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using Rotativa.AspNetCore.Options;
using System.Threading.Tasks;

namespace RotativaExample
{
    public class HeaderFooterController : Controller
    {
        public async Task<IActionResult> GeneratePdfWithHeaderFooter()
        {
            return new ViewAsPdf("Report")
            {
                PageSize = Size.A4,
                PageMargins = new Margins(20, 10, 20, 10),
                CustomSwitches = "--header-center \"Page Header\" --footer-center \"Page [page] of [toPage]\""
            };
        }
    }
}
Imports Microsoft.AspNetCore.Mvc
Imports Rotativa.AspNetCore
Imports Rotativa.AspNetCore.Options
Imports System.Threading.Tasks

Namespace RotativaExample
    Public Class HeaderFooterController
        Inherits Controller

        Public Async Function GeneratePdfWithHeaderFooter() As Task(Of IActionResult)
            Return New ViewAsPdf("Report") With {
                .PageSize = Size.A4,
                .PageMargins = New Margins(20, 10, 20, 10),
                .CustomSwitches = "--header-center ""Page Header"" --footer-center ""Page [page] of [toPage]"""
            }
        End Function
    End Class
End Namespace
$vbLabelText   $csharpLabel

After (IronPDF):

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

namespace IronPdfExample
{
    class Program
    {
        static void Main(string[] args)
        {
            var renderer = new ChromePdfRenderer();

            renderer.RenderingOptions.TextHeader = new TextHeaderFooter()
            {
                CenterText = "Page Header",
                DrawDividerLine = true
            };

            renderer.RenderingOptions.TextFooter = new TextHeaderFooter()
            {
                CenterText = "Page {page} of {total-pages}",
                DrawDividerLine = true
            };

            var htmlContent = "<h1>Report Title</h1><p>Report content goes here.</p>";
            var pdf = renderer.RenderHtmlAsPdf(htmlContent);
            pdf.SaveAs("report.pdf");

            Console.WriteLine("PDF with headers and footers created successfully!");
        }
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;

namespace IronPdfExample
{
    class Program
    {
        static void Main(string[] args)
        {
            var renderer = new ChromePdfRenderer();

            renderer.RenderingOptions.TextHeader = new TextHeaderFooter()
            {
                CenterText = "Page Header",
                DrawDividerLine = true
            };

            renderer.RenderingOptions.TextFooter = new TextHeaderFooter()
            {
                CenterText = "Page {page} of {total-pages}",
                DrawDividerLine = true
            };

            var htmlContent = "<h1>Report Title</h1><p>Report content goes here.</p>";
            var pdf = renderer.RenderHtmlAsPdf(htmlContent);
            pdf.SaveAs("report.pdf");

            Console.WriteLine("PDF with headers and footers created successfully!");
        }
    }
}
Imports IronPdf
Imports IronPdf.Rendering
Imports System

Namespace IronPdfExample
    Class Program
        Shared Sub Main(ByVal args As String())
            Dim renderer = New ChromePdfRenderer()

            renderer.RenderingOptions.TextHeader = New TextHeaderFooter() With {
                .CenterText = "Page Header",
                .DrawDividerLine = True
            }

            renderer.RenderingOptions.TextFooter = New TextHeaderFooter() With {
                .CenterText = "Page {page} of {total-pages}",
                .DrawDividerLine = True
            }

            Dim htmlContent = "<h1>Report Title</h1><p>Report content goes here.</p>"
            Dim pdf = renderer.RenderHtmlAsPdf(htmlContent)
            pdf.SaveAs("report.pdf")

            Console.WriteLine("PDF with headers and footers created successfully!")
        End Sub
    End Class
End Namespace
$vbLabelText   $csharpLabel

Rotativa uses CustomSwitches to pass command-line arguments to wkhtmltopdf, including header and footer configuration with placeholders like [page] and [toPage]. This string-based approach is error-prone and hard to validate at compile time.

IronPDF uses strongly-typed TextHeaderFooter objects with properties like CenterText and DrawDividerLine. The placeholder syntax changes from [page] to {page} and from [toPage] to {total-pages}. Typed properties provide IntelliSense, compile-time checking, and no risk of typos.


The MVC-Only Architecture Problem

Rotativa was designed for ASP.NET MVC 5 and earlier:

// ❌ Rotativa - Only works with classic MVC pattern
public class InvoiceController : Controller
{
    public ActionResult InvoicePdf(int id)
    {
        var model = GetInvoice(id);
        return new ViewAsPdf("Invoice", model);  // Tied to MVC Views
    }
}

// Problems:
// - No Razor Pages support
// - No Blazor support
// - No minimal APIs support
// - No ASP.NET Core native integration
// ❌ Rotativa - Only works with classic MVC pattern
public class InvoiceController : Controller
{
    public ActionResult InvoicePdf(int id)
    {
        var model = GetInvoice(id);
        return new ViewAsPdf("Invoice", model);  // Tied to MVC Views
    }
}

// Problems:
// - No Razor Pages support
// - No Blazor support
// - No minimal APIs support
// - No ASP.NET Core native integration
' ❌ Rotativa - Only works with classic MVC pattern
Public Class InvoiceController
    Inherits Controller

    Public Function InvoicePdf(id As Integer) As ActionResult
        Dim model = GetInvoice(id)
        Return New ViewAsPdf("Invoice", model)  ' Tied to MVC Views
    End Function
End Class

' Problems:
' - No Razor Pages support
' - No Blazor support
' - No minimal APIs support
' - No ASP.NET Core native integration
$vbLabelText   $csharpLabel

IronPDF separates view rendering from PDF generation, which is actually more flexible—you can render any HTML, not just MVC views.


Async Pattern Migration

Rotativa blocks the thread; IronPDF supports full async/await:

// ❌ Rotativa - Blocks the thread
public ActionResult GeneratePdf()
{
    return new ViewAsPdf("Report");
    // This blocks the request thread until PDF is complete
    // Poor scalability under load
}

// ✅ IronPDF - Full async support
public async Task<IActionResult> GeneratePdf()
{
    var renderer = new ChromePdfRenderer();
    var pdf = await renderer.RenderHtmlAsPdfAsync(html);
    return File(pdf.BinaryData, "application/pdf");
    // Non-blocking, better scalability
}
// ❌ Rotativa - Blocks the thread
public ActionResult GeneratePdf()
{
    return new ViewAsPdf("Report");
    // This blocks the request thread until PDF is complete
    // Poor scalability under load
}

// ✅ IronPDF - Full async support
public async Task<IActionResult> GeneratePdf()
{
    var renderer = new ChromePdfRenderer();
    var pdf = await renderer.RenderHtmlAsPdfAsync(html);
    return File(pdf.BinaryData, "application/pdf");
    // Non-blocking, better scalability
}
' ❌ Rotativa - Blocks the thread
Public Function GeneratePdf() As ActionResult
    Return New ViewAsPdf("Report")
    ' This blocks the request thread until PDF is complete
    ' Poor scalability under load
End Function

' ✅ IronPDF - Full async support
Public Async Function GeneratePdf() As Task(Of IActionResult)
    Dim renderer = New ChromePdfRenderer()
    Dim pdf = Await renderer.RenderHtmlAsPdfAsync(html)
    Return File(pdf.BinaryData, "application/pdf")
    ' Non-blocking, better scalability
End Function
$vbLabelText   $csharpLabel

New Capabilities After Migration

After migrating to IronPDF, you gain capabilities that Rotativa cannot provide:

PDF Merging

var merged = PdfDocument.Merge(pdf1, pdf2, pdf3);
merged.SaveAs("complete.pdf");
var merged = PdfDocument.Merge(pdf1, pdf2, pdf3);
merged.SaveAs("complete.pdf");
Dim merged = PdfDocument.Merge(pdf1, pdf2, pdf3)
merged.SaveAs("complete.pdf")
$vbLabelText   $csharpLabel

Digital Signatures

var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);
var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);
Dim signature = New PdfSignature("certificate.pfx", "password")
pdf.Sign(signature)
$vbLabelText   $csharpLabel

Password Protection

pdf.SecuritySettings.UserPassword = "secret";
pdf.SecuritySettings.UserPassword = "secret";
pdf.SecuritySettings.UserPassword = "secret"
$vbLabelText   $csharpLabel

Watermarks

pdf.ApplyWatermark("<h1 style='color:red; opacity:0.3;'>DRAFT</h1>");
pdf.ApplyWatermark("<h1 style='color:red; opacity:0.3;'>DRAFT</h1>");
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

PDF/A Archival Compliance

pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b);
pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b);
pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b)
$vbLabelText   $csharpLabel

Modern CSS Support

// This now works (broke in Rotativa)
var html = @"
    <div style='display: flex; justify-content: space-between;'>
        <div>Left</div>
        <div>Right</div>
    </div>
    <div style='display: grid; grid-template-columns: 1fr 1fr 1fr;'>
        <div>Col 1</div><div>Col 2</div><div>Col 3</div>
    </div>";
var pdf = renderer.RenderHtmlAsPdf(html);  // Works!
// This now works (broke in Rotativa)
var html = @"
    <div style='display: flex; justify-content: space-between;'>
        <div>Left</div>
        <div>Right</div>
    </div>
    <div style='display: grid; grid-template-columns: 1fr 1fr 1fr;'>
        <div>Col 1</div><div>Col 2</div><div>Col 3</div>
    </div>";
var pdf = renderer.RenderHtmlAsPdf(html);  // Works!
' This now works (broke in Rotativa)
Dim html As String = "
    <div style='display: flex; justify-content: space-between;'>
        <div>Left</div>
        <div>Right</div>
    </div>
    <div style='display: grid; grid-template-columns: 1fr 1fr 1fr;'>
        <div>Col 1</div><div>Col 2</div><div>Col 3</div>
    </div>"
Dim pdf = renderer.RenderHtmlAsPdf(html)  ' Works!
$vbLabelText   $csharpLabel

Migration Checklist

Pre-Migration

  • Identify all Rotativa usage in codebase
  • Document CustomSwitches used for conversion to RenderingOptions
  • Note header/footer placeholder syntax for conversion ([page]{page})
  • Obtain IronPDF license key from ironpdf.com

Package Changes

  • Remove Rotativa and Rotativa.AspNetCore NuGet packages
  • Delete wkhtmltopdf binaries (wkhtmltopdf.exe, wkhtmltox.dll)
  • Install IronPdf NuGet package

Code Changes

  • Update namespace imports (using Rotativa;using IronPdf;)
  • Replace ViewAsPdf with ChromePdfRenderer + RenderHtmlAsPdf()
  • Replace UrlAsPdf with RenderUrlAsPdf()
  • Convert CustomSwitches to RenderingOptions properties
  • Update placeholder syntax ([page]{page}, [topage]{total-pages})
  • Replace PageMargins with individual MarginTop/MarginBottom/MarginLeft/MarginRight
  • Change to async pattern where appropriate
  • Add license initialization at application startup

Post-Migration

  • Verify all PDF generation works correctly
  • Compare PDF output quality (Chromium renders more accurately)
  • Verify CSS rendering improvements (Flexbox/Grid now work)
  • Test JavaScript execution (now reliable with Chromium)
  • Verify security scan passes (no more CVE-2022-35583 flags)
  • Update Docker configurations to remove wkhtmltopdf installation

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