Skip to footer content
MIGRATION GUIDES

How to Migrate from Kaizen.io to IronPDF in C#

Migrating from Kaizen.io HTML-to-PDF to IronPDF replaces a self-hosted Docker container exposed over HTTP with an in-process .NET library. Kaizen.io HTML-to-PDF ships only as the Docker image kaizenio.azurecr.io/html-to-pdf and exposes a single REST endpoint at POST /html-to-pdf on port 8080 — there is no official .NET SDK or NuGet package, so every C# call has to be hand-rolled HttpClient against the running container. This guide walks through swapping that pattern for IronPDF's ChromePdfRenderer.

Why Migrate from Kaizen.io to IronPDF

The Container-API Challenges

Kaizen.io HTML-to-PDF is a Docker container with a deliberately small v1.x API, and the C# integration story is whatever you build yourself on top of HttpClient. That shape has real limits in production:

  1. Container to Operate: You run, monitor, and update kaizenio.azurecr.io/html-to-pdf:latest somewhere reachable from your app — local Docker, sidecar, or a separate host.

  2. No .NET SDK: Every C# call is hand-rolled HttpClient POST + JSON. No IntelliSense, no compile-time checks on the request shape.

  3. Tiny v1.x API Surface: The documented JSON body accepts only an html field. URL-to-PDF, custom stylesheets, headers/footers, page size, orientation, and margins are listed as roadmap items rather than shipping features — anything beyond rendering a string of HTML must be expressed inside the HTML itself, typically via @page CSS and absolute-positioned divs.

  4. No Page-Number Support: The API has no {page} / {total} placeholders, so "Page X of Y" footers cannot be produced server-side.

  5. HTTP Round-Trip Per PDF: Even when the container runs on localhost, every PDF pays JSON serialization and a socket hop.

  6. Watermark on Free Tier: Without the KAIZEN_PDF_LICENSE environment variable set on the container, output is watermarked.

Kaizen.io vs IronPDF Comparison

Feature Kaizen.io HTML-to-PDF IronPDF
Distribution Docker image kaizenio.azurecr.io/html-to-pdf NuGet IronPdf
C# Integration Hand-rolled HttpClient POST (no SDK) Strongly-typed ChromePdfRenderer API
Process Model Out-of-process container In-process
Endpoint Surface (v1.x) POST /html-to-pdf with { "html": ... } Methods for HTML, file, URL
URL Input Roadmap RenderUrlAsPdf(url)
Headers / Footers Not in v1.x API; fake via fixed-position CSS TextHeader/Footer and HtmlHeader/Footer
Page Numbers Unsupported {page} and {total-pages} placeholders
Page Size / Orientation Embed @page CSS in HTML RenderingOptions.PaperSize etc.
Licensing One-time license; watermarked free tier Commercial (annual or perpetual)

For teams standardizing on modern .NET, IronPDF removes the sidecar container and HTTP hop from the request path while exposing a strongly-typed configuration surface.


Migration Complexity Assessment

Estimated Effort by Feature

Feature Migration Complexity
Basic HTML to PDF Very Low
HTML File to PDF Very Low
URL to PDF Low (Kaizen v1.x has no URL endpoint — workaround is replaced wholesale)
Headers/Footers Medium (fake CSS divs replaced with real header zones)
Page Numbers New capability (not available in Kaizen v1.x)
Page Settings Low (@page CSS moves to RenderingOptions)

Paradigm Shift

The fundamental shift is from out-of-process HTTP calls to a Docker container to in-process rendering:

Kaizen.io:  HttpClient.PostAsync("http://.../html-to-pdf", { html }) → byte[]
IronPDF:    ChromePdfRenderer → RenderHtmlAsPdf(html) → PdfDocument

Before You Start

Prerequisites

  1. .NET Environment: .NET Framework 4.6.2+ or .NET Core 3.1+ / .NET 5+
  2. NuGet Access: Ability to install NuGet packages
  3. IronPDF License: Obtain your license key from ironpdf.com

Package Changes

There is no Kaizen NuGet package to remove — Kaizen ships only as a Docker image. Stop the container and add the IronPDF package:

# Stop and remove the running Kaizen container (if any)
docker stop kaizen-pdf
docker rm kaizen-pdf

# Install IronPDF
dotnet add package IronPdf
# Stop and remove the running Kaizen container (if any)
docker stop kaizen-pdf
docker rm kaizen-pdf

# Install IronPDF
dotnet add package IronPdf
SHELL

License Configuration

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

Identify Kaizen.io Usage

Because Kaizen has no SDK, calls into it look like generic HttpClient POSTs. Search for the endpoint, image name, and license env var rather than a namespace:

grep -r "html-to-pdf\|KAIZEN_PDF_LICENSE\|kaizenio.azurecr.io\|localhost:8080" \
  --include="*.cs" --include="*.json" --include="*.yml" .
grep -r "html-to-pdf\|KAIZEN_PDF_LICENSE\|kaizenio.azurecr.io\|localhost:8080" \
  --include="*.cs" --include="*.json" --include="*.yml" .
SHELL

Complete API Reference

Concept Mappings

There is no Kaizen .NET class to map — only the JSON request shape and the conventions you built around it.

Kaizen.io Concept IronPDF Equivalent
HttpClient + POST /html-to-pdf ChromePdfRenderer
JSON { "html": "..." } body RenderHtmlAsPdf(string html)
(No URL field in v1.x) RenderUrlAsPdf(string url)
(No file field in v1.x) RenderHtmlFileAsPdf(string path)
Inline @page CSS for size RenderingOptions.PaperSize
Inline @page CSS for orientation RenderingOptions.PaperOrientation
Inline @page { margin: ... } RenderingOptions.MarginTop/Bottom/Left/Right
Fixed-position <div class='header'> hack RenderingOptions.TextHeader / HtmlHeader
Fixed-position <div class='footer'> hack RenderingOptions.TextFooter / HtmlFooter
HttpClient.PostAsync RenderHtmlAsPdfAsync
Container env var KAIZEN_PDF_LICENSE IronPdf.License.LicenseKey
HTTP byte[] response pdf.BinaryData / pdf.SaveAs(path)

Placeholder Mappings

Kaizen v1.x has no server-side placeholders. If you previously hand-substituted strings into the HTML before POSTing, switch to IronPDF's render-time placeholders:

What you used to do IronPDF Placeholder
html.Replace("{page}", currentPage.ToString()) {page}
html.Replace("{total}", total.ToString()) {total-pages}
html.Replace("{date}", DateTime.Now.ToShortDateString()) {date}
html.Replace("{title}", docTitle) {html-title}

Code Migration Examples

Example 1: Basic HTML to PDF

Before (Kaizen.io — POST JSON to the container):

// Container must be running:
//   docker run -d -p 8080:8080 -e KAIZEN_PDF_LICENSE=... \
//     kaizenio.azurecr.io/html-to-pdf:latest
using System.IO;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        using var http = new HttpClient();
        var payload = JsonSerializer.Serialize(new { html = "<html><body><h1>Hello World</h1></body></html>" });
        var content = new StringContent(payload, Encoding.UTF8, "application/json");
        var response = await http.PostAsync("http://localhost:8080/html-to-pdf", content);
        response.EnsureSuccessStatusCode();
        var pdfBytes = await response.Content.ReadAsByteArrayAsync();
        File.WriteAllBytes("output.pdf", pdfBytes);
    }
}
// Container must be running:
//   docker run -d -p 8080:8080 -e KAIZEN_PDF_LICENSE=... \
//     kaizenio.azurecr.io/html-to-pdf:latest
using System.IO;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        using var http = new HttpClient();
        var payload = JsonSerializer.Serialize(new { html = "<html><body><h1>Hello World</h1></body></html>" });
        var content = new StringContent(payload, Encoding.UTF8, "application/json");
        var response = await http.PostAsync("http://localhost:8080/html-to-pdf", content);
        response.EnsureSuccessStatusCode();
        var pdfBytes = await response.Content.ReadAsByteArrayAsync();
        File.WriteAllBytes("output.pdf", pdfBytes);
    }
}
Imports System.IO
Imports System.Net.Http
Imports System.Text
Imports System.Text.Json
Imports System.Threading.Tasks

Module Program
    Async Function Main() As Task
        Using http As New HttpClient()
            Dim payload = JsonSerializer.Serialize(New With {.html = "<html><body><h1>Hello World</h1></body></html>"})
            Dim content As New StringContent(payload, Encoding.UTF8, "application/json")
            Dim response = Await http.PostAsync("http://localhost:8080/html-to-pdf", content)
            response.EnsureSuccessStatusCode()
            Dim pdfBytes = Await response.Content.ReadAsByteArrayAsync()
            File.WriteAllBytes("output.pdf", pdfBytes)
        End Using
    End Function
End Module
$vbLabelText   $csharpLabel

After (IronPDF):

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

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var 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.IO;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var html = "<html><body><h1>Hello World</h1></body></html>";
        var pdf = renderer.RenderHtmlAsPdf(html);
        pdf.SaveAs("output.pdf");
    }
}
Imports IronPdf
Imports System.IO

Class Program
    Shared Sub Main()
        Dim renderer = New ChromePdfRenderer()
        Dim html = "<html><body><h1>Hello World</h1></body></html>"
        Dim pdf = renderer.RenderHtmlAsPdf(html)
        pdf.SaveAs("output.pdf")
    End Sub
End Class
$vbLabelText   $csharpLabel

The Kaizen.io approach serializes JSON, posts it to the container's REST endpoint, checks the status code, reads the response as bytes, and writes those bytes to disk. IronPDF's ChromePdfRenderer runs in-process — RenderHtmlAsPdf() returns a PdfDocument with a SaveAs() method, so the round-trip and the manual byte handling go away. See the HTML to PDF documentation for additional rendering options.

Example 2: HTML File to PDF with Page Settings

Kaizen v1.x has no file endpoint and no page-layout fields — you read the file yourself and embed page size/orientation in @page CSS.

Before (Kaizen.io):

using System.IO;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        var body = File.ReadAllText("input.html");
        var html = "<style>@page { size: A4 portrait; }</style>" + body;

        using var http = new HttpClient();
        var payload = JsonSerializer.Serialize(new { html });
        var response = await http.PostAsync(
            "http://localhost:8080/html-to-pdf",
            new StringContent(payload, Encoding.UTF8, "application/json"));
        response.EnsureSuccessStatusCode();
        File.WriteAllBytes("document.pdf", await response.Content.ReadAsByteArrayAsync());
    }
}
using System.IO;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        var body = File.ReadAllText("input.html");
        var html = "<style>@page { size: A4 portrait; }</style>" + body;

        using var http = new HttpClient();
        var payload = JsonSerializer.Serialize(new { html });
        var response = await http.PostAsync(
            "http://localhost:8080/html-to-pdf",
            new StringContent(payload, Encoding.UTF8, "application/json"));
        response.EnsureSuccessStatusCode();
        File.WriteAllBytes("document.pdf", await response.Content.ReadAsByteArrayAsync());
    }
}
Imports System.IO
Imports System.Net.Http
Imports System.Text
Imports System.Text.Json
Imports System.Threading.Tasks

Module Program
    Async Function Main() As Task
        Dim body = File.ReadAllText("input.html")
        Dim html = "<style>@page { size: A4 portrait; }</style>" & body

        Using http As New HttpClient()
            Dim payload = JsonSerializer.Serialize(New With {Key .html = html})
            Dim response = Await http.PostAsync(
                "http://localhost:8080/html-to-pdf",
                New StringContent(payload, Encoding.UTF8, "application/json"))
            response.EnsureSuccessStatusCode()
            File.WriteAllBytes("document.pdf", Await response.Content.ReadAsByteArrayAsync())
        End Using
    End Function
End Module
$vbLabelText   $csharpLabel

After (IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
        renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Portrait;
        var pdf = renderer.RenderHtmlFileAsPdf("input.html");
        pdf.SaveAs("document.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
        renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Portrait;
        var pdf = renderer.RenderHtmlFileAsPdf("input.html");
        pdf.SaveAs("document.pdf");
    }
}
Imports IronPdf

Class Program
    Shared Sub Main()
        Dim renderer = New ChromePdfRenderer()
        renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
        renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Portrait
        Dim pdf = renderer.RenderHtmlFileAsPdf("input.html")
        pdf.SaveAs("document.pdf")
    End Sub
End Class
$vbLabelText   $csharpLabel

RenderHtmlFileAsPdf() reads the file directly, and page size and orientation move from inline @page CSS to RenderingOptions properties.

Example 3: URL to PDF with Headers and Footers

Kaizen v1.x has no ConvertUrl, no header/footer fields, and no page-number placeholders. The workaround is to fetch the page yourself and wrap it with @page CSS and fixed-position divs to fake header/footer — with no way to render page numbers.

Before (Kaizen.io):

using System.IO;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        using var http = new HttpClient();
        var page = await http.GetStringAsync("https://example.com");
        var html = $@"<!doctype html><html><head><style>
            @page {{ margin: 20mm; }}
            .h {{ position: fixed; top: -15mm; left: 0; right: 0; text-align: center; }}
            .f {{ position: fixed; bottom: -15mm; left: 0; right: 0; text-align: center; }}
        </style></head><body>
            <div class='h'>Company Header</div>
            <div class='f'>Footer (page numbers unsupported in Kaizen v1.x)</div>
            {page}
        </body></html>";

        var payload = JsonSerializer.Serialize(new { html });
        var response = await http.PostAsync(
            "http://localhost:8080/html-to-pdf",
            new StringContent(payload, Encoding.UTF8, "application/json"));
        response.EnsureSuccessStatusCode();
        File.WriteAllBytes("webpage.pdf", await response.Content.ReadAsByteArrayAsync());
    }
}
using System.IO;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        using var http = new HttpClient();
        var page = await http.GetStringAsync("https://example.com");
        var html = $@"<!doctype html><html><head><style>
            @page {{ margin: 20mm; }}
            .h {{ position: fixed; top: -15mm; left: 0; right: 0; text-align: center; }}
            .f {{ position: fixed; bottom: -15mm; left: 0; right: 0; text-align: center; }}
        </style></head><body>
            <div class='h'>Company Header</div>
            <div class='f'>Footer (page numbers unsupported in Kaizen v1.x)</div>
            {page}
        </body></html>";

        var payload = JsonSerializer.Serialize(new { html });
        var response = await http.PostAsync(
            "http://localhost:8080/html-to-pdf",
            new StringContent(payload, Encoding.UTF8, "application/json"));
        response.EnsureSuccessStatusCode();
        File.WriteAllBytes("webpage.pdf", await response.Content.ReadAsByteArrayAsync());
    }
}
Imports System.IO
Imports System.Net.Http
Imports System.Text
Imports System.Text.Json
Imports System.Threading.Tasks

Module Program
    Async Function Main() As Task
        Using http As New HttpClient()
            Dim page As String = Await http.GetStringAsync("https://example.com")
            Dim html As String = $"<!doctype html><html><head><style>
                @page {{ margin: 20mm; }}
                .h {{ position: fixed; top: -15mm; left: 0; right: 0; text-align: center; }}
                .f {{ position: fixed; bottom: -15mm; left: 0; right: 0; text-align: center; }}
            </style></head><body>
                <div class='h'>Company Header</div>
                <div class='f'>Footer (page numbers unsupported in Kaizen v1.x)</div>
                {page}
            </body></html>"

            Dim payload As String = JsonSerializer.Serialize(New With {Key .html = html})
            Dim response As HttpResponseMessage = Await http.PostAsync(
                "http://localhost:8080/html-to-pdf",
                New StringContent(payload, Encoding.UTF8, "application/json"))
            response.EnsureSuccessStatusCode()
            File.WriteAllBytes("webpage.pdf", Await response.Content.ReadAsByteArrayAsync())
        End Using
    End Function
End Module
$vbLabelText   $csharpLabel

After (IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.TextHeader.CenterText = "Company Header";
        renderer.RenderingOptions.TextFooter.CenterText = "Page {page} of {total-pages}";
        renderer.RenderingOptions.MarginTop = 20;
        renderer.RenderingOptions.MarginBottom = 20;
        var pdf = renderer.RenderUrlAsPdf("https://example.com");
        pdf.SaveAs("webpage.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.TextHeader.CenterText = "Company Header";
        renderer.RenderingOptions.TextFooter.CenterText = "Page {page} of {total-pages}";
        renderer.RenderingOptions.MarginTop = 20;
        renderer.RenderingOptions.MarginBottom = 20;
        var pdf = renderer.RenderUrlAsPdf("https://example.com");
        pdf.SaveAs("webpage.pdf");
    }
}
Imports IronPdf

Class Program
    Shared Sub Main()
        Dim renderer = New ChromePdfRenderer()
        renderer.RenderingOptions.TextHeader.CenterText = "Company Header"
        renderer.RenderingOptions.TextFooter.CenterText = "Page {page} of {total-pages}"
        renderer.RenderingOptions.MarginTop = 20
        renderer.RenderingOptions.MarginBottom = 20
        Dim pdf = renderer.RenderUrlAsPdf("https://example.com")
        pdf.SaveAs("webpage.pdf")
    End Sub
End Class
$vbLabelText   $csharpLabel

RenderUrlAsPdf() fetches and renders the URL directly — no client-side page fetch — and the fake fixed-position divs are replaced with TextHeader / TextFooter zones. Page numbers are produced via the {page} and {total-pages} placeholders, which Kaizen v1.x does not provide. Learn more about URL to PDF conversion and headers and footers.


Critical Migration Notes

License Lives in Code, Not the Container

Kaizen's license is configured via the KAIZEN_PDF_LICENSE environment variable on the Docker container. IronPDF's license is a static property set once at application startup:

// DELETE the Kaizen container env var:
//   docker run ... -e KAIZEN_PDF_LICENSE=... kaizenio.azurecr.io/html-to-pdf

// IronPDF: set once at startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
var renderer = new ChromePdfRenderer();
// DELETE the Kaizen container env var:
//   docker run ... -e KAIZEN_PDF_LICENSE=... kaizenio.azurecr.io/html-to-pdf

// IronPDF: set once at startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
var renderer = new ChromePdfRenderer();
' DELETE the Kaizen container env var:
'   docker run ... -e KAIZEN_PDF_LICENSE=... kaizenio.azurecr.io/html-to-pdf

' IronPDF: set once at startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim renderer As New ChromePdfRenderer()
$vbLabelText   $csharpLabel

Placeholder Syntax

If you previously hand-substituted strings into the HTML before POSTing, switch to IronPDF's render-time placeholders:

  • {page} (unchanged)
  • {total}{total-pages}
  • {title}{html-title}
  • {date}{date} (unchanged)

Return Type Change

Kaizen returns raw bytes over HTTP. IronPDF returns a PdfDocument:

// Kaizen.io returns byte[] via HTTP
byte[] pdfBytes = await response.Content.ReadAsByteArrayAsync();
File.WriteAllBytes("output.pdf", pdfBytes);

// IronPDF returns PdfDocument
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");           // Direct save
byte[] bytes = pdf.BinaryData;      // Or get bytes if needed
// Kaizen.io returns byte[] via HTTP
byte[] pdfBytes = await response.Content.ReadAsByteArrayAsync();
File.WriteAllBytes("output.pdf", pdfBytes);

// IronPDF returns PdfDocument
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");           // Direct save
byte[] bytes = pdf.BinaryData;      // Or get bytes if needed
Imports System.IO

' Kaizen.io returns Byte() via HTTP
Dim pdfBytes As Byte() = Await response.Content.ReadAsByteArrayAsync()
File.WriteAllBytes("output.pdf", pdfBytes)

' IronPDF returns PdfDocument
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")           ' Direct save
Dim bytes As Byte() = pdf.BinaryData ' Or get bytes if needed
$vbLabelText   $csharpLabel

Delete the HTTP Plumbing

Once the renderer is in-process, the supporting code disappears:

// DELETE all of:
// - HttpClient lifetime management
// - JSON serialization of { html }
// - response.EnsureSuccessStatusCode() / status-code branches
// - "container unreachable" retry/backoff
// - ReadAsByteArrayAsync()

// Replaced with a single in-process call:
var pdf = renderer.RenderHtmlAsPdf(html);
// DELETE all of:
// - HttpClient lifetime management
// - JSON serialization of { html }
// - response.EnsureSuccessStatusCode() / status-code branches
// - "container unreachable" retry/backoff
// - ReadAsByteArrayAsync()

// Replaced with a single in-process call:
var pdf = renderer.RenderHtmlAsPdf(html);
$vbLabelText   $csharpLabel

Troubleshooting

Issue 1: No HtmlToPdfConverter Class

Problem: There is no HtmlToPdfConverter class to swap for — Kaizen has no .NET SDK at all.

Solution: The migration is from HttpClient POSTs against the container to ChromePdfRenderer:

// Kaizen.io: hand-rolled HTTP
using var http = new HttpClient();
var response = await http.PostAsync("http://localhost:8080/html-to-pdf", content);

// IronPDF: in-process renderer
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
// Kaizen.io: hand-rolled HTTP
using var http = new HttpClient();
var response = await http.PostAsync("http://localhost:8080/html-to-pdf", content);

// IronPDF: in-process renderer
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
Imports System.Net.Http
Imports IronPdf

' Kaizen.io: hand-rolled HTTP
Using http As New HttpClient()
    Dim response = Await http.PostAsync("http://localhost:8080/html-to-pdf", content)
End Using

' IronPDF: in-process renderer
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
$vbLabelText   $csharpLabel

Issue 2: Where Did the Options Object Go?

Problem: Kaizen v1.x has no ConversionOptions — page layout was inline @page CSS, headers/footers were fixed-position divs.

Solution: Move that configuration to RenderingOptions on the renderer:

// Before: <style>@page { size: A4 portrait; margin: 20mm; }</style>
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Portrait;
renderer.RenderingOptions.MarginTop = 20;
renderer.RenderingOptions.MarginBottom = 20;
// Before: <style>@page { size: A4 portrait; margin: 20mm; }</style>
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Portrait;
renderer.RenderingOptions.MarginTop = 20;
renderer.RenderingOptions.MarginBottom = 20;
' Before: <style>@page { size: A4 portrait; margin: 20mm; }</style>
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Portrait
renderer.RenderingOptions.MarginTop = 20
renderer.RenderingOptions.MarginBottom = 20
$vbLabelText   $csharpLabel

Issue 3: Page Numbers Don't Render

Problem: Kaizen v1.x has no {page} / {total} placeholder support, so any pre-migration "Page X of Y" footer was either missing or static text.

Solution: Use IronPDF's header/footer placeholders:

renderer.RenderingOptions.TextFooter = new TextHeaderFooter
{
    CenterText = "Page {page} of {total-pages}"
};
renderer.RenderingOptions.TextFooter = new TextHeaderFooter
{
    CenterText = "Page {page} of {total-pages}"
};
renderer.RenderingOptions.TextFooter = New TextHeaderFooter With {
    .CenterText = "Page {page} of {total-pages}"
}
$vbLabelText   $csharpLabel

If you previously hand-substituted {total} in your own code before POSTing, remove that substitution — IronPDF resolves {total-pages} at render time.

Issue 4: Container Connection Errors

Problem: Code paths handling "container unreachable" / port-8080 errors.

Solution: IronPDF runs in-process — there is no endpoint to connect to. Delete the connection error handling.

Issue 5: First Render Slow

Problem: First PDF generation takes 1-3 seconds.

Solution: IronPDF initializes Chromium on first use. Warm up at application startup:

// In Program.cs or Startup.cs:
new ChromePdfRenderer().RenderHtmlAsPdf("<html></html>");
// In Program.cs or Startup.cs:
new ChromePdfRenderer().RenderHtmlAsPdf("<html></html>");
' In Program.vb or Startup.vb:
Call New ChromePdfRenderer().RenderHtmlAsPdf("<html></html>")
$vbLabelText   $csharpLabel

Migration Checklist

Pre-Migration

  • Locate every Kaizen call site (search for html-to-pdf, KAIZEN_PDF_LICENSE, kaizenio.azurecr.io, localhost:8080)
  • Document inline @page CSS used for size, orientation, margins
  • Document fake header/footer divs (fixed-position with negative offsets)
  • List any client-side placeholder substitution (html.Replace("{page}", ...) etc.)
  • Note container lifecycle: pull, run, restart, license env var
  • Obtain IronPDF license key

Container Teardown

  • Stop and remove the running Kaizen container (docker stop kaizen-pdf && docker rm kaizen-pdf)
  • Remove Kaizen pull/run steps from CI/CD
  • Remove KAIZEN_PDF_LICENSE from secrets/env
  • Install IronPdf NuGet package (dotnet add package IronPdf)

Code Changes

  • Add license key configuration at startup
  • Replace HttpClient POST with ChromePdfRenderer
  • Move embedded @page CSS into RenderingOptions properties
  • Replace JSON POST with RenderHtmlAsPdf() / RenderHtmlFileAsPdf() / RenderUrlAsPdf()
  • Replace fake header/footer divs with TextHeader/Footer or HtmlHeader/Footer
  • Update placeholder syntax ({total}{total-pages}, {title}{html-title})
  • Replace byte[] HTTP body with pdf.BinaryData
  • Use pdf.SaveAs() instead of File.WriteAllBytes()
  • Delete container-reachability error handling and retry/backoff

Testing

  • Test all PDF generation paths
  • Verify header/footer rendering and page numbers (new capability)
  • Validate margins, page size, and orientation
  • Test offline operation (no container required)

Post-Migration

  • Tear down Kaizen container infrastructure
  • Update environment variables / secrets
  • Remove container health checks from monitoring/alerting
  • Document the new typed-exception error patterns

Please noteKaizen.io is a registered trademark of its respective owner. This site is not affiliated with, endorsed by, or sponsored by Kaizen.io. 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

Iron Support Team

We're online 24 hours, 5 days a week.
Chat
Email
Call Me