푸터 콘텐츠로 바로가기
MIGRATION GUIDES

How to Migrate from MigraDoc to IronPDF in C#

Migrating from MigraDoc to IronPDF transforms your .NET PDF workflow from a verbose programmatic document model requiring manual element-by-element construction to a modern HTML/CSS-based approach that leverages existing web development skills. This guide provides a comprehensive, step-by-step migration path that eliminates the steep learning curve of MigraDoc's proprietary document object model for professional .NET developers.

Why Migrate from MigraDoc to IronPDF

The MigraDoc Challenges

MigraDoc, while powerful for programmatic PDF generation, has fundamental limitations that affect modern development workflows:

  1. No HTML Support: MigraDoc doesn't support HTML directly. You must manually construct documents element-by-element using Document, Section, Paragraph, and Table objects—you cannot leverage existing HTML/CSS designs.

  2. Proprietary Document Model: MigraDoc requires learning a unique document model with concepts like AddSection(), AddParagraph(), AddTable(), AddRow(), and AddCell(). This steep learning curve is particularly challenging for developers with web development backgrounds.

  3. Limited Styling Options: While MigraDoc offers robust document structure management, its styling capabilities are modest compared to modern web tools. Properties like Format.Font.Size, Format.Font.Bold, and Format.Alignment are limited compared to full CSS3.

  4. Verbose Code: Creating even simple layouts requires dozens of lines of code. A basic table with headers can require 15-20 lines of MigraDoc code.

  5. No JavaScript Support: MigraDoc cannot render dynamic content or execute JavaScript, limiting options for modern charting and interactive elements.

  6. Charts Are Basic: MigraDoc's chart functionality is limited compared to modern JavaScript charting libraries like Chart.js or D3.

MigraDoc vs IronPDF Comparison

Feature MigraDoc IronPDF
Content Definition Programmatic (Document/Section/Paragraph) HTML/CSS
Learning Curve Steep (proprietary DOM) Easy (web skills)
Styling Limited properties Full CSS3
JavaScript None Full Chromium execution
Tables Manual column/row definition HTML <table> with CSS
Charts Basic MigraDoc charts Any JavaScript charting library
Images Manual sizing/positioning Standard HTML <img>
Responsive Layouts Not supported Flexbox, Grid
License Open Source (MIT) Commercial

For teams planning .NET 10 and C# 14 adoption through 2025 and 2026, IronPDF provides a future-proof foundation that allows developers to use familiar HTML/CSS skills rather than learning a proprietary document model.


Migration Complexity Assessment

Estimated Effort by Feature

Feature Migration Complexity
Simple Text Very Low
Tables Low
Headers/Footers Low
Styles Medium
Images Low
Charts Medium

Paradigm Shift

The fundamental shift in this MigraDoc migration is from programmatic document construction to HTML-first rendering:

MigraDoc:  Document → AddSection() → AddParagraph() → PdfDocumentRenderer → Save()
IronPDF:   ChromePdfRenderer → RenderHtmlAsPdf(html) → SaveAs()

This paradigm shift dramatically reduces code complexity while providing unlimited styling capabilities through CSS.


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 MigraDoc packages
dotnet remove package PdfSharp-MigraDoc
dotnet remove package PdfSharp-MigraDoc-GDI
dotnet remove package PDFsharp.MigraDoc.Standard

# Install IronPDF
dotnet add package IronPdf
# Remove MigraDoc packages
dotnet remove package PdfSharp-MigraDoc
dotnet remove package PdfSharp-MigraDoc-GDI
dotnet remove package PDFsharp.MigraDoc.Standard

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

Identify MigraDoc Usage

# Find all MigraDoc references
grep -r "using MigraDoc\|PdfDocumentRenderer\|AddSection\|AddParagraph" --include="*.cs" .
grep -r "AddTable\|AddRow\|AddColumn\|AddCell\|AddImage" --include="*.cs" .
# Find all MigraDoc references
grep -r "using MigraDoc\|PdfDocumentRenderer\|AddSection\|AddParagraph" --include="*.cs" .
grep -r "AddTable\|AddRow\|AddColumn\|AddCell\|AddImage" --include="*.cs" .
SHELL

Complete API Reference

Class Mappings

MigraDoc Class IronPDF Equivalent
Document ChromePdfRenderer
Section HTML <body> or <div>
Paragraph HTML <p>, <h1>, etc.
FormattedText HTML <span>, <strong>, etc.
Table HTML <table>
Row HTML <tr>
Column HTML <col> or CSS
Cell HTML <td>, <th>
PdfDocumentRenderer ChromePdfRenderer

Method Mappings

MigraDoc Method IronPDF Equivalent
document.AddSection() HTML structure
section.AddParagraph(text) <p>text</p>
section.AddTable() <table>
table.AddColumn(width) CSS width property
table.AddRow() <tr>
row.Cells[n].AddParagraph() <td>content</td>
renderer.RenderDocument() RenderHtmlAsPdf(html)
pdfDocument.Save(path) pdf.SaveAs(path)

Placeholder Mappings (Headers/Footers)

MigraDoc Method IronPDF Placeholder
AddPageField() {page}
AddNumPagesField() {total-pages}
AddDateField() {date}

Code Migration Examples

Example 1: Basic HTML to PDF (The Fundamental Difference)

Before (MigraDoc):

// NuGet: Install-Package PdfSharp-MigraDoc-GDI
using MigraDoc.DocumentObjectModel;
using MigraDoc.Rendering;
using System.Diagnostics;

class Program
{
    static void Main()
    {
        // MigraDoc doesn't support HTML directly
        // Must manually create document structure
        Document document = new Document();
        Section section = document.AddSection();

        Paragraph paragraph = section.AddParagraph();
        paragraph.AddFormattedText("Hello World", TextFormat.Bold);
        paragraph.Format.Font.Size = 16;

        PdfDocumentRenderer pdfRenderer = new PdfDocumentRenderer();
        pdfRenderer.Document = document;
        pdfRenderer.RenderDocument();
        pdfRenderer.PdfDocument.Save("output.pdf");
    }
}
// NuGet: Install-Package PdfSharp-MigraDoc-GDI
using MigraDoc.DocumentObjectModel;
using MigraDoc.Rendering;
using System.Diagnostics;

class Program
{
    static void Main()
    {
        // MigraDoc doesn't support HTML directly
        // Must manually create document structure
        Document document = new Document();
        Section section = document.AddSection();

        Paragraph paragraph = section.AddParagraph();
        paragraph.AddFormattedText("Hello World", TextFormat.Bold);
        paragraph.Format.Font.Size = 16;

        PdfDocumentRenderer pdfRenderer = new PdfDocumentRenderer();
        pdfRenderer.Document = document;
        pdfRenderer.RenderDocument();
        pdfRenderer.PdfDocument.Save("output.pdf");
    }
}
$vbLabelText   $csharpLabel

After (IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1>");
        pdf.SaveAs("output.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1>");
        pdf.SaveAs("output.pdf");
    }
}
$vbLabelText   $csharpLabel

This example illustrates the fundamental difference between MigraDoc and IronPDF. MigraDoc requires creating a Document, adding a Section, adding a Paragraph, using AddFormattedText() with TextFormat.Bold, setting Format.Font.Size, creating a PdfDocumentRenderer, assigning the document, calling RenderDocument(), and finally saving. That's 10+ lines of code with multiple objects.

IronPDF accomplishes the same result in 3 lines: create a renderer, render HTML, and save. The HTML <h1> tag naturally provides the bold, large heading style. See the HTML to PDF documentation for additional rendering options.

Example 2: Creating Tables

Before (MigraDoc):

// NuGet: Install-Package PdfSharp-MigraDoc-GDI
using MigraDoc.DocumentObjectModel;
using MigraDoc.DocumentObjectModel.Tables;
using MigraDoc.Rendering;

class Program
{
    static void Main()
    {
        Document document = new Document();
        Section section = document.AddSection();

        Table table = section.AddTable();
        table.Borders.Width = 0.75;

        Column column1 = table.AddColumn("3cm");
        Column column2 = table.AddColumn("3cm");

        Row row1 = table.AddRow();
        row1.Cells[0].AddParagraph("Name");
        row1.Cells[1].AddParagraph("Age");

        Row row2 = table.AddRow();
        row2.Cells[0].AddParagraph("John");
        row2.Cells[1].AddParagraph("30");

        PdfDocumentRenderer pdfRenderer = new PdfDocumentRenderer();
        pdfRenderer.Document = document;
        pdfRenderer.RenderDocument();
        pdfRenderer.PdfDocument.Save("table.pdf");
    }
}
// NuGet: Install-Package PdfSharp-MigraDoc-GDI
using MigraDoc.DocumentObjectModel;
using MigraDoc.DocumentObjectModel.Tables;
using MigraDoc.Rendering;

class Program
{
    static void Main()
    {
        Document document = new Document();
        Section section = document.AddSection();

        Table table = section.AddTable();
        table.Borders.Width = 0.75;

        Column column1 = table.AddColumn("3cm");
        Column column2 = table.AddColumn("3cm");

        Row row1 = table.AddRow();
        row1.Cells[0].AddParagraph("Name");
        row1.Cells[1].AddParagraph("Age");

        Row row2 = table.AddRow();
        row2.Cells[0].AddParagraph("John");
        row2.Cells[1].AddParagraph("30");

        PdfDocumentRenderer pdfRenderer = new PdfDocumentRenderer();
        pdfRenderer.Document = document;
        pdfRenderer.RenderDocument();
        pdfRenderer.PdfDocument.Save("table.pdf");
    }
}
$vbLabelText   $csharpLabel

After (IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        string htmlTable = @"
            <table border='1'>
                <tr><th>Name</th><th>Age</th></tr>
                <tr><td>John</td><td>30</td></tr>
            </table>";

        var pdf = renderer.RenderHtmlAsPdf(htmlTable);
        pdf.SaveAs("table.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        string htmlTable = @"
            <table border='1'>
                <tr><th>Name</th><th>Age</th></tr>
                <tr><td>John</td><td>30</td></tr>
            </table>";

        var pdf = renderer.RenderHtmlAsPdf(htmlTable);
        pdf.SaveAs("table.pdf");
    }
}
$vbLabelText   $csharpLabel

The MigraDoc table creation requires understanding the Table, Column, Row, and Cell hierarchy. You must explicitly add columns with AddColumn(), create rows with AddRow(), access cells by index with Cells[n], and add content with AddParagraph(). The border is set via table.Borders.Width.

IronPDF uses standard HTML table syntax that any web developer knows. The border='1' attribute provides the border, <th> elements create header cells, and <td> elements create data cells. CSS can be added for advanced styling like zebra striping, hover effects, or responsive layouts. Learn more about creating tables in PDFs.

Example 3: Headers and Footers with Page Numbers

Before (MigraDoc):

// NuGet: Install-Package PdfSharp-MigraDoc-GDI
using MigraDoc.DocumentObjectModel;
using MigraDoc.Rendering;

class Program
{
    static void Main()
    {
        Document document = new Document();
        Section section = document.AddSection();

        // Add header
        Paragraph headerPara = section.Headers.Primary.AddParagraph();
        headerPara.AddText("Document Header");
        headerPara.Format.Font.Size = 12;
        headerPara.Format.Alignment = ParagraphAlignment.Center;

        // Add footer
        Paragraph footerPara = section.Footers.Primary.AddParagraph();
        footerPara.AddText("Page ");
        footerPara.AddPageField();
        footerPara.Format.Alignment = ParagraphAlignment.Center;

        // Add content
        section.AddParagraph("Main content of the document");

        PdfDocumentRenderer pdfRenderer = new PdfDocumentRenderer();
        pdfRenderer.Document = document;
        pdfRenderer.RenderDocument();
        pdfRenderer.PdfDocument.Save("header-footer.pdf");
    }
}
// NuGet: Install-Package PdfSharp-MigraDoc-GDI
using MigraDoc.DocumentObjectModel;
using MigraDoc.Rendering;

class Program
{
    static void Main()
    {
        Document document = new Document();
        Section section = document.AddSection();

        // Add header
        Paragraph headerPara = section.Headers.Primary.AddParagraph();
        headerPara.AddText("Document Header");
        headerPara.Format.Font.Size = 12;
        headerPara.Format.Alignment = ParagraphAlignment.Center;

        // Add footer
        Paragraph footerPara = section.Footers.Primary.AddParagraph();
        footerPara.AddText("Page ");
        footerPara.AddPageField();
        footerPara.Format.Alignment = ParagraphAlignment.Center;

        // Add content
        section.AddParagraph("Main content of the document");

        PdfDocumentRenderer pdfRenderer = new PdfDocumentRenderer();
        pdfRenderer.Document = document;
        pdfRenderer.RenderDocument();
        pdfRenderer.PdfDocument.Save("header-footer.pdf");
    }
}
$vbLabelText   $csharpLabel

After (IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<h1>Main content of the document</h1>");

        pdf.AddTextHeader("Document Header");
        pdf.AddTextFooter("Page {page}");

        pdf.SaveAs("header-footer.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<h1>Main content of the document</h1>");

        pdf.AddTextHeader("Document Header");
        pdf.AddTextFooter("Page {page}");

        pdf.SaveAs("header-footer.pdf");
    }
}
$vbLabelText   $csharpLabel

MigraDoc headers and footers require accessing section.Headers.Primary and section.Footers.Primary, creating paragraphs within them, adding text with AddText(), and using special methods like AddPageField() for dynamic content. Alignment requires setting Format.Alignment.

IronPDF provides simple AddTextHeader() and AddTextFooter() methods on the PdfDocument object. The {page} placeholder automatically inserts the current page number. For more complex headers, you can use HtmlHeaderFooter with full HTML/CSS support. See the headers and footers documentation for advanced options.


Critical Migration Notes

Page Number Placeholder Syntax

The most important change for headers and footers is the placeholder syntax:

// MigraDoc field methods:
footerPara.AddPageField();       // Current page
footerPara.AddNumPagesField();   // Total pages

// IronPDF placeholders:
"Page {page} of {total-pages}"
// MigraDoc field methods:
footerPara.AddPageField();       // Current page
footerPara.AddNumPagesField();   // Total pages

// IronPDF placeholders:
"Page {page} of {total-pages}"
$vbLabelText   $csharpLabel

Format Properties to CSS

MigraDoc's Format properties map to CSS:

// MigraDoc:
paragraph.Format.Font.Size = 16;
paragraph.Format.Font.Bold = true;
paragraph.Format.Alignment = ParagraphAlignment.Center;

// IronPDF (CSS):
<p style="font-size: 16pt; font-weight: bold; text-align: center;">
// MigraDoc:
paragraph.Format.Font.Size = 16;
paragraph.Format.Font.Bold = true;
paragraph.Format.Alignment = ParagraphAlignment.Center;

// IronPDF (CSS):
<p style="font-size: 16pt; font-weight: bold; text-align: center;">
$vbLabelText   $csharpLabel

Unit Conversion

MigraDoc uses various units; IronPDF margins use millimeters:

  • "1cm" = 10mm
  • "1in" = 25.4mm
  • "72pt" = 25.4mm
// MigraDoc:
table.AddColumn("3cm");

// IronPDF (CSS):
<th style="width: 3cm;">
// MigraDoc:
table.AddColumn("3cm");

// IronPDF (CSS):
<th style="width: 3cm;">
$vbLabelText   $csharpLabel

Rendering Pattern Change

The entire rendering pattern changes:

// MigraDoc pattern (DELETE):
PdfDocumentRenderer pdfRenderer = new PdfDocumentRenderer();
pdfRenderer.Document = document;
pdfRenderer.RenderDocument();
pdfRenderer.PdfDocument.Save("output.pdf");

// IronPDF pattern:
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
// MigraDoc pattern (DELETE):
PdfDocumentRenderer pdfRenderer = new PdfDocumentRenderer();
pdfRenderer.Document = document;
pdfRenderer.RenderDocument();
pdfRenderer.PdfDocument.Save("output.pdf");

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

Troubleshooting

Issue 1: Document/Section Not Found

Problem: Document and Section classes don't exist in IronPDF.

Solution: Replace with HTML structure:

// MigraDoc
Document document = new Document();
Section section = document.AddSection();

// IronPDF
string html = "<html><body>...</body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
// MigraDoc
Document document = new Document();
Section section = document.AddSection();

// IronPDF
string html = "<html><body>...</body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
$vbLabelText   $csharpLabel

Issue 2: AddParagraph Not Found

Problem: AddParagraph() method doesn't exist.

Solution: Use HTML elements:

// MigraDoc
section.AddParagraph("Hello World");

// IronPDF
"<p>Hello World</p>"
// MigraDoc
section.AddParagraph("Hello World");

// IronPDF
"<p>Hello World</p>"
$vbLabelText   $csharpLabel

Issue 3: PdfDocumentRenderer Not Found

Problem: PdfDocumentRenderer class doesn't exist.

Solution: Use ChromePdfRenderer:

// MigraDoc
PdfDocumentRenderer pdfRenderer = new PdfDocumentRenderer();

// IronPDF
var renderer = new ChromePdfRenderer();
// MigraDoc
PdfDocumentRenderer pdfRenderer = new PdfDocumentRenderer();

// IronPDF
var renderer = new ChromePdfRenderer();
$vbLabelText   $csharpLabel

Issue 4: AddPageField Not Working

Problem: AddPageField() method doesn't exist.

Solution: Use IronPDF placeholder syntax:

// MigraDoc
footerPara.AddPageField();

// IronPDF
pdf.AddTextFooter("Page {page}");
// MigraDoc
footerPara.AddPageField();

// IronPDF
pdf.AddTextFooter("Page {page}");
$vbLabelText   $csharpLabel

Migration Checklist

Pre-Migration

  • Identify all MigraDoc using statements
  • Document table structures (columns, rows, styling)
  • Note header/footer content and page field usage
  • List custom styles defined with document.Styles
  • Obtain IronPDF license key

Package Changes

  • Remove PdfSharp-MigraDoc package
  • Remove PdfSharp-MigraDoc-GDI package
  • Install IronPdf NuGet package: dotnet add package IronPdf
  • Update namespace imports

Code Changes

  • Add license key configuration at startup
  • Replace Document/Section with HTML structure
  • Convert AddParagraph() to HTML <p> elements
  • Convert Table/Row/Cell to HTML <table> structure
  • Replace AddPageField() with {page} placeholder
  • Replace AddNumPagesField() with {total-pages} placeholder
  • Convert Format properties to CSS styles
  • Replace PdfDocumentRenderer with ChromePdfRenderer

Testing

  • Compare visual output between old and new PDFs
  • Verify page breaks work correctly
  • Check header/footer rendering and page numbers
  • Validate table formatting and borders
  • Test with complex multi-page documents

Post-Migration

  • Remove MigraDoc-related documentation
  • Update team training materials
  • Document new HTML template locations

커티스 차우
기술 문서 작성자

커티스 차우는 칼턴 대학교에서 컴퓨터 과학 학사 학위를 취득했으며, Node.js, TypeScript, JavaScript, React를 전문으로 하는 프론트엔드 개발자입니다. 직관적이고 미적으로 뛰어난 사용자 인터페이스를 만드는 데 열정을 가진 그는 최신 프레임워크를 활용하고, 잘 구성되고 시각적으로 매력적인 매뉴얼을 제작하는 것을 즐깁니다.

커티스는 개발 분야 외에도 사물 인터넷(IoT)에 깊은 관심을 가지고 있으며, 하드웨어와 소프트웨어를 통합하는 혁신적인 방법을 연구합니다. 여가 시간에는 게임을 즐기거나 디스코드 봇을 만들면서 기술에 대한 애정과 창의성을 결합합니다.