How to Migrate from BitMiracle Docotic PDF to IronPDF in C#
BitMiracle Docotic PDF is a well-regarded .NET PDF library known for its 100% managed code architecture and extensive programmatic PDF manipulation capabilities. However, its modular add-on structure—requiring separate packages for HTML-to-PDF conversion, layout features, and other functionality—adds complexity to project management and licensing. This comprehensive guide provides a step-by-step migration path from BitMiracle Docotic PDF to IronPDF—a unified .NET PDF library with built-in Chromium-based HTML rendering and all features included in a single NuGet package.
Why Migrate from BitMiracle Docotic PDF to IronPDF?
While BitMiracle Docotic PDF offers robust PDF manipulation features, several factors drive development teams to seek alternatives with more streamlined architecture.
Package Architecture Comparison
BitMiracle Docotic PDF uses a modular add-on approach that requires multiple packages for full functionality:
| Aspect | BitMiracle Docotic PDF | IronPDF |
|---|---|---|
| HTML-to-PDF | Requires separate add-on (HtmlToPdf) | Built-in core feature |
| Package Structure | Core + multiple add-ons | Single NuGet package |
| Licensing Model | Per-add-on licensing | All features included |
| API Complexity | Separate namespaces per add-on | Unified API |
| HTML Engine | Chromium (via add-on) | Chromium (built-in) |
| Community Size | Smaller | Larger, more resources |
| Documentation | Technical reference | Extensive tutorials |
Feature Parity
Both libraries support comprehensive PDF functionality:
| Feature | BitMiracle Docotic PDF | IronPDF |
|---|---|---|
| Create PDF from scratch | ✅ | ✅ |
| HTML to PDF | ✅ (add-on required) | ✅ (built-in) |
| URL to PDF | ✅ (add-on required) | ✅ (built-in) |
| PDF manipulation | ✅ | ✅ |
| Text extraction | ✅ | ✅ |
| Merge/Split | ✅ | ✅ |
| Digital signatures | ✅ | ✅ |
| Encryption | ✅ | ✅ |
| Form filling | ✅ | ✅ |
| PDF/A compliance | ✅ | ✅ |
Key Differences in Approach
BitMiracle Docotic PDF uses canvas-based drawing with coordinate positioning (canvas.DrawString(x, y, text)), while IronPDF leverages HTML/CSS for layout and positioning. This represents a paradigm shift that simplifies content creation for developers familiar with web technologies.
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 BitMiracle Docotic PDF Usage
Run these commands in your solution directory to identify all Docotic.Pdf references:
# Find all Docotic.Pdf usages in your codebase
grep -r "using BitMiracle.Docotic" --include="*.cs" .
grep -r "PdfDocument\|PdfPage\|PdfCanvas" --include="*.cs" .
# Find NuGet package references
grep -r "Docotic.Pdf" --include="*.csproj" .# Find all Docotic.Pdf usages in your codebase
grep -r "using BitMiracle.Docotic" --include="*.cs" .
grep -r "PdfDocument\|PdfPage\|PdfCanvas" --include="*.cs" .
# Find NuGet package references
grep -r "Docotic.Pdf" --include="*.csproj" .Breaking Changes to Anticipate
| Change | BitMiracle Docotic PDF | IronPDF | Impact |
|---|---|---|---|
| HTML rendering | Requires HtmlToPdf add-on | Built-in | Remove add-on package |
| Page indexing | 0-based (Pages[0]) | 0-based (Pages[0]) | No change needed |
| Coordinate system | Bottom-left origin | HTML/CSS flow | Use CSS for positioning |
| Canvas drawing | PdfCanvas.DrawText() | HTML markup | Paradigm shift |
| Text extraction | page.GetText() | pdf.ExtractAllText() | Method name change |
| Document loading | new PdfDocument(path) | PdfDocument.FromFile(path) | Constructor → static method |
| Saving | document.Save(path) | pdf.SaveAs(path) | Method name change |
| Disposal | IDisposable pattern | Not required | Simpler resource management |
Step-by-Step Migration Process
Step 1: Update NuGet Packages
Remove BitMiracle Docotic PDF packages and install IronPDF:
# Remove Docotic.Pdf packages
dotnet remove package BitMiracle.Docotic.Pdf
dotnet remove package BitMiracle.Docotic.Pdf.HtmlToPdf
dotnet remove package BitMiracle.Docotic.Pdf.Layout
# Install IronPDF
dotnet add package IronPdf# Remove Docotic.Pdf packages
dotnet remove package BitMiracle.Docotic.Pdf
dotnet remove package BitMiracle.Docotic.Pdf.HtmlToPdf
dotnet remove package BitMiracle.Docotic.Pdf.Layout
# Install IronPDF
dotnet add package IronPdfStep 2: Update Namespace References
Replace BitMiracle Docotic PDF namespaces with IronPDF:
// Remove these
using BitMiracle.Docotic.Pdf;
using BitMiracle.Docotic.Pdf.Layout;
using BitMiracle.Docotic.Pdf.HtmlToPdf;
// Add this
using IronPdf;// Remove these
using BitMiracle.Docotic.Pdf;
using BitMiracle.Docotic.Pdf.Layout;
using BitMiracle.Docotic.Pdf.HtmlToPdf;
// Add this
using IronPdf;Step 3: Configure License
// Add at application startup (Program.cs or Global.asax)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";// Add at application startup (Program.cs or Global.asax)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";Complete API Migration Reference
Document Operations
| Task | BitMiracle Docotic PDF | IronPDF |
|---|---|---|
| Create empty document | new PdfDocument() | new PdfDocument() |
| Load from file | new PdfDocument(path) | PdfDocument.FromFile(path) |
| Load from stream | PdfDocument.Load(stream) | PdfDocument.FromStream(stream) |
| Load from bytes | PdfDocument.Load(bytes) | PdfDocument.FromBinaryData(bytes) |
| Save to file | document.Save(path) | pdf.SaveAs(path) |
| Get page count | document.PageCount | pdf.PageCount |
| Close/Dispose | document.Dispose() | Not required |
HTML to PDF Conversion
| Task | BitMiracle Docotic PDF (HtmlToPdf Add-on) | IronPDF |
|---|---|---|
| HTML string to PDF | HtmlConverter.Create(html).ToPdf() | renderer.RenderHtmlAsPdf(html) |
| HTML file to PDF | HtmlConverter.Create(new Uri(filePath)).ToPdf() | renderer.RenderHtmlFileAsPdf(path) |
| URL to PDF | HtmlConverter.Create(new Uri(url)).ToPdf() | renderer.RenderUrlAsPdf(url) |
| Set page size | options.PageSize = PageSize.A4 | renderer.RenderingOptions.PaperSize = PdfPaperSize.A4 |
| Set margins | options.PageMargins = new Margins(20) | renderer.RenderingOptions.MarginTop = 20 |
Merge and Split Operations
| Task | BitMiracle Docotic PDF | IronPDF |
|---|---|---|
| Merge documents | doc1.Append(doc2) | PdfDocument.Merge(pdf1, pdf2) |
| Split document | document.CopyPage(index) to new doc | pdf.CopyPages(start, end) |
Code Migration Examples
HTML to PDF Conversion
The most common operation demonstrates the significant simplification IronPDF provides.
BitMiracle Docotic PDF Implementation:
// NuGet: Install-Package Docotic.Pdf
using BitMiracle.Docotic.Pdf;
using System;
class Program
{
static void Main()
{
using (var pdf = new PdfDocument())
{
string html = "<html><body><h1>Hello World</h1><p>This is HTML to PDF conversion.</p></body></html>";
pdf.CreatePage(html);
pdf.Save("output.pdf");
}
Console.WriteLine("PDF created successfully");
}
}// NuGet: Install-Package Docotic.Pdf
using BitMiracle.Docotic.Pdf;
using System;
class Program
{
static void Main()
{
using (var pdf = new PdfDocument())
{
string html = "<html><body><h1>Hello World</h1><p>This is HTML to PDF conversion.</p></body></html>";
pdf.CreatePage(html);
pdf.Save("output.pdf");
}
Console.WriteLine("PDF created successfully");
}
}IronPDF Implementation:
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
string html = "<html><body><h1>Hello World</h1><p>This is HTML to PDF conversion.</p></body></html>";
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()
{
var renderer = new ChromePdfRenderer();
string html = "<html><body><h1>Hello World</h1><p>This is HTML to PDF conversion.</p></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
Console.WriteLine("PDF created successfully");
}
}IronPDF eliminates the using statement requirement and provides a dedicated ChromePdfRenderer class that clearly indicates its Chromium-based rendering capability. For more HTML conversion options, see the HTML to PDF documentation.
Merging Multiple PDFs
BitMiracle Docotic PDF Implementation:
// NuGet: Install-Package Docotic.Pdf
using BitMiracle.Docotic.Pdf;
using System;
class Program
{
static void Main()
{
using (var pdf1 = new PdfDocument("document1.pdf"))
using (var pdf2 = new PdfDocument("document2.pdf"))
{
pdf1.Append(pdf2);
pdf1.Save("merged.pdf");
}
Console.WriteLine("PDFs merged successfully");
}
}// NuGet: Install-Package Docotic.Pdf
using BitMiracle.Docotic.Pdf;
using System;
class Program
{
static void Main()
{
using (var pdf1 = new PdfDocument("document1.pdf"))
using (var pdf2 = new PdfDocument("document2.pdf"))
{
pdf1.Append(pdf2);
pdf1.Save("merged.pdf");
}
Console.WriteLine("PDFs merged successfully");
}
}IronPDF Implementation:
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
var pdf1 = PdfDocument.FromFile("document1.pdf");
var pdf2 = PdfDocument.FromFile("document2.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("document1.pdf");
var pdf2 = PdfDocument.FromFile("document2.pdf");
var merged = PdfDocument.Merge(new List<PdfDocument> { pdf1, pdf2 });
merged.SaveAs("merged.pdf");
Console.WriteLine("PDFs merged successfully");
}
}IronPDF's static Merge method accepts multiple documents directly, providing a cleaner API than the iterative Append pattern. For more options, see the PDF merging documentation.
Text Extraction
BitMiracle Docotic PDF Implementation:
// NuGet: Install-Package Docotic.Pdf
using BitMiracle.Docotic.Pdf;
using System;
class Program
{
static void Main()
{
using (var pdf = new PdfDocument("document.pdf"))
{
string allText = "";
foreach (var page in pdf.Pages)
{
allText += page.GetText();
}
Console.WriteLine("Extracted text:");
Console.WriteLine(allText);
}
}
}// NuGet: Install-Package Docotic.Pdf
using BitMiracle.Docotic.Pdf;
using System;
class Program
{
static void Main()
{
using (var pdf = new PdfDocument("document.pdf"))
{
string allText = "";
foreach (var page in pdf.Pages)
{
allText += page.GetText();
}
Console.WriteLine("Extracted text:");
Console.WriteLine(allText);
}
}
}IronPDF Implementation:
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var pdf = PdfDocument.FromFile("document.pdf");
string allText = pdf.ExtractAllText();
Console.WriteLine("Extracted text:");
Console.WriteLine(allText);
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var pdf = PdfDocument.FromFile("document.pdf");
string allText = pdf.ExtractAllText();
Console.WriteLine("Extracted text:");
Console.WriteLine(allText);
}
}IronPDF reduces the text extraction from a multi-line loop to a single method call. For more extraction options, see the text extraction documentation.
Password Protection and Encryption
IronPDF Implementation:
using IronPdf;
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Confidential Document</h1>");
// Set security
pdf.SecuritySettings.UserPassword = "userPassword";
pdf.SecuritySettings.OwnerPassword = "ownerPassword";
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.FullPrintRights;
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SaveAs("protected.pdf");using IronPdf;
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Confidential Document</h1>");
// Set security
pdf.SecuritySettings.UserPassword = "userPassword";
pdf.SecuritySettings.OwnerPassword = "ownerPassword";
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.FullPrintRights;
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SaveAs("protected.pdf");For comprehensive security options, see the encryption documentation.
Headers and Footers
IronPDF Implementation:
using IronPdf;
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
HtmlFragment = @"
<div style='text-align:center; font-size:12px;'>
Company Header - Confidential
</div>",
DrawDividerLine = true,
MaxHeight = 30
};
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
HtmlFragment = @"
<div style='text-align:center; font-size:10px;'>
Page {page} of {total-pages}
</div>",
DrawDividerLine = true,
MaxHeight = 25
};
var pdf = renderer.RenderHtmlAsPdf("<h1>Document Content</h1>");
pdf.SaveAs("with_headers.pdf");using IronPdf;
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
HtmlFragment = @"
<div style='text-align:center; font-size:12px;'>
Company Header - Confidential
</div>",
DrawDividerLine = true,
MaxHeight = 30
};
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
HtmlFragment = @"
<div style='text-align:center; font-size:10px;'>
Page {page} of {total-pages}
</div>",
DrawDividerLine = true,
MaxHeight = 25
};
var pdf = renderer.RenderHtmlAsPdf("<h1>Document Content</h1>");
pdf.SaveAs("with_headers.pdf");IronPDF supports placeholder tokens like {page} and {total-pages} for dynamic page numbering. For more options, see the headers and footers documentation.
Critical Migration Notes
Canvas to HTML Paradigm Shift
BitMiracle Docotic PDF's canvas-based drawing approach must be converted to HTML with CSS positioning:
BitMiracle Docotic PDF Pattern:
var canvas = pdfPage.Canvas;
canvas.DrawString(50, 50, "Hello, World!");var canvas = pdfPage.Canvas;
canvas.DrawString(50, 50, "Hello, World!");IronPDF Pattern:
var html = "<div style='position:absolute; left:50px; top:50px;'>Hello, World!</div>";
var pdf = renderer.RenderHtmlAsPdf(html);var html = "<div style='position:absolute; left:50px; top:50px;'>Hello, World!</div>";
var pdf = renderer.RenderHtmlAsPdf(html);Same Page Indexing
Both libraries use 0-based indexing (Pages[0] is the first page)—no changes needed for page access code.
Disposal Not Required
IronPDF doesn't require using statements for memory management, simplifying code structure:
// BitMiracle Docotic PDF - disposal required
using (var pdf = new PdfDocument("input.pdf"))
{
// operations
}
// IronPDF - disposal optional
var pdf = PdfDocument.FromFile("input.pdf");
// operations - no using statement needed// BitMiracle Docotic PDF - disposal required
using (var pdf = new PdfDocument("input.pdf"))
{
// operations
}
// IronPDF - disposal optional
var pdf = PdfDocument.FromFile("input.pdf");
// operations - no using statement neededAsync Support
BitMiracle Docotic PDF's HtmlToPdf add-on requires async patterns everywhere. IronPDF supports both synchronous and asynchronous methods:
// Synchronous
var pdf = renderer.RenderHtmlAsPdf(html);
// Asynchronous
var pdf = await renderer.RenderHtmlAsPdfAsync(html);// Synchronous
var pdf = renderer.RenderHtmlAsPdf(html);
// Asynchronous
var pdf = await renderer.RenderHtmlAsPdfAsync(html);ASP.NET Core Integration
IronPDF Pattern:
[ApiController]
[Route("[controller]")]
public class PdfController : ControllerBase
{
[HttpGet("generate")]
public IActionResult GeneratePdf()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Report</h1>");
return File(pdf.BinaryData, "application/pdf", "report.pdf");
}
[HttpGet("generate-async")]
public async Task<IActionResult> GeneratePdfAsync()
{
var renderer = new ChromePdfRenderer();
var pdf = await renderer.RenderHtmlAsPdfAsync("<h1>Report</h1>");
return File(pdf.Stream, "application/pdf", "report.pdf");
}
}[ApiController]
[Route("[controller]")]
public class PdfController : ControllerBase
{
[HttpGet("generate")]
public IActionResult GeneratePdf()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Report</h1>");
return File(pdf.BinaryData, "application/pdf", "report.pdf");
}
[HttpGet("generate-async")]
public async Task<IActionResult> GeneratePdfAsync()
{
var renderer = new ChromePdfRenderer();
var pdf = await renderer.RenderHtmlAsPdfAsync("<h1>Report</h1>");
return File(pdf.Stream, "application/pdf", "report.pdf");
}
}Post-Migration Checklist
After completing the code migration, verify the following:
- Run all unit tests to verify PDF generation works correctly
- Compare PDF output quality (IronPDF's Chromium engine may render slightly differently—usually better)
- Verify text extraction accuracy
- Test form filling functionality
- Validate digital signatures if applicable
- Performance test batch operations
- Test in all target environments
- Update CI/CD pipelines
- Remove Docotic.Pdf license files
Future-Proofing Your PDF Infrastructure
With .NET 10 on the horizon and C# 14 introducing new language features, choosing a PDF library with a unified architecture simplifies dependency management and ensures consistent feature availability. IronPDF's single-package approach means you won't need to track multiple add-on version compatibility as projects extend into 2025 and 2026.
Additional Resources
Migrating from BitMiracle Docotic PDF to IronPDF eliminates the complexity of managing multiple add-on packages while providing the same Chromium-based HTML rendering capabilities. The transition from canvas-based drawing to HTML/CSS positioning leverages web development skills most .NET developers already possess, resulting in more maintainable PDF generation code.






