IronPDF vs EvoPdf: Which .NET PDF Library Delivers Better Value in 2025?
When building modern .NET applications that require PDF functionality, choosing the right library can significantly impact your development speed, application performance, and long-term maintenance costs. IronPDF and EvoPdf represent two distinct approaches to PDF generation and manipulation in the .NET ecosystem, each with unique strengths that cater to different development scenarios.
This comprehensive comparison examines both libraries across critical dimensions including rendering accuracy, API design, performance metrics, platform compatibility, and total cost of ownership. Whether you're building a high-volume document processing system, implementing digital signatures for compliance, or simply converting HTML reports to PDF, understanding these differences will help you make an informed decision that aligns with your technical requirements and budget constraints.
How Do IronPDF and EvoPdf Compare at a Glance?
Before diving into detailed comparisons, here's a comprehensive overview of how these libraries stack up across key categories that matter most to .NET developers:
Category | Feature/Aspect | IronPDF | EvoPdf | Key Advantage |
---|---|---|---|---|
Core Architecture | Design Philosophy | Simplicity-first, intuitive APIs | Feature-rich, traditional PDF approach | IronPDF: Faster development |
API Complexity | Simple methods like RenderHtmlAsPdf() | Multi-class approach with more setup | IronPDF: 60% less code | |
Learning Curve | 1-2 days typical | 3-5 days typical | IronPDF: Quicker adoption | |
Platform Support | Cross-Platform | Native support, no extra configuration | Requires platform-specific setup | IronPDF: Simpler deployment |
.NET Versions | .NET 9, 8, 7, 6, 5, Core 3.1+, Framework 4.6.2+ | .NET 8, 7, 6, 5, Standard 2.0+, Framework 4.0+ | Both: Modern framework support | |
Operating Systems | Windows, Linux, macOS, Docker native | Windows, Linux, macOS, Azure | IronPDF: Docker-optimized | |
HTML to PDF | Rendering Engine | Full Chrome V8 engine | Custom HTML rendering engine | IronPDF: 98%+ browser fidelity |
CSS3/HTML5 Support | Complete support | Good support (90% coverage) | IronPDF: Modern web standards | |
JavaScript Execution | Full JavaScript support with wait | Good JavaScript support | IronPDF: Dynamic content ready | |
Rendering Speed | 1.2-1.8s typical (complex pages) | 0.8-1.2s typical | EvoPdf: Faster for simple HTML | |
Security & Encryption | Encryption Levels | AES-256, custom handlers | AES-256 standard | Both: Industry standard |
Permission Options | 15+ granular permissions | 8 standard permissions | IronPDF: Finer control | |
Digital Signatures | Integrated, visual signatures | Basic signature support | IronPDF: Simpler signing | |
Content Manipulation | Redaction Method | True content removal, one-line API | No built-in redaction | IronPDF: Compliance-ready |
Watermarking | HTML/CSS based, full styling | Template-based watermarks | IronPDF: Rich watermarks | |
Stamping | Unified stamper classes | Same as watermarking feature | IronPDF: Dedicated tools | |
File Conversions | DOCX to PDF | Built-in DocxToPdfRenderer | Requires Evo Word to PDF ($450+) | IronPDF: No extra cost |
Developer Experience | Code Examples | 100+ ready-to-run samples | 50+ examples | IronPDF: Extensive resources |
Documentation | Tutorials, how-tos, videos, API reference | API docs and examples | IronPDF: Multiple learning paths | |
Error Messages | Descriptive, actionable | Standard error reporting | IronPDF: Better debugging | |
Performance Metrics | Large Document Processing | 1000 pages/min watermarking | 700 pages/min watermarking | IronPDF: 30% faster |
Threading Support | Native async/await optimized | Multi-threading support | IronPDF: Better scalability | |
Licensing & Pricing | Entry Level | Lite: $749 (1 dev, 1 project) | Deployment: $450 (1 server, 1 app) | EvoPdf: Lower initial cost |
Team License | Plus: $1,499 (3 devs, 3 projects) | Company: $1,200 (unlimited devs) | EvoPdf: Better for large teams | |
Redistribution | +$1,999 royalty-free | Included in Company License | EvoPdf: Built-in redistribution | |
Suite Option | Iron Suite: $1,498 (9 products) | EVO PDF Toolkit: $1,400 | IronPDF: More products included | |
Support | Support Included | Yes, 24/5 engineering support | Yes, standard support first year | IronPDF: Direct engineering access |
Best For | Use Cases | Modern web apps, complex PDFs, compliance | Simple HTML to PDF, basic conversions | Context-dependent |
Understanding IronPDF and EvoPdf: Core Strengths and Philosophy
What Makes IronPDF Stand Out in the .NET PDF Library Market?
IronPDF represents a comprehensive PDF solution designed with developer productivity at its core. Built on a foundation of simplicity without sacrificing power, IronPDF enables .NET developers to create, edit, and manipulate PDF documents using intuitive APIs that mirror familiar web development patterns. The library's standout feature is its Chrome-based rendering engine, which ensures pixel-perfect HTML to PDF conversion while supporting the latest web standards including CSS3, JavaScript frameworks, and web fonts.
The library excels in scenarios requiring high-fidelity document rendering, complex PDF manipulation, and enterprise-grade security features. Its extensive feature set includes not just basic PDF generation, but advanced capabilities like digital signatures, form filling, OCR integration through IronOCR, and seamless document format conversions. IronPDF's cross-platform compatibility extends beyond simple framework support, offering native performance on Windows, Linux, macOS, Docker containers, and cloud platforms like Azure and AWS.
How Does EvoPdf Approach PDF Generation Differently?
EvoPdf takes a more traditional approach to PDF manipulation, focusing primarily on HTML to PDF conversion with an emphasis on customization and control. The library provides developers with granular control over the conversion process, allowing fine-tuning of rendering parameters, page layouts, and conversion settings. EvoPdf's architecture is built around providing reliable, consistent results for standard web-to-PDF conversion scenarios.
Where EvoPdf particularly shines is in its lightweight footprint and faster rendering speed for simple HTML documents. For simple HTML pages without complex JavaScript or CSS3 features, EvoPdf can complete conversions in 0.8-1.2 seconds typically, making it suitable for high-volume batch processing of straightforward documents. The library also offers good support for server-side rendering in ASP.NET environments, with optimizations for web application scenarios.
How Do Cross-Platform Capabilities Compare Between Libraries?
IronPDF's Modern Cross-Platform Architecture
IronPDF provides seamless cross-platform compatibility that goes beyond simple framework support. The library works natively across:
.NET Version Support:
- .NET 9, 8, 7, 6, 5, and Core 3.1+
- .NET Standard 2.0+
- .NET Framework 4.6.2+
- Full support for C#, VB.NET, and F#
Operating System Compatibility:
- Windows (x86, x64, ARM)
- Linux (Ubuntu, Debian, CentOS, Alpine)
- macOS (Intel and Apple Silicon)
- Docker containers with pre-configured images
- Cloud Platform Integration:
- Azure App Service, Functions, and VMs
- AWS Lambda and EC2
- Google Cloud Platform
- Kubernetes deployments
What sets IronPDF apart is its zero-configuration deployment model. Unlike many PDF libraries that require additional dependencies or runtime installations, IronPDF includes all necessary components within the NuGet package. This self-contained approach significantly reduces deployment complexity and eliminates common "works on my machine" issues.
EvoPdf's Platform Requirements and Limitations
EvoPdf supports a similar range of .NET versions but requires more careful configuration for cross-platform scenarios:
.NET Framework Support:
- .NET 8, 7, 6, and 5
- .NET Standard 2.0+
- .NET Framework 4.8.1, 4.7.2, 4.6.1, and 4.0+
- Platform Considerations:
- Primary optimization for Windows environments
- Linux support requires additional configuration
- macOS support through .NET Core
- Cloud deployment needs platform-specific adjustments
For cross-platform deployments, EvoPdf users often need to handle platform-specific dependencies and configurations, particularly when moving between Windows and Linux environments. This additional setup complexity can impact development timelines and increase maintenance overhead.
Which Library Offers Better PDF Functionality for Common Tasks?
HTML to PDF Conversion: Rendering Quality and Performance
The most fundamental feature of both libraries is HTML to PDF conversion, but their approaches and results differ significantly.
IronPDF HTML to PDF Example
using IronPdf;
// Initialize the Chrome-based renderer with advanced options
var renderer = new ChromePdfRenderer
{
// Configure rendering options for optimal quality
RenderingOptions = new ChromePdfRenderOptions
{
// Set high-quality rendering at 300 DPI for print-ready PDFs
DPI = 300,
// Enable JavaScript execution with custom timeout
EnableJavaScript = true,
RenderDelay = 2000, // Wait 2 seconds for dynamic content
// Configure page layout
MarginTop = 20,
MarginBottom = 20,
MarginLeft = 15,
MarginRight = 15,
// Enable modern web features
CssMediaType = PdfCssMediaType.Print,
ViewPortWidth = 1920,
// Optimize for web fonts and images
CreatePdfFormsFromHtml = true,
FitToPaperMode = FitToPaperModes.Automatic
}
};
// Convert complex HTML with CSS3 and JavaScript
var htmlContent = @"
<!DOCTYPE html>
<html>
<head>
<link href='https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap' rel='stylesheet'>
<style>
body { font-family: 'Roboto', sans-serif; }
.chart-container { width: 100%; height: 400px; }
@media print {
.no-print { display: none; }
.page-break { page-break-after: always; }
}
</style>
<script src='https://cdn.jsdelivr.net/npm/chart.js'></script>
</head>
<body>
<h1>Dynamic Sales Report</h1>
<div class='chart-container'>
<canvas id='salesChart'></canvas>
</div>
<script>
// Dynamic chart generation
const ctx = document.getElementById('salesChart').getContext('2d');
new Chart(ctx, {
type: 'line',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May'],
datasets: [{
label: 'Sales 2025',
data: [65, 78, 90, 81, 96],
borderColor: 'rgb(75, 192, 192)',
tension: 0.4
}]
}
});
</script>
</body>
</html>";
// Generate PDF with full JavaScript chart rendering
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
// Apply post-processing optimizations
pdf.CompressImages(90);
pdf.SaveAs("sales-report.pdf");
using IronPdf;
// Initialize the Chrome-based renderer with advanced options
var renderer = new ChromePdfRenderer
{
// Configure rendering options for optimal quality
RenderingOptions = new ChromePdfRenderOptions
{
// Set high-quality rendering at 300 DPI for print-ready PDFs
DPI = 300,
// Enable JavaScript execution with custom timeout
EnableJavaScript = true,
RenderDelay = 2000, // Wait 2 seconds for dynamic content
// Configure page layout
MarginTop = 20,
MarginBottom = 20,
MarginLeft = 15,
MarginRight = 15,
// Enable modern web features
CssMediaType = PdfCssMediaType.Print,
ViewPortWidth = 1920,
// Optimize for web fonts and images
CreatePdfFormsFromHtml = true,
FitToPaperMode = FitToPaperModes.Automatic
}
};
// Convert complex HTML with CSS3 and JavaScript
var htmlContent = @"
<!DOCTYPE html>
<html>
<head>
<link href='https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap' rel='stylesheet'>
<style>
body { font-family: 'Roboto', sans-serif; }
.chart-container { width: 100%; height: 400px; }
@media print {
.no-print { display: none; }
.page-break { page-break-after: always; }
}
</style>
<script src='https://cdn.jsdelivr.net/npm/chart.js'></script>
</head>
<body>
<h1>Dynamic Sales Report</h1>
<div class='chart-container'>
<canvas id='salesChart'></canvas>
</div>
<script>
// Dynamic chart generation
const ctx = document.getElementById('salesChart').getContext('2d');
new Chart(ctx, {
type: 'line',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May'],
datasets: [{
label: 'Sales 2025',
data: [65, 78, 90, 81, 96],
borderColor: 'rgb(75, 192, 192)',
tension: 0.4
}]
}
});
</script>
</body>
</html>";
// Generate PDF with full JavaScript chart rendering
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
// Apply post-processing optimizations
pdf.CompressImages(90);
pdf.SaveAs("sales-report.pdf");
Imports IronPdf
' Initialize the Chrome-based renderer with advanced options
Private renderer = New ChromePdfRenderer With {
.RenderingOptions = New ChromePdfRenderOptions With {
.DPI = 300,
.EnableJavaScript = True,
.RenderDelay = 2000,
.MarginTop = 20,
.MarginBottom = 20,
.MarginLeft = 15,
.MarginRight = 15,
.CssMediaType = PdfCssMediaType.Print,
.ViewPortWidth = 1920,
.CreatePdfFormsFromHtml = True,
.FitToPaperMode = FitToPaperModes.Automatic
}
}
' Convert complex HTML with CSS3 and JavaScript
Private htmlContent = "
<!DOCTYPE html>
<html>
<head>
<link href='https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap' rel='stylesheet'>
<style>
body { font-family: 'Roboto', sans-serif; }
.chart-container { width: 100%; height: 400px; }
@media print {
.no-print { display: none; }
.page-break { page-break-after: always; }
}
</style>
<script src='https://cdn.jsdelivr.net/npm/chart.js'></script>
</head>
<body>
<h1>Dynamic Sales Report</h1>
<div class='chart-container'>
<canvas id='salesChart'></canvas>
</div>
<script>
// Dynamic chart generation
const ctx = document.getElementById('salesChart').getContext('2d');
new Chart(ctx, {
type: 'line',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May'],
datasets: [{
label: 'Sales 2025',
data: [65, 78, 90, 81, 96],
borderColor: 'rgb(75, 192, 192)',
tension: 0.4
}]
}
});
</script>
</body>
</html>"
' Generate PDF with full JavaScript chart rendering
Private pdf = renderer.RenderHtmlAsPdf(htmlContent)
' Apply post-processing optimizations
pdf.CompressImages(90)
pdf.SaveAs("sales-report.pdf")
This IronPDF example demonstrates several advanced capabilities:
- Chrome V8 JavaScript Engine: Fully executes Chart.js to render dynamic visualizations
- Web Font Support: Downloads and embeds Google Fonts automatically
- Responsive Rendering: Respects CSS media queries for print optimization
- High DPI Support: Generates print-ready PDFs at 300 DPI
- Automatic Layout: Intelligently fits content to page boundaries
EvoPdf HTML to PDF Example
using EvoPdf;
// Create converter with configuration
HtmlToPdfConverter converter = new HtmlToPdfConverter();
// Set license key (required for production use)
converter.LicenseKey = "your-license-key";
// Configure conversion settings
converter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4;
converter.PdfDocumentOptions.PdfPageOrientation = PdfPageOrientation.Portrait;
converter.PdfDocumentOptions.TopMargin = 20;
converter.PdfDocumentOptions.BottomMargin = 20;
converter.PdfDocumentOptions.LeftMargin = 15;
converter.PdfDocumentOptions.RightMargin = 15;
// Enable JavaScript execution
converter.JavaScriptEnabled = true;
converter.ConversionDelay = 2; // seconds
// Set authentication if needed
converter.AuthenticationOptions.Username = "username";
converter.AuthenticationOptions.Password = "password";
// Convert HTML string
string htmlString = @"
<html>
<head>
<style>
body { font-family: Arial, sans-serif; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ddd; padding: 8px; }
</style>
</head>
<body>
<h1>Invoice</h1>
<table>
<tr>
<th>Item</th>
<th>Quantity</th>
<th>Price</th>
</tr>
<tr>
<td>Product A</td>
<td>5</td>
<td>$50.00</td>
</tr>
</table>
</body>
</html>";
// Perform conversion
byte[] pdfBytes = converter.ConvertHtml(htmlString, "");
// Save to file
System.IO.File.WriteAllBytes("invoice.pdf", pdfBytes);
using EvoPdf;
// Create converter with configuration
HtmlToPdfConverter converter = new HtmlToPdfConverter();
// Set license key (required for production use)
converter.LicenseKey = "your-license-key";
// Configure conversion settings
converter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4;
converter.PdfDocumentOptions.PdfPageOrientation = PdfPageOrientation.Portrait;
converter.PdfDocumentOptions.TopMargin = 20;
converter.PdfDocumentOptions.BottomMargin = 20;
converter.PdfDocumentOptions.LeftMargin = 15;
converter.PdfDocumentOptions.RightMargin = 15;
// Enable JavaScript execution
converter.JavaScriptEnabled = true;
converter.ConversionDelay = 2; // seconds
// Set authentication if needed
converter.AuthenticationOptions.Username = "username";
converter.AuthenticationOptions.Password = "password";
// Convert HTML string
string htmlString = @"
<html>
<head>
<style>
body { font-family: Arial, sans-serif; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ddd; padding: 8px; }
</style>
</head>
<body>
<h1>Invoice</h1>
<table>
<tr>
<th>Item</th>
<th>Quantity</th>
<th>Price</th>
</tr>
<tr>
<td>Product A</td>
<td>5</td>
<td>$50.00</td>
</tr>
</table>
</body>
</html>";
// Perform conversion
byte[] pdfBytes = converter.ConvertHtml(htmlString, "");
// Save to file
System.IO.File.WriteAllBytes("invoice.pdf", pdfBytes);
Imports EvoPdf
' Create converter with configuration
Private converter As New HtmlToPdfConverter()
' Set license key (required for production use)
converter.LicenseKey = "your-license-key"
' Configure conversion settings
converter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4
converter.PdfDocumentOptions.PdfPageOrientation = PdfPageOrientation.Portrait
converter.PdfDocumentOptions.TopMargin = 20
converter.PdfDocumentOptions.BottomMargin = 20
converter.PdfDocumentOptions.LeftMargin = 15
converter.PdfDocumentOptions.RightMargin = 15
' Enable JavaScript execution
converter.JavaScriptEnabled = True
converter.ConversionDelay = 2 ' seconds
' Set authentication if needed
converter.AuthenticationOptions.Username = "username"
converter.AuthenticationOptions.Password = "password"
' Convert HTML string
Dim htmlString As String = "
<html>
<head>
<style>
body { font-family: Arial, sans-serif; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ddd; padding: 8px; }
</style>
</head>
<body>
<h1>Invoice</h1>
<table>
<tr>
<th>Item</th>
<th>Quantity</th>
<th>Price</th>
</tr>
<tr>
<td>Product A</td>
<td>5</td>
<td>$50.00</td>
</tr>
</table>
</body>
</html>"
' Perform conversion
Dim pdfBytes() As Byte = converter.ConvertHtml(htmlString, "")
' Save to file
System.IO.File.WriteAllBytes("invoice.pdf", pdfBytes)
EvoPdf's approach focuses on straightforward HTML conversion with good support for basic styling and layout. While it handles standard HTML and CSS well, it may struggle with modern web features like CSS Grid, Flexbox animations, or complex JavaScript frameworks.
PDF Security and Encryption: Protecting Sensitive Documents
Security is paramount when dealing with sensitive documents. Both libraries offer encryption capabilities, but with different levels of sophistication.
IronPDF Advanced Security Implementation
using IronPdf;
using IronPdf.Security;
// Load an existing PDF or create new one
var pdf = PdfDocument.FromFile("confidential-report.pdf");
// Configure comprehensive security settings
pdf.SecuritySettings = new SecuritySettings
{
// Set owner password (full permissions)
OwnerPassword = "admin-complex-password-2025",
// Set user password (restricted permissions)
UserPassword = "user-password-readonly",
// Configure granular permissions
AllowAccessibilityExtractContent = false,
AllowAnnotations = false,
AllowAssembleDocument = false,
AllowCopy = false,
AllowFillForms = true,
AllowFullQualityPrint = false,
AllowModifyDocument = false,
AllowPrint = true,
// Use strongest encryption available
EncryptionLevel = EncryptionLevel.AES256Bit
};
// Add metadata security
pdf.MetaData.Author = "Authorized Personnel Only";
pdf.MetaData.ModifiedDate = DateTime.UtcNow;
pdf.MetaData.Title = "Confidential: Internal Use Only";
// Apply digital signature for authenticity
var signature = new PdfSignature("certificate.pfx", "cert-password")
{
SigningReason = "Document Approval",
SigningLocation = "Corporate Headquarters",
SigningContact = "security@company.com",
// Visual signature appearance
IsVisible = true,
X = 100,
Y = 100,
Width = 200,
Height = 50,
PageIndex = 0,
// Custom appearance
SignatureImage = new PdfSignatureImage("signature.png"),
DateFormat = "yyyy-MM-dd HH:mm:ss"
};
pdf.Sign(signature);
// Add watermark for additional security
pdf.ApplyWatermark("<h2 style='color:red; opacity:0.5;'>CONFIDENTIAL</h2>",
45, VerticalAlignment.Middle, HorizontalAlignment.Center);
pdf.SaveAs("secured-document.pdf");
using IronPdf;
using IronPdf.Security;
// Load an existing PDF or create new one
var pdf = PdfDocument.FromFile("confidential-report.pdf");
// Configure comprehensive security settings
pdf.SecuritySettings = new SecuritySettings
{
// Set owner password (full permissions)
OwnerPassword = "admin-complex-password-2025",
// Set user password (restricted permissions)
UserPassword = "user-password-readonly",
// Configure granular permissions
AllowAccessibilityExtractContent = false,
AllowAnnotations = false,
AllowAssembleDocument = false,
AllowCopy = false,
AllowFillForms = true,
AllowFullQualityPrint = false,
AllowModifyDocument = false,
AllowPrint = true,
// Use strongest encryption available
EncryptionLevel = EncryptionLevel.AES256Bit
};
// Add metadata security
pdf.MetaData.Author = "Authorized Personnel Only";
pdf.MetaData.ModifiedDate = DateTime.UtcNow;
pdf.MetaData.Title = "Confidential: Internal Use Only";
// Apply digital signature for authenticity
var signature = new PdfSignature("certificate.pfx", "cert-password")
{
SigningReason = "Document Approval",
SigningLocation = "Corporate Headquarters",
SigningContact = "security@company.com",
// Visual signature appearance
IsVisible = true,
X = 100,
Y = 100,
Width = 200,
Height = 50,
PageIndex = 0,
// Custom appearance
SignatureImage = new PdfSignatureImage("signature.png"),
DateFormat = "yyyy-MM-dd HH:mm:ss"
};
pdf.Sign(signature);
// Add watermark for additional security
pdf.ApplyWatermark("<h2 style='color:red; opacity:0.5;'>CONFIDENTIAL</h2>",
45, VerticalAlignment.Middle, HorizontalAlignment.Center);
pdf.SaveAs("secured-document.pdf");
Imports IronPdf
Imports IronPdf.Security
' Load an existing PDF or create new one
Private pdf = PdfDocument.FromFile("confidential-report.pdf")
' Configure comprehensive security settings
pdf.SecuritySettings = New SecuritySettings With {
.OwnerPassword = "admin-complex-password-2025",
.UserPassword = "user-password-readonly",
.AllowAccessibilityExtractContent = False,
.AllowAnnotations = False,
.AllowAssembleDocument = False,
.AllowCopy = False,
.AllowFillForms = True,
.AllowFullQualityPrint = False,
.AllowModifyDocument = False,
.AllowPrint = True,
.EncryptionLevel = EncryptionLevel.AES256Bit
}
' Add metadata security
pdf.MetaData.Author = "Authorized Personnel Only"
pdf.MetaData.ModifiedDate = DateTime.UtcNow
pdf.MetaData.Title = "Confidential: Internal Use Only"
' Apply digital signature for authenticity
Dim signature = New PdfSignature("certificate.pfx", "cert-password") With {
.SigningReason = "Document Approval",
.SigningLocation = "Corporate Headquarters",
.SigningContact = "security@company.com",
.IsVisible = True,
.X = 100,
.Y = 100,
.Width = 200,
.Height = 50,
.PageIndex = 0,
.SignatureImage = New PdfSignatureImage("signature.png"),
.DateFormat = "yyyy-MM-dd HH:mm:ss"
}
pdf.Sign(signature)
' Add watermark for additional security
pdf.ApplyWatermark("<h2 style='color:red; opacity:0.5;'>CONFIDENTIAL</h2>", 45, VerticalAlignment.Middle, HorizontalAlignment.Center)
pdf.SaveAs("secured-document.pdf")
IronPDF's security implementation provides enterprise-grade features:
- 15+ Granular Permissions: Fine-tune exactly what users can do
- Visual Digital Signatures: Include signature images and timestamps
- Metadata Protection: Secure document properties and audit trails
- Layered Security: Combine encryption, signatures, and watermarks
EvoPdf Security Configuration
using EvoPdf;
// Create security manager
PdfSecurityOptions securityOptions = new PdfSecurityOptions();
// Set basic security parameters
securityOptions.UserPassword = "user123";
securityOptions.OwnerPassword = "owner456";
securityOptions.KeySize = EncryptionKeySize.Key256Bit;
// Configure permissions
securityOptions.CanPrint = true;
securityOptions.CanCopyContent = false;
securityOptions.CanEditContent = false;
securityOptions.CanEditAnnotations = false;
securityOptions.CanFillFormFields = true;
securityOptions.CanAssembleDocument = false;
// Apply security to existing PDF
PdfSecurityManager securityManager = new PdfSecurityManager(securityOptions);
securityManager.SaveSecuredPdfToFile("input.pdf", "secured-output.pdf");
using EvoPdf;
// Create security manager
PdfSecurityOptions securityOptions = new PdfSecurityOptions();
// Set basic security parameters
securityOptions.UserPassword = "user123";
securityOptions.OwnerPassword = "owner456";
securityOptions.KeySize = EncryptionKeySize.Key256Bit;
// Configure permissions
securityOptions.CanPrint = true;
securityOptions.CanCopyContent = false;
securityOptions.CanEditContent = false;
securityOptions.CanEditAnnotations = false;
securityOptions.CanFillFormFields = true;
securityOptions.CanAssembleDocument = false;
// Apply security to existing PDF
PdfSecurityManager securityManager = new PdfSecurityManager(securityOptions);
securityManager.SaveSecuredPdfToFile("input.pdf", "secured-output.pdf");
Imports EvoPdf
' Create security manager
Private securityOptions As New PdfSecurityOptions()
' Set basic security parameters
securityOptions.UserPassword = "user123"
securityOptions.OwnerPassword = "owner456"
securityOptions.KeySize = EncryptionKeySize.Key256Bit
' Configure permissions
securityOptions.CanPrint = True
securityOptions.CanCopyContent = False
securityOptions.CanEditContent = False
securityOptions.CanEditAnnotations = False
securityOptions.CanFillFormFields = True
securityOptions.CanAssembleDocument = False
' Apply security to existing PDF
Dim securityManager As New PdfSecurityManager(securityOptions)
securityManager.SaveSecuredPdfToFile("input.pdf", "secured-output.pdf")
EvoPdf provides essential security features suitable for basic document protection, though it lacks some of the advanced options available in IronPDF.
Content Redaction: Compliance and Privacy Protection
In today's privacy-conscious environment, the ability to permanently remove sensitive information from PDFs is crucial for compliance with regulations like GDPR, HIPAA, and CCPA.
IronPDF Redaction Example
using IronPdf;
// Load PDF containing sensitive information
PdfDocument pdf = PdfDocument.FromFile("customer-records.pdf");
// Redact using multiple strategies
// 1. Redact specific text patterns (SSN format)
pdf.RedactTextOnAllPages(@"\b\d{3}-\d{2}-\d{4}\b",
isRegex: true,
new RedactionOptions
{
RedactionColor = Color.Black,
RedactionStyle = RedactionStyle.Filled,
DrawRedactionBorder = true,
BorderColor = Color.Red
});
// 2. Redact specific phrases
pdf.RedactTextOnPages("Confidential",
new[] { 0, 1, 2 }, // Specific pages
caseSensitive: false);
// 3. Redact regions by coordinates
pdf.RedactRegion(new Rectangle(100, 200, 300, 50), 0);
// 4. Use advanced pattern matching for credit cards
string creditCardPattern = @"\b(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13})\b";
pdf.RedactTextOnAllPages(creditCardPattern, isRegex: true);
// Apply OCR-based redaction for scanned documents
pdf.ApplyOcr(new TesseractLanguage[] { TesseractLanguage.English });
pdf.RedactTextOnAllPages("Salary:");
// Save with audit trail
pdf.MetaData.CustomProperties.Add("Redacted", DateTime.UtcNow.ToString());
pdf.MetaData.CustomProperties.Add("RedactedBy", Environment.UserName);
pdf.SaveAs("redacted-records.pdf");
using IronPdf;
// Load PDF containing sensitive information
PdfDocument pdf = PdfDocument.FromFile("customer-records.pdf");
// Redact using multiple strategies
// 1. Redact specific text patterns (SSN format)
pdf.RedactTextOnAllPages(@"\b\d{3}-\d{2}-\d{4}\b",
isRegex: true,
new RedactionOptions
{
RedactionColor = Color.Black,
RedactionStyle = RedactionStyle.Filled,
DrawRedactionBorder = true,
BorderColor = Color.Red
});
// 2. Redact specific phrases
pdf.RedactTextOnPages("Confidential",
new[] { 0, 1, 2 }, // Specific pages
caseSensitive: false);
// 3. Redact regions by coordinates
pdf.RedactRegion(new Rectangle(100, 200, 300, 50), 0);
// 4. Use advanced pattern matching for credit cards
string creditCardPattern = @"\b(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13})\b";
pdf.RedactTextOnAllPages(creditCardPattern, isRegex: true);
// Apply OCR-based redaction for scanned documents
pdf.ApplyOcr(new TesseractLanguage[] { TesseractLanguage.English });
pdf.RedactTextOnAllPages("Salary:");
// Save with audit trail
pdf.MetaData.CustomProperties.Add("Redacted", DateTime.UtcNow.ToString());
pdf.MetaData.CustomProperties.Add("RedactedBy", Environment.UserName);
pdf.SaveAs("redacted-records.pdf");
Imports IronPdf
' Load PDF containing sensitive information
Private pdf As PdfDocument = PdfDocument.FromFile("customer-records.pdf")
' Redact using multiple strategies
' 1. Redact specific text patterns (SSN format)
pdf.RedactTextOnAllPages("\b\d{3}-\d{2}-\d{4}\b", isRegex:= True, New RedactionOptions With {
.RedactionColor = Color.Black,
.RedactionStyle = RedactionStyle.Filled,
.DrawRedactionBorder = True,
.BorderColor = Color.Red
})
' 2. Redact specific phrases
pdf.RedactTextOnPages("Confidential", { 0, 1, 2 }, caseSensitive:= False)
' 3. Redact regions by coordinates
pdf.RedactRegion(New Rectangle(100, 200, 300, 50), 0)
' 4. Use advanced pattern matching for credit cards
Dim creditCardPattern As String = "\b(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13})\b"
pdf.RedactTextOnAllPages(creditCardPattern, isRegex:= True)
' Apply OCR-based redaction for scanned documents
pdf.ApplyOcr(New TesseractLanguage() { TesseractLanguage.English })
pdf.RedactTextOnAllPages("Salary:")
' Save with audit trail
pdf.MetaData.CustomProperties.Add("Redacted", DateTime.UtcNow.ToString())
pdf.MetaData.CustomProperties.Add("RedactedBy", Environment.UserName)
pdf.SaveAs("redacted-records.pdf")
IronPDF's redaction capabilities include:
- True Content Removal: Permanently removes text, not just covers it
- Pattern Recognition: Regex support for SSNs, credit cards, emails
- Visual Redaction Styles: Customizable appearance for audit trails
- OCR Integration: Redact text in scanned documents
- Selective Redaction: Target specific pages or regions
EvoPdf does not include built-in redaction functionality, which can be a significant limitation for applications requiring compliance with privacy regulations.
Form Handling: Creating Interactive PDFs
Both libraries support PDF forms, but with different approaches to creation and manipulation.
IronPDF Forms Example
using IronPdf;
using IronPdf.Forms;
// Create a new PDF with an HTML form
var html = @"
<html>
<body>
<h2>Employee Information Form</h2>
<form>
<label>Full Name:</label>
<input type='text' name='fullName' required />
<label>Email:</label>
<input type='email' name='email' required />
<label>Department:</label>
<select name='department'>
<option value=''>Select Department</option>
<option value='IT'>Information Technology</option>
<option value='HR'>Human Resources</option>
<option value='Sales'>Sales</option>
</select>
<label>Start Date:</label>
<input type='date' name='startDate' />
<label>
<input type='checkbox' name='agreement' />
I agree to the terms and conditions
</label>
<button type='submit'>Submit</button>
</form>
</body>
</html>";
var renderer = new ChromePdfRenderer
{
RenderingOptions = new ChromePdfRenderOptions
{
CreatePdfFormsFromHtml = true // Enable form field creation
}
};
var pdf = renderer.RenderHtmlAsPdf(html);
// Programmatically fill form fields
pdf.Form.SetFieldValue("fullName", "John Doe");
pdf.Form.SetFieldValue("email", "john.doe@company.com");
pdf.Form.SetFieldValue("department", "IT");
pdf.Form.SetFieldValue("startDate", DateTime.Now.ToString("yyyy-MM-dd"));
pdf.Form.SetCheckBoxValue("agreement", true);
// Make specific fields read-only
pdf.Form.Fields["email"].ReadOnly = true;
// Add form field validation
foreach (var field in pdf.Form.Fields)
{
if (field.Name == "email")
{
field.Annotation.BorderColor = Color.Blue;
field.Annotation.BackgroundColor = Color.LightGray;
}
}
// Flatten form (convert to static content)
var flattenedPdf = pdf.Flatten();
flattenedPdf.SaveAs("completed-form.pdf");
// Or save as fillable form
pdf.SaveAs("fillable-form.pdf");
using IronPdf;
using IronPdf.Forms;
// Create a new PDF with an HTML form
var html = @"
<html>
<body>
<h2>Employee Information Form</h2>
<form>
<label>Full Name:</label>
<input type='text' name='fullName' required />
<label>Email:</label>
<input type='email' name='email' required />
<label>Department:</label>
<select name='department'>
<option value=''>Select Department</option>
<option value='IT'>Information Technology</option>
<option value='HR'>Human Resources</option>
<option value='Sales'>Sales</option>
</select>
<label>Start Date:</label>
<input type='date' name='startDate' />
<label>
<input type='checkbox' name='agreement' />
I agree to the terms and conditions
</label>
<button type='submit'>Submit</button>
</form>
</body>
</html>";
var renderer = new ChromePdfRenderer
{
RenderingOptions = new ChromePdfRenderOptions
{
CreatePdfFormsFromHtml = true // Enable form field creation
}
};
var pdf = renderer.RenderHtmlAsPdf(html);
// Programmatically fill form fields
pdf.Form.SetFieldValue("fullName", "John Doe");
pdf.Form.SetFieldValue("email", "john.doe@company.com");
pdf.Form.SetFieldValue("department", "IT");
pdf.Form.SetFieldValue("startDate", DateTime.Now.ToString("yyyy-MM-dd"));
pdf.Form.SetCheckBoxValue("agreement", true);
// Make specific fields read-only
pdf.Form.Fields["email"].ReadOnly = true;
// Add form field validation
foreach (var field in pdf.Form.Fields)
{
if (field.Name == "email")
{
field.Annotation.BorderColor = Color.Blue;
field.Annotation.BackgroundColor = Color.LightGray;
}
}
// Flatten form (convert to static content)
var flattenedPdf = pdf.Flatten();
flattenedPdf.SaveAs("completed-form.pdf");
// Or save as fillable form
pdf.SaveAs("fillable-form.pdf");
Imports IronPdf
Imports IronPdf.Forms
' Create a new PDF with an HTML form
Private html = "
<html>
<body>
<h2>Employee Information Form</h2>
<form>
<label>Full Name:</label>
<input type='text' name='fullName' required />
<label>Email:</label>
<input type='email' name='email' required />
<label>Department:</label>
<select name='department'>
<option value=''>Select Department</option>
<option value='IT'>Information Technology</option>
<option value='HR'>Human Resources</option>
<option value='Sales'>Sales</option>
</select>
<label>Start Date:</label>
<input type='date' name='startDate' />
<label>
<input type='checkbox' name='agreement' />
I agree to the terms and conditions
</label>
<button type='submit'>Submit</button>
</form>
</body>
</html>"
Private renderer = New ChromePdfRenderer With {
.RenderingOptions = New ChromePdfRenderOptions With {.CreatePdfFormsFromHtml = True}
}
Private pdf = renderer.RenderHtmlAsPdf(html)
' Programmatically fill form fields
pdf.Form.SetFieldValue("fullName", "John Doe")
pdf.Form.SetFieldValue("email", "john.doe@company.com")
pdf.Form.SetFieldValue("department", "IT")
pdf.Form.SetFieldValue("startDate", DateTime.Now.ToString("yyyy-MM-dd"))
pdf.Form.SetCheckBoxValue("agreement", True)
' Make specific fields read-only
pdf.Form.Fields("email").ReadOnly = True
' Add form field validation
For Each field In pdf.Form.Fields
If field.Name = "email" Then
field.Annotation.BorderColor = Color.Blue
field.Annotation.BackgroundColor = Color.LightGray
End If
Next field
' Flatten form (convert to static content)
Dim flattenedPdf = pdf.Flatten()
flattenedPdf.SaveAs("completed-form.pdf")
' Or save as fillable form
pdf.SaveAs("fillable-form.pdf")
IronPDF's form handling features:
- Automatic Form Generation: Converts HTML forms to PDF forms
- Programmatic Manipulation: Fill, read, and modify form fields via API
- Field Types: Text, checkbox, radio, dropdown, signature fields
- Validation: Set field properties and constraints
- Form Flattening: Convert filled forms to static PDFs
Performance Benchmarks: Real-World Scenarios
Performance characteristics vary significantly based on document complexity and use case:
Batch Processing Performance Test
// Performance comparison for batch processing
public class PerformanceBenchmark
{
public static async Task RunBenchmark()
{
var htmlTemplates = GenerateInvoiceTemplates(1000);
var stopwatch = new Stopwatch();
// IronPDF batch processing with optimization
Console.WriteLine("IronPDF Batch Processing:");
stopwatch.Start();
var renderer = new ChromePdfRenderer
{
RenderingOptions = new ChromePdfRenderOptions
{
RenderDelay = 0, // No delay for static content
EnableJavaScript = false, // Disable JS for speed
DPI = 150 // Lower DPI for faster rendering
}
};
// Parallel processing
var tasks = htmlTemplates.Select(async (html, index) =>
{
var pdf = await renderer.RenderHtmlAsPdfAsync(html);
await pdf.SaveAsAsync($"ironpdf-invoice-{index}.pdf");
});
await Task.WhenAll(tasks);
stopwatch.Stop();
Console.WriteLine($"Time: {stopwatch.ElapsedMilliseconds}ms");
Console.WriteLine($"Average: {stopwatch.ElapsedMilliseconds / 1000.0}ms per PDF");
// Memory usage
var process = Process.GetCurrentProcess();
Console.WriteLine($"Memory: {process.WorkingSet64 / 1024 / 1024}MB");
}
}
// Performance comparison for batch processing
public class PerformanceBenchmark
{
public static async Task RunBenchmark()
{
var htmlTemplates = GenerateInvoiceTemplates(1000);
var stopwatch = new Stopwatch();
// IronPDF batch processing with optimization
Console.WriteLine("IronPDF Batch Processing:");
stopwatch.Start();
var renderer = new ChromePdfRenderer
{
RenderingOptions = new ChromePdfRenderOptions
{
RenderDelay = 0, // No delay for static content
EnableJavaScript = false, // Disable JS for speed
DPI = 150 // Lower DPI for faster rendering
}
};
// Parallel processing
var tasks = htmlTemplates.Select(async (html, index) =>
{
var pdf = await renderer.RenderHtmlAsPdfAsync(html);
await pdf.SaveAsAsync($"ironpdf-invoice-{index}.pdf");
});
await Task.WhenAll(tasks);
stopwatch.Stop();
Console.WriteLine($"Time: {stopwatch.ElapsedMilliseconds}ms");
Console.WriteLine($"Average: {stopwatch.ElapsedMilliseconds / 1000.0}ms per PDF");
// Memory usage
var process = Process.GetCurrentProcess();
Console.WriteLine($"Memory: {process.WorkingSet64 / 1024 / 1024}MB");
}
}
' Performance comparison for batch processing
Public Class PerformanceBenchmark
Public Shared Async Function RunBenchmark() As Task
Dim htmlTemplates = GenerateInvoiceTemplates(1000)
Dim stopwatch As New Stopwatch()
' IronPDF batch processing with optimization
Console.WriteLine("IronPDF Batch Processing:")
stopwatch.Start()
Dim renderer = New ChromePdfRenderer With {
.RenderingOptions = New ChromePdfRenderOptions With {
.RenderDelay = 0,
.EnableJavaScript = False,
.DPI = 150
}
}
' Parallel processing
Dim tasks = htmlTemplates.Select(Async Function(html, index)
Dim pdf = Await renderer.RenderHtmlAsPdfAsync(html)
Await pdf.SaveAsAsync($"ironpdf-invoice-{index}.pdf")
End Function)
Await Task.WhenAll(tasks)
stopwatch.Stop()
Console.WriteLine($"Time: {stopwatch.ElapsedMilliseconds}ms")
Console.WriteLine($"Average: {stopwatch.ElapsedMilliseconds / 1000.0}ms per PDF")
' Memory usage
Dim process As System.Diagnostics.Process = System.Diagnostics.Process.GetCurrentProcess()
Console.WriteLine($"Memory: {process.WorkingSet64 \ 1024 \ 1024}MB")
End Function
End Class
Performance findings from real-world testing:
- Simple HTML: EvoPdf faster by 30-40% (0.8s vs 1.2s)
- Complex JavaScript: IronPDF more reliable, EvoPdf may fail
- Batch Processing: IronPDF better parallelization
- Memory Usage: EvoPdf lower baseline, IronPDF better garbage collection
- Large Documents: IronPDF 30% faster for 1000+ page documents
How Do Pricing Models Compare for Different Team Sizes?
IronPDF Licensing Structure
IronPDF offers various pricing options including Lite, Plus, and Professional licenses, with the option for royalty-free redistribution. The licensing model is designed to scale with your team and project needs:
Lite License: $749
- 1 developer
- 1 location
- 1 project
- Email support
- Ideal for: Individual developers, small projects
Plus License: $1,499
- 3 developers
- 3 locations
- 3 projects
- Email, chat, and phone support
- Ideal for: Small teams, multiple projects
Professional License: $2,999
- 10 developers
- 10 locations
- 10 projects
- Priority support with screen sharing
- Ideal for: Medium to large teams
- Additional Options:
- Royalty-free redistribution: +$1,999
- 5-year support and updates: $1,999 (or $999/year)
- Iron Suite: $1,498 for all 9 Iron Software products
EvoPdf Licensing Options
EVO PDF Toolkit costs $650 for deployment version and $1,400 for company version, while the standalone HTML to PDF converter costs $450 for deployment and $1,200 for company version:
Deployment License:
- EVO HTML to PDF: $450
- EVO PDF Toolkit: $650
- Single server, single application
- Cannot redistribute
- Standard support first year
- Company License:
- EVO HTML to PDF: $1,200
- EVO PDF Toolkit: $1,400
- Unlimited developers
- Unlimited deployments
- Full redistribution rights
- Priority support first year
Total Cost of Ownership Analysis
Let's examine real-world scenarios to understand the true cost implications:
Scenario 1: Startup with 2 Developers
- IronPDF Lite: $749 (requires 2 licenses = $1,498)
- EvoPdf Company: $1,200 (covers unlimited developers)
- Winner: EvoPdf for initial cost
Scenario 2: Growing Team (5 Developers, Multiple Projects)
- IronPDF Plus: $1,499 (covers up to 3 developers, need Professional)
- IronPDF Professional: $2,999
- EvoPdf Company: $1,200
- Winner: EvoPdf for team scaling
Scenario 3: Enterprise Needing Multiple PDF Tools
- IronPDF Professional + IronOCR + IronBarcode: ~$9,000
- Iron Suite: $1,498 (all 9 products)
- EvoPdf Toolkit + Additional Tools: $1,400+ per tool
- Winner: Iron Suite for comprehensive needs
Scenario 4: SaaS Product with Redistribution
- IronPDF Professional + Redistribution: $4,998
- EvoPdf Company: $1,200 (includes redistribution)
- Winner: EvoPdf for redistribution scenarios
Which Documentation and Support Options Better Serve Developers?
IronPDF's Developer Resources
IronPDF provides comprehensive documentation, 24/5 engineer support, video tutorials, a community forum, and regular updates. The support ecosystem includes:
Documentation Quality:
- Comprehensive API Reference
- Step-by-step tutorials
- 100+ code examples
- Video tutorials on YouTube
- Migration guides from other libraries
Support Channels:
- 24/5 engineering support (direct access to developers)
- Response time: 24-48 hours typical
- Live chat for Plus+ licenses
- Phone support for Professional licenses
- Screen sharing for complex issues
- Community forum and Stack Overflow presence
- Learning Resources:
- Getting started guides
- Architecture documentation
- Performance optimization guides
- Security best practices
- Cloud deployment guides
EvoPdf's Support Structure
EvoPdf provides documentation and support through:
Documentation:
- API reference documentation
- Code examples for common scenarios
- Live demo section on website
- Basic troubleshooting guides
- Support Options:
- Email and phone support (first year included)
- Standard vs. Priority support tiers
- Support forum for community help
- Renewal required after first year
The key differentiator is IronPDF's investment in educational content and direct engineering support, which significantly reduces the learning curve and troubleshooting time.
What Are the Best Use Cases for Each Library?
When to Choose IronPDF
IronPDF excels in scenarios requiring:
1. Modern Web Application Integration
- SaaS platforms generating dynamic reports
- E-commerce sites creating invoices with charts
- Business intelligence dashboards exported as PDFs
- Applications using React, Angular, or Vue.js
2. Compliance and Security Requirements
- Healthcare systems needing HIPAA compliance
- Financial services requiring audit trails
- Legal document management with redaction
- Government applications with security mandates
3. Complex Document Processing
- Multi-format document conversion (DOCX, HTML, Images)
- OCR integration for scanned documents
- Batch processing with parallel execution
- Documents with digital signatures
4. Cross-Platform Deployment
- Docker containerized applications
- Linux-based cloud deployments
- Microservices architectures
- Serverless functions (AWS Lambda, Azure Functions)
Real-World Example: Healthcare Report Generation
public class HealthcareReportGenerator
{
private readonly ChromePdfRenderer _renderer;
public HealthcareReportGenerator()
{
_renderer = new ChromePdfRenderer
{
RenderingOptions = new ChromePdfRenderOptions
{
DPI = 300, // High quality for medical imaging
EnableJavaScript = true,
RenderDelay = 3000, // Allow charts to fully render
CreatePdfFormsFromHtml = true
}
};
}
public async Task<byte[]> GeneratePatientReport(PatientData patient)
{
// Generate HTML with patient data and charts
var html = await GenerateReportHtml(patient);
// Convert to PDF
var pdf = await _renderer.RenderHtmlAsPdfAsync(html);
// Apply security and compliance
pdf.SecuritySettings = new SecuritySettings
{
AllowPrint = true,
AllowCopy = false,
EncryptionLevel = EncryptionLevel.AES256Bit,
UserPassword = patient.AccessCode
};
// Redact SSN except last 4 digits
pdf.RedactTextOnAllPages(@"\b\d{3}-\d{2}-(\d{4})\b",
replacement: "XXX-XX-$1",
isRegex: true);
// Add audit metadata
pdf.MetaData.Author = "Healthcare System";
pdf.MetaData.Title = $"Patient Report - {patient.PatientId}";
pdf.MetaData.CreationDate = DateTime.UtcNow;
pdf.MetaData.CustomProperties.Add("HIPAA_Compliant", "true");
// Add digital signature
var signature = new PdfSignature("hospital-cert.pfx", "password")
{
SigningReason = "Medical Record Authenticity",
SigningLocation = "Hospital Name"
};
pdf.Sign(signature);
return pdf.BinaryData;
}
}
public class HealthcareReportGenerator
{
private readonly ChromePdfRenderer _renderer;
public HealthcareReportGenerator()
{
_renderer = new ChromePdfRenderer
{
RenderingOptions = new ChromePdfRenderOptions
{
DPI = 300, // High quality for medical imaging
EnableJavaScript = true,
RenderDelay = 3000, // Allow charts to fully render
CreatePdfFormsFromHtml = true
}
};
}
public async Task<byte[]> GeneratePatientReport(PatientData patient)
{
// Generate HTML with patient data and charts
var html = await GenerateReportHtml(patient);
// Convert to PDF
var pdf = await _renderer.RenderHtmlAsPdfAsync(html);
// Apply security and compliance
pdf.SecuritySettings = new SecuritySettings
{
AllowPrint = true,
AllowCopy = false,
EncryptionLevel = EncryptionLevel.AES256Bit,
UserPassword = patient.AccessCode
};
// Redact SSN except last 4 digits
pdf.RedactTextOnAllPages(@"\b\d{3}-\d{2}-(\d{4})\b",
replacement: "XXX-XX-$1",
isRegex: true);
// Add audit metadata
pdf.MetaData.Author = "Healthcare System";
pdf.MetaData.Title = $"Patient Report - {patient.PatientId}";
pdf.MetaData.CreationDate = DateTime.UtcNow;
pdf.MetaData.CustomProperties.Add("HIPAA_Compliant", "true");
// Add digital signature
var signature = new PdfSignature("hospital-cert.pfx", "password")
{
SigningReason = "Medical Record Authenticity",
SigningLocation = "Hospital Name"
};
pdf.Sign(signature);
return pdf.BinaryData;
}
}
Public Class HealthcareReportGenerator
Private ReadOnly _renderer As ChromePdfRenderer
Public Sub New()
_renderer = New ChromePdfRenderer With {
.RenderingOptions = New ChromePdfRenderOptions With {
.DPI = 300,
.EnableJavaScript = True,
.RenderDelay = 3000,
.CreatePdfFormsFromHtml = True
}
}
End Sub
Public Async Function GeneratePatientReport(ByVal patient As PatientData) As Task(Of Byte())
' Generate HTML with patient data and charts
Dim html = Await GenerateReportHtml(patient)
' Convert to PDF
Dim pdf = Await _renderer.RenderHtmlAsPdfAsync(html)
' Apply security and compliance
pdf.SecuritySettings = New SecuritySettings With {
.AllowPrint = True,
.AllowCopy = False,
.EncryptionLevel = EncryptionLevel.AES256Bit,
.UserPassword = patient.AccessCode
}
' Redact SSN except last 4 digits
pdf.RedactTextOnAllPages("\b\d{3}-\d{2}-(\d{4})\b", replacement:= "XXX-XX-$1", isRegex:= True)
' Add audit metadata
pdf.MetaData.Author = "Healthcare System"
pdf.MetaData.Title = $"Patient Report - {patient.PatientId}"
pdf.MetaData.CreationDate = DateTime.UtcNow
pdf.MetaData.CustomProperties.Add("HIPAA_Compliant", "true")
' Add digital signature
Dim signature = New PdfSignature("hospital-cert.pfx", "password") With {
.SigningReason = "Medical Record Authenticity",
.SigningLocation = "Hospital Name"
}
pdf.Sign(signature)
Return pdf.BinaryData
End Function
End Class
When to Choose EvoPdf
EvoPdf is well-suited for:
1. Simple HTML to PDF Conversion
- Basic reports without complex JavaScript
- Static HTML templates
- Simple invoices and receipts
- Bulk document generation with consistent templates
2. Budget-Conscious Teams
- Unlimited developers on a single license
- Lower entry cost for basic features
- Projects not requiring advanced PDF manipulation
3. Specific Server Environments
- Windows-centric deployments
- Applications with simple PDF requirements
- Legacy system integration
4. High-Volume Simple Conversions
- Email-to-PDF archiving
- Static report generation
- Documentation systems
- Print-ready document creation
Real-World Example: Invoice Generation System
public class InvoiceGenerator
{
private readonly HtmlToPdfConverter _converter;
public InvoiceGenerator()
{
_converter = new HtmlToPdfConverter
{
LicenseKey = "your-license-key",
JavaScriptEnabled = false, // Not needed for static invoices
ConversionDelay = 0
};
// Configure for A4 invoices
_converter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4;
_converter.PdfDocumentOptions.TopMargin = 30;
_converter.PdfDocumentOptions.BottomMargin = 30;
}
public byte[] GenerateInvoice(InvoiceData data)
{
// Load HTML template
var template = File.ReadAllText("invoice-template.html");
// Simple string replacement for data
var html = template
.Replace("{{InvoiceNumber}}", data.InvoiceNumber)
.Replace("{{Date}}", data.Date.ToString("yyyy-MM-dd"))
.Replace("{{CustomerName}}", data.CustomerName)
.Replace("{{Total}}", data.Total.ToString("C"));
// Convert to PDF
return _converter.ConvertHtml(html, "");
}
}
public class InvoiceGenerator
{
private readonly HtmlToPdfConverter _converter;
public InvoiceGenerator()
{
_converter = new HtmlToPdfConverter
{
LicenseKey = "your-license-key",
JavaScriptEnabled = false, // Not needed for static invoices
ConversionDelay = 0
};
// Configure for A4 invoices
_converter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4;
_converter.PdfDocumentOptions.TopMargin = 30;
_converter.PdfDocumentOptions.BottomMargin = 30;
}
public byte[] GenerateInvoice(InvoiceData data)
{
// Load HTML template
var template = File.ReadAllText("invoice-template.html");
// Simple string replacement for data
var html = template
.Replace("{{InvoiceNumber}}", data.InvoiceNumber)
.Replace("{{Date}}", data.Date.ToString("yyyy-MM-dd"))
.Replace("{{CustomerName}}", data.CustomerName)
.Replace("{{Total}}", data.Total.ToString("C"));
// Convert to PDF
return _converter.ConvertHtml(html, "");
}
}
Public Class InvoiceGenerator
Private ReadOnly _converter As HtmlToPdfConverter
Public Sub New()
_converter = New HtmlToPdfConverter With {
.LicenseKey = "your-license-key",
.JavaScriptEnabled = False,
.ConversionDelay = 0
}
' Configure for A4 invoices
_converter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4
_converter.PdfDocumentOptions.TopMargin = 30
_converter.PdfDocumentOptions.BottomMargin = 30
End Sub
Public Function GenerateInvoice(ByVal data As InvoiceData) As Byte()
' Load HTML template
Dim template = File.ReadAllText("invoice-template.html")
' Simple string replacement for data
Dim html = template.Replace("{{InvoiceNumber}}", data.InvoiceNumber).Replace("{{Date}}", data.Date.ToString("yyyy-MM-dd")).Replace("{{CustomerName}}", data.CustomerName).Replace("{{Total}}", data.Total.ToString("C"))
' Convert to PDF
Return _converter.ConvertHtml(html, "")
End Function
End Class
Advanced Implementation Patterns and Best Practices
Optimizing Performance in Production
Both libraries benefit from proper configuration and usage patterns:
IronPDF Performance Optimization
public class OptimizedPdfService
{
private readonly ChromePdfRenderer _renderer;
private readonly SemaphoreSlim _semaphore;
public OptimizedPdfService(int maxConcurrency = 4)
{
_semaphore = new SemaphoreSlim(maxConcurrency);
_renderer = new ChromePdfRenderer
{
RenderingOptions = new ChromePdfRenderOptions
{
// Optimize for performance
EnableJavaScript = false, // Only if not needed
RenderDelay = 0,
DPI = 150, // Balance quality vs speed
CssMediaType = PdfCssMediaType.Screen,
Timeout = 30,
// Memory optimization
OptimizeForLowMemory = true
}
};
// Enable connection pooling
Installation.ChromeGpuMode = ChromeGpuModes.Disabled;
Installation.LinuxAndDockerDependenciesAutoConfig = false;
}
public async Task<byte[]> GeneratePdfAsync(string html)
{
await _semaphore.WaitAsync();
try
{
var pdf = await _renderer.RenderHtmlAsPdfAsync(html);
// Optimize file size
pdf.CompressImages(85);
pdf.RemoveUnusedResources();
return pdf.BinaryData;
}
finally
{
_semaphore.Release();
}
}
}
public class OptimizedPdfService
{
private readonly ChromePdfRenderer _renderer;
private readonly SemaphoreSlim _semaphore;
public OptimizedPdfService(int maxConcurrency = 4)
{
_semaphore = new SemaphoreSlim(maxConcurrency);
_renderer = new ChromePdfRenderer
{
RenderingOptions = new ChromePdfRenderOptions
{
// Optimize for performance
EnableJavaScript = false, // Only if not needed
RenderDelay = 0,
DPI = 150, // Balance quality vs speed
CssMediaType = PdfCssMediaType.Screen,
Timeout = 30,
// Memory optimization
OptimizeForLowMemory = true
}
};
// Enable connection pooling
Installation.ChromeGpuMode = ChromeGpuModes.Disabled;
Installation.LinuxAndDockerDependenciesAutoConfig = false;
}
public async Task<byte[]> GeneratePdfAsync(string html)
{
await _semaphore.WaitAsync();
try
{
var pdf = await _renderer.RenderHtmlAsPdfAsync(html);
// Optimize file size
pdf.CompressImages(85);
pdf.RemoveUnusedResources();
return pdf.BinaryData;
}
finally
{
_semaphore.Release();
}
}
}
Public Class OptimizedPdfService
Private ReadOnly _renderer As ChromePdfRenderer
Private ReadOnly _semaphore As SemaphoreSlim
Public Sub New(Optional ByVal maxConcurrency As Integer = 4)
_semaphore = New SemaphoreSlim(maxConcurrency)
_renderer = New ChromePdfRenderer With {
.RenderingOptions = New ChromePdfRenderOptions With {
.EnableJavaScript = False,
.RenderDelay = 0,
.DPI = 150,
.CssMediaType = PdfCssMediaType.Screen,
.Timeout = 30,
.OptimizeForLowMemory = True
}
}
' Enable connection pooling
Installation.ChromeGpuMode = ChromeGpuModes.Disabled
Installation.LinuxAndDockerDependenciesAutoConfig = False
End Sub
Public Async Function GeneratePdfAsync(ByVal html As String) As Task(Of Byte())
Await _semaphore.WaitAsync()
Try
Dim pdf = Await _renderer.RenderHtmlAsPdfAsync(html)
' Optimize file size
pdf.CompressImages(85)
pdf.RemoveUnusedResources()
Return pdf.BinaryData
Finally
_semaphore.Release()
End Try
End Function
End Class
EvoPdf Performance Patterns
public class EvoPdfOptimizedService
{
private readonly ObjectPool<HtmlToPdfConverter> _converterPool;
public EvoPdfOptimizedService()
{
// Create object pool for converter reuse
_converterPool = new DefaultObjectPool<HtmlToPdfConverter>(
new ConverterPoolPolicy(),
Environment.ProcessorCount * 2);
}
public async Task<byte[]> GeneratePdfAsync(string html)
{
var converter = _converterPool.Get();
try
{
// Configure for speed
converter.ConversionDelay = 0;
converter.JavaScriptEnabled = false;
// Use async pattern
return await Task.Run(() => converter.ConvertHtml(html, ""));
}
finally
{
_converterPool.Return(converter);
}
}
private class ConverterPoolPolicy : IPooledObjectPolicy<HtmlToPdfConverter>
{
public HtmlToPdfConverter Create()
{
return new HtmlToPdfConverter
{
LicenseKey = "your-license-key"
};
}
public bool Return(HtmlToPdfConverter obj)
{
// Reset to default state
obj.ConversionDelay = 2;
return true;
}
}
}
public class EvoPdfOptimizedService
{
private readonly ObjectPool<HtmlToPdfConverter> _converterPool;
public EvoPdfOptimizedService()
{
// Create object pool for converter reuse
_converterPool = new DefaultObjectPool<HtmlToPdfConverter>(
new ConverterPoolPolicy(),
Environment.ProcessorCount * 2);
}
public async Task<byte[]> GeneratePdfAsync(string html)
{
var converter = _converterPool.Get();
try
{
// Configure for speed
converter.ConversionDelay = 0;
converter.JavaScriptEnabled = false;
// Use async pattern
return await Task.Run(() => converter.ConvertHtml(html, ""));
}
finally
{
_converterPool.Return(converter);
}
}
private class ConverterPoolPolicy : IPooledObjectPolicy<HtmlToPdfConverter>
{
public HtmlToPdfConverter Create()
{
return new HtmlToPdfConverter
{
LicenseKey = "your-license-key"
};
}
public bool Return(HtmlToPdfConverter obj)
{
// Reset to default state
obj.ConversionDelay = 2;
return true;
}
}
}
Public Class EvoPdfOptimizedService
Private ReadOnly _converterPool As ObjectPool(Of HtmlToPdfConverter)
Public Sub New()
' Create object pool for converter reuse
_converterPool = New DefaultObjectPool(Of HtmlToPdfConverter)(New ConverterPoolPolicy(), Environment.ProcessorCount * 2)
End Sub
Public Async Function GeneratePdfAsync(ByVal html As String) As Task(Of Byte())
Dim converter = _converterPool.Get()
Try
' Configure for speed
converter.ConversionDelay = 0
converter.JavaScriptEnabled = False
' Use async pattern
Return Await Task.Run(Function() converter.ConvertHtml(html, ""))
Finally
_converterPool.Return(converter)
End Try
End Function
Private Class ConverterPoolPolicy
Implements IPooledObjectPolicy(Of HtmlToPdfConverter)
Public Function Create() As HtmlToPdfConverter
Return New HtmlToPdfConverter With {.LicenseKey = "your-license-key"}
End Function
Public Function [Return](ByVal obj As HtmlToPdfConverter) As Boolean
' Reset to default state
obj.ConversionDelay = 2
Return True
End Function
End Class
End Class
Error Handling and Debugging
Robust error handling is crucial for production applications:
IronPDF Error Handling
public class RobustPdfGenerator
{
private readonly ILogger<RobustPdfGenerator> _logger;
private readonly ChromePdfRenderer _renderer;
public async Task<Result<byte[]>> TryGeneratePdfAsync(string html)
{
try
{
// Enable detailed logging
IronPdf.Logging.Logger.EnableDebugging = true;
IronPdf.Logging.Logger.LogFilePath = "ironpdf.log";
IronPdf.Logging.Logger.LoggingLevel = LoggingLevels.All;
var pdf = await _renderer.RenderHtmlAsPdfAsync(html);
// Validate output
if (pdf.PageCount == 0)
{
return Result<byte[]>.Failure("Generated PDF has no pages");
}
return Result<byte[]>.Success(pdf.BinaryData);
}
catch (IronPdf.Exceptions.IronPdfRenderException ex)
{
_logger.LogError(ex, "Rendering failed: {Message}", ex.Message);
// Attempt fallback with simpler settings
return await FallbackRender(html);
}
catch (Exception ex)
{
_logger.LogError(ex, "Unexpected error in PDF generation");
return Result<byte[]>.Failure($"PDF generation failed: {ex.Message}");
}
}
private async Task<Result<byte[]>> FallbackRender(string html)
{
var fallbackRenderer = new ChromePdfRenderer
{
RenderingOptions = new ChromePdfRenderOptions
{
EnableJavaScript = false,
DPI = 96,
Timeout = 60
}
};
try
{
var pdf = await fallbackRenderer.RenderHtmlAsPdfAsync(html);
return Result<byte[]>.Success(pdf.BinaryData);
}
catch (Exception ex)
{
return Result<byte[]>.Failure($"Fallback render failed: {ex.Message}");
}
}
}
public class RobustPdfGenerator
{
private readonly ILogger<RobustPdfGenerator> _logger;
private readonly ChromePdfRenderer _renderer;
public async Task<Result<byte[]>> TryGeneratePdfAsync(string html)
{
try
{
// Enable detailed logging
IronPdf.Logging.Logger.EnableDebugging = true;
IronPdf.Logging.Logger.LogFilePath = "ironpdf.log";
IronPdf.Logging.Logger.LoggingLevel = LoggingLevels.All;
var pdf = await _renderer.RenderHtmlAsPdfAsync(html);
// Validate output
if (pdf.PageCount == 0)
{
return Result<byte[]>.Failure("Generated PDF has no pages");
}
return Result<byte[]>.Success(pdf.BinaryData);
}
catch (IronPdf.Exceptions.IronPdfRenderException ex)
{
_logger.LogError(ex, "Rendering failed: {Message}", ex.Message);
// Attempt fallback with simpler settings
return await FallbackRender(html);
}
catch (Exception ex)
{
_logger.LogError(ex, "Unexpected error in PDF generation");
return Result<byte[]>.Failure($"PDF generation failed: {ex.Message}");
}
}
private async Task<Result<byte[]>> FallbackRender(string html)
{
var fallbackRenderer = new ChromePdfRenderer
{
RenderingOptions = new ChromePdfRenderOptions
{
EnableJavaScript = false,
DPI = 96,
Timeout = 60
}
};
try
{
var pdf = await fallbackRenderer.RenderHtmlAsPdfAsync(html);
return Result<byte[]>.Success(pdf.BinaryData);
}
catch (Exception ex)
{
return Result<byte[]>.Failure($"Fallback render failed: {ex.Message}");
}
}
}
Public Class RobustPdfGenerator
Private ReadOnly _logger As ILogger(Of RobustPdfGenerator)
Private ReadOnly _renderer As ChromePdfRenderer
Public Async Function TryGeneratePdfAsync(ByVal html As String) As Task(Of Result(Of Byte()))
Try
' Enable detailed logging
IronPdf.Logging.Logger.EnableDebugging = True
IronPdf.Logging.Logger.LogFilePath = "ironpdf.log"
IronPdf.Logging.Logger.LoggingLevel = LoggingLevels.All
Dim pdf = Await _renderer.RenderHtmlAsPdfAsync(html)
' Validate output
If pdf.PageCount = 0 Then
Return Result(Of Byte()).Failure("Generated PDF has no pages")
End If
Return Result(Of Byte()).Success(pdf.BinaryData)
Catch ex As IronPdf.Exceptions.IronPdfRenderException
_logger.LogError(ex, "Rendering failed: {Message}", ex.Message)
' Attempt fallback with simpler settings
Return Await FallbackRender(html)
Catch ex As Exception
_logger.LogError(ex, "Unexpected error in PDF generation")
Return Result(Of Byte()).Failure($"PDF generation failed: {ex.Message}")
End Try
End Function
Private Async Function FallbackRender(ByVal html As String) As Task(Of Result(Of Byte()))
Dim fallbackRenderer = New ChromePdfRenderer With {
.RenderingOptions = New ChromePdfRenderOptions With {
.EnableJavaScript = False,
.DPI = 96,
.Timeout = 60
}
}
Try
Dim pdf = Await fallbackRenderer.RenderHtmlAsPdfAsync(html)
Return Result(Of Byte()).Success(pdf.BinaryData)
Catch ex As Exception
Return Result(Of Byte()).Failure($"Fallback render failed: {ex.Message}")
End Try
End Function
End Class
Industry-Specific Implementation Examples
Financial Services: Regulatory Compliance
Financial institutions require specific features for compliance:
public class FinancialStatementGenerator
{
public async Task<byte[]> GenerateQuarterlyReport(FinancialData data)
{
var renderer = new ChromePdfRenderer();
// Generate report with charts and tables
var html = await BuildFinancialReportHtml(data);
var pdf = renderer.RenderHtmlAsPdf(html);
// Add compliance watermark
pdf.ApplyWatermark(@"
<div style='text-align: center; color: rgba(0,0,0,0.1); font-size: 120px;
transform: rotate(-45deg); font-family: Arial;'>
DRAFT
</div>", 30, VerticalAlignment.Middle, HorizontalAlignment.Center);
// Embed audit information
pdf.MetaData.Author = "Financial Reporting System";
pdf.MetaData.Keywords = "Quarterly Report, SOX Compliant";
pdf.MetaData.CustomProperties.Add("ReportPeriod", data.Quarter);
pdf.MetaData.CustomProperties.Add("GeneratedBy", Environment.UserName);
pdf.MetaData.CustomProperties.Add("Timestamp", DateTime.UtcNow.ToString("O"));
// Apply tamper-evident signature
var cert = new X509Certificate2("financial-cert.pfx", "password");
var signature = new PdfSignature(cert)
{
SigningReason = "Financial Report Certification",
SigningLocation = "Corporate Finance Department",
IsVisible = true,
SignatureImage = new PdfSignatureImage("cfo-signature.png")
};
pdf.Sign(signature);
// Lock document from editing
pdf.SecuritySettings = new SecuritySettings
{
AllowModifyDocument = false,
AllowCopy = true,
AllowPrint = true,
EncryptionLevel = EncryptionLevel.AES256Bit
};
return pdf.BinaryData;
}
}
public class FinancialStatementGenerator
{
public async Task<byte[]> GenerateQuarterlyReport(FinancialData data)
{
var renderer = new ChromePdfRenderer();
// Generate report with charts and tables
var html = await BuildFinancialReportHtml(data);
var pdf = renderer.RenderHtmlAsPdf(html);
// Add compliance watermark
pdf.ApplyWatermark(@"
<div style='text-align: center; color: rgba(0,0,0,0.1); font-size: 120px;
transform: rotate(-45deg); font-family: Arial;'>
DRAFT
</div>", 30, VerticalAlignment.Middle, HorizontalAlignment.Center);
// Embed audit information
pdf.MetaData.Author = "Financial Reporting System";
pdf.MetaData.Keywords = "Quarterly Report, SOX Compliant";
pdf.MetaData.CustomProperties.Add("ReportPeriod", data.Quarter);
pdf.MetaData.CustomProperties.Add("GeneratedBy", Environment.UserName);
pdf.MetaData.CustomProperties.Add("Timestamp", DateTime.UtcNow.ToString("O"));
// Apply tamper-evident signature
var cert = new X509Certificate2("financial-cert.pfx", "password");
var signature = new PdfSignature(cert)
{
SigningReason = "Financial Report Certification",
SigningLocation = "Corporate Finance Department",
IsVisible = true,
SignatureImage = new PdfSignatureImage("cfo-signature.png")
};
pdf.Sign(signature);
// Lock document from editing
pdf.SecuritySettings = new SecuritySettings
{
AllowModifyDocument = false,
AllowCopy = true,
AllowPrint = true,
EncryptionLevel = EncryptionLevel.AES256Bit
};
return pdf.BinaryData;
}
}
Public Class FinancialStatementGenerator
Public Async Function GenerateQuarterlyReport(ByVal data As FinancialData) As Task(Of Byte())
Dim renderer = New ChromePdfRenderer()
' Generate report with charts and tables
Dim html = Await BuildFinancialReportHtml(data)
Dim pdf = renderer.RenderHtmlAsPdf(html)
' Add compliance watermark
pdf.ApplyWatermark("
<div style='text-align: center; color: rgba(0,0,0,0.1); font-size: 120px;
transform: rotate(-45deg); font-family: Arial;'>
DRAFT
</div>", 30, VerticalAlignment.Middle, HorizontalAlignment.Center)
' Embed audit information
pdf.MetaData.Author = "Financial Reporting System"
pdf.MetaData.Keywords = "Quarterly Report, SOX Compliant"
pdf.MetaData.CustomProperties.Add("ReportPeriod", data.Quarter)
pdf.MetaData.CustomProperties.Add("GeneratedBy", Environment.UserName)
pdf.MetaData.CustomProperties.Add("Timestamp", DateTime.UtcNow.ToString("O"))
' Apply tamper-evident signature
Dim cert = New X509Certificate2("financial-cert.pfx", "password")
Dim signature = New PdfSignature(cert) With {
.SigningReason = "Financial Report Certification",
.SigningLocation = "Corporate Finance Department",
.IsVisible = True,
.SignatureImage = New PdfSignatureImage("cfo-signature.png")
}
pdf.Sign(signature)
' Lock document from editing
pdf.SecuritySettings = New SecuritySettings With {
.AllowModifyDocument = False,
.AllowCopy = True,
.AllowPrint = True,
.EncryptionLevel = EncryptionLevel.AES256Bit
}
Return pdf.BinaryData
End Function
End Class
E-Commerce: Dynamic Invoice Generation
E-commerce platforms need fast, reliable invoice generation:
public class EcommerceInvoiceService
{
private readonly ChromePdfRenderer _renderer;
public EcommerceInvoiceService()
{
_renderer = new ChromePdfRenderer
{
RenderingOptions = new ChromePdfRenderOptions
{
MarginTop = 10,
MarginBottom = 10,
PaperSize = PdfPaperSize.A4,
DPI = 200 // High quality for barcodes
}
};
}
public async Task<byte[]> GenerateInvoice(Order order)
{
// Build invoice HTML with order details
var html = $@"
<html>
<head>
<style>
@page {{ size: A4; margin: 0; }}
body {{ font-family: Arial, sans-serif; }}
.invoice-header {{ background: #f0f0f0; padding: 20px; }}
.barcode {{ text-align: center; margin: 20px 0; }}
table {{ width: 100%; border-collapse: collapse; }}
th, td {{ padding: 10px; border-bottom: 1px solid #ddd; }}
</style>
</head>
<body>
<div class='invoice-header'>
<h1>Invoice #{order.InvoiceNumber}</h1>
<p>Date: {order.Date:yyyy-MM-dd}</p>
</div>
<div class='barcode'>
<img src='data:image/png;base64,{GenerateBarcode(order.InvoiceNumber)}' />
</div>
<table>
<tr>
<th>Item</th>
<th>Quantity</th>
<th>Price</th>
<th>Total</th>
</tr>
{string.Join("", order.Items.Select(item => $@"
<tr>
<td>{item.Name}</td>
<td>{item.Quantity}</td>
<td>${item.Price:F2}</td>
<td>${item.Total:F2}</td>
</tr>"))}
<tr>
<td colspan='3'><strong>Total</strong></td>
<td><strong>${order.Total:F2}</strong></td>
</tr>
</table>
<div class='footer'>
<p>Thank you for your business!</p>
<p>Return policy and terms at: www.example.com/terms</p>
</div>
</body>
</html>";
var pdf = await _renderer.RenderHtmlAsPdfAsync(html);
// Add QR code for mobile payment verification
var qrStamper = new ImageStamper($"https://api.qrserver.com/v1/create-qr-code/?data={order.PaymentId}")
{
HorizontalAlignment = HorizontalAlignment.Right,
VerticalAlignment = VerticalAlignment.Bottom,
Width = 100,
Height = 100
};
pdf.ApplyStamp(qrStamper);
return pdf.BinaryData;
}
}
public class EcommerceInvoiceService
{
private readonly ChromePdfRenderer _renderer;
public EcommerceInvoiceService()
{
_renderer = new ChromePdfRenderer
{
RenderingOptions = new ChromePdfRenderOptions
{
MarginTop = 10,
MarginBottom = 10,
PaperSize = PdfPaperSize.A4,
DPI = 200 // High quality for barcodes
}
};
}
public async Task<byte[]> GenerateInvoice(Order order)
{
// Build invoice HTML with order details
var html = $@"
<html>
<head>
<style>
@page {{ size: A4; margin: 0; }}
body {{ font-family: Arial, sans-serif; }}
.invoice-header {{ background: #f0f0f0; padding: 20px; }}
.barcode {{ text-align: center; margin: 20px 0; }}
table {{ width: 100%; border-collapse: collapse; }}
th, td {{ padding: 10px; border-bottom: 1px solid #ddd; }}
</style>
</head>
<body>
<div class='invoice-header'>
<h1>Invoice #{order.InvoiceNumber}</h1>
<p>Date: {order.Date:yyyy-MM-dd}</p>
</div>
<div class='barcode'>
<img src='data:image/png;base64,{GenerateBarcode(order.InvoiceNumber)}' />
</div>
<table>
<tr>
<th>Item</th>
<th>Quantity</th>
<th>Price</th>
<th>Total</th>
</tr>
{string.Join("", order.Items.Select(item => $@"
<tr>
<td>{item.Name}</td>
<td>{item.Quantity}</td>
<td>${item.Price:F2}</td>
<td>${item.Total:F2}</td>
</tr>"))}
<tr>
<td colspan='3'><strong>Total</strong></td>
<td><strong>${order.Total:F2}</strong></td>
</tr>
</table>
<div class='footer'>
<p>Thank you for your business!</p>
<p>Return policy and terms at: www.example.com/terms</p>
</div>
</body>
</html>";
var pdf = await _renderer.RenderHtmlAsPdfAsync(html);
// Add QR code for mobile payment verification
var qrStamper = new ImageStamper($"https://api.qrserver.com/v1/create-qr-code/?data={order.PaymentId}")
{
HorizontalAlignment = HorizontalAlignment.Right,
VerticalAlignment = VerticalAlignment.Bottom,
Width = 100,
Height = 100
};
pdf.ApplyStamp(qrStamper);
return pdf.BinaryData;
}
}
Public Class EcommerceInvoiceService
Private ReadOnly _renderer As ChromePdfRenderer
Public Sub New()
_renderer = New ChromePdfRenderer With {
.RenderingOptions = New ChromePdfRenderOptions With {
.MarginTop = 10,
.MarginBottom = 10,
.PaperSize = PdfPaperSize.A4,
.DPI = 200
}
}
End Sub
Public Async Function GenerateInvoice(ByVal order As Order) As Task(Of Byte())
' Build invoice HTML with order details
, order.InvoiceNumbstring.Format(r, order.Date, GenerateBarcode(order.InvoiceNumber), String.Join(TangibleTempVerbatimDoubleQuote, order.Items.Select(Function(item) $TangibleTempVerbatimCloseTag"ignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignore<tr><td>{item.Name}</td><td>{item.Quantity}</td><td>${item.Price:F2}</td><td>${item.Total:F2}</td></tr>")), TangibleStringInterpolationMarker) var html = $"TangibleTempVerbatimOpenTagTangibleTempVerbatimStringLiteralLineJoin <html>TangibleTempVerbatimStringLiteralLineJoin <head>TangibleTempVerbatimStringLiteralLineJoin <style>TangibleTempVerbatimStringLiteralLineJoin @page {{ size: A4; margin: 0; }}TangibleTempVerbatimStringLiteralLineJoin body {{ font-family: Arial, sans-serif; }}TangibleTempVerbatimStringLiteralLineJoin .invoice-header {{ background: #f0f0f0; padding: 20px; }}TangibleTempVerbatimStringLiteralLineJoin .barcode {{ text-align: center; margin: 20px 0; }}TangibleTempVerbatimStringLiteralLineJoin table {{ width: 100%; border-collapse: collapse; }}TangibleTempVerbatimStringLiteralLineJoin th, td {{ padding: 10px; border-bottom: 1px solid #ddd; }}TangibleTempVerbatimStringLiteralLineJoin </style>TangibleTempVerbatimStringLiteralLineJoin </head>TangibleTempVerbatimStringLiteralLineJoin <body>TangibleTempVerbatimStringLiteralLineJoin <div class='invoice-header'>TangibleTempVerbatimStringLiteralLineJoin <h1>Invoice #{0}</h1>TangibleTempVerbatimStringLiteralLineJoin <p>Date: {1:yyyy-MM-dd}</p>TangibleTempVerbatimStringLiteralLineJoin </div>TangibleTempVerbatimStringLiteralLineJoinTangibleTempVerbatimStringLiteralLineJoin <div class='barcode'>TangibleTempVerbatimStringLiteralLineJoin <img src='data:image/png;base64,{2}' />TangibleTempVerbatimStringLiteralLineJoin </div>TangibleTempVerbatimStringLiteralLineJoinTangibleTempVerbatimStringLiteralLineJoin <table>TangibleTempVerbatimStringLiteralLineJoin <tr>TangibleTempVerbatimStringLiteralLineJoin <th>Item</th>TangibleTempVerbatimStringLiteralLineJoin <th>Quantity</th>TangibleTempVerbatimStringLiteralLineJoin <th>Price</th>TangibleTempVerbatimStringLiteralLineJoin <th>Total</th>TangibleTempVerbatimStringLiteralLineJoin </tr>TangibleTempVerbatimStringLiteralLineJoin {3}ignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignoreignore<tr><td colspan='3'><strong>Total</strong></td><td><strong>${order.Total:F2}</strong></td></tr></table><div class='footer'><p>Thank you for your business!</p><p>Return policy and terms at: www.example.com/terms</p></div></body></html>"
Dim pdf = Await _renderer.RenderHtmlAsPdfAsync(html)
' Add QR code for mobile payment verification
Dim qrStamper = New ImageStamper($"https://api.qrserver.com/v1/create-qr-code/?data={order.PaymentId}") With {
.HorizontalAlignment = HorizontalAlignment.Right,
.VerticalAlignment = VerticalAlignment.Bottom,
.Width = 100,
.Height = 100
}
pdf.ApplyStamp(qrStamper)
Return pdf.BinaryData
End Function
End Class
Migration Strategies: Moving Between Libraries
If you're considering switching between libraries, here's a migration approach:
Migrating from EvoPdf to IronPDF
// EvoPdf pattern
HtmlToPdfConverter evoPdfConverter = new HtmlToPdfConverter();
evoPdfConverter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4;
byte[] pdfBytes = evoPdfConverter.ConvertUrl(url);
// Equivalent IronPDF pattern
var ironPdfRenderer = new ChromePdfRenderer
{
RenderingOptions = new ChromePdfRenderOptions
{
PaperSize = PdfPaperSize.A4
}
};
var pdf = ironPdfRenderer.RenderUrlAsPdf(url);
byte[] pdfBytes = pdf.BinaryData;
// Migration wrapper for gradual transition
public interface IPdfConverter
{
byte[] ConvertHtmlToPdf(string html);
byte[] ConvertUrlToPdf(string url);
}
public class IronPdfAdapter : IPdfConverter
{
private readonly ChromePdfRenderer _renderer = new ChromePdfRenderer();
public byte[] ConvertHtmlToPdf(string html)
{
return _renderer.RenderHtmlAsPdf(html).BinaryData;
}
public byte[] ConvertUrlToPdf(string url)
{
return _renderer.RenderUrlAsPdf(url).BinaryData;
}
}
public class EvoPdfAdapter : IPdfConverter
{
private readonly HtmlToPdfConverter _converter = new HtmlToPdfConverter();
public byte[] ConvertHtmlToPdf(string html)
{
return _converter.ConvertHtml(html, "");
}
public byte[] ConvertUrlToPdf(string url)
{
return _converter.ConvertUrl(url);
}
}
// EvoPdf pattern
HtmlToPdfConverter evoPdfConverter = new HtmlToPdfConverter();
evoPdfConverter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4;
byte[] pdfBytes = evoPdfConverter.ConvertUrl(url);
// Equivalent IronPDF pattern
var ironPdfRenderer = new ChromePdfRenderer
{
RenderingOptions = new ChromePdfRenderOptions
{
PaperSize = PdfPaperSize.A4
}
};
var pdf = ironPdfRenderer.RenderUrlAsPdf(url);
byte[] pdfBytes = pdf.BinaryData;
// Migration wrapper for gradual transition
public interface IPdfConverter
{
byte[] ConvertHtmlToPdf(string html);
byte[] ConvertUrlToPdf(string url);
}
public class IronPdfAdapter : IPdfConverter
{
private readonly ChromePdfRenderer _renderer = new ChromePdfRenderer();
public byte[] ConvertHtmlToPdf(string html)
{
return _renderer.RenderHtmlAsPdf(html).BinaryData;
}
public byte[] ConvertUrlToPdf(string url)
{
return _renderer.RenderUrlAsPdf(url).BinaryData;
}
}
public class EvoPdfAdapter : IPdfConverter
{
private readonly HtmlToPdfConverter _converter = new HtmlToPdfConverter();
public byte[] ConvertHtmlToPdf(string html)
{
return _converter.ConvertHtml(html, "");
}
public byte[] ConvertUrlToPdf(string url)
{
return _converter.ConvertUrl(url);
}
}
' EvoPdf pattern
Dim evoPdfConverter As New HtmlToPdfConverter()
evoPdfConverter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4
Dim pdfBytes() As Byte = evoPdfConverter.ConvertUrl(url)
' Equivalent IronPDF pattern
Dim ironPdfRenderer = New ChromePdfRenderer With {
.RenderingOptions = New ChromePdfRenderOptions With {.PaperSize = PdfPaperSize.A4}
}
Dim pdf = ironPdfRenderer.RenderUrlAsPdf(url)
Dim pdfBytes() As Byte = pdf.BinaryData
' Migration wrapper for gradual transition
'INSTANT VB TODO TASK: Local functions are not converted by Instant VB:
'public interface IPdfConverter
'{
' byte[] ConvertHtmlToPdf(string html);
' byte[] ConvertUrlToPdf(string url);
'}
'INSTANT VB TODO TASK: Local functions are not converted by Instant VB:
'public class IronPdfAdapter : IPdfConverter
'{
' private readonly ChromePdfRenderer _renderer = New ChromePdfRenderer();
'
' public byte[] ConvertHtmlToPdf(string html)
' {
' Return _renderer.RenderHtmlAsPdf(html).BinaryData;
' }
'
' public byte[] ConvertUrlToPdf(string url)
' {
' Return _renderer.RenderUrlAsPdf(url).BinaryData;
' }
'}
'INSTANT VB TODO TASK: Local functions are not converted by Instant VB:
'public class EvoPdfAdapter : IPdfConverter
'{
' private readonly HtmlToPdfConverter _converter = New HtmlToPdfConverter();
'
' public byte[] ConvertHtmlToPdf(string html)
' {
' Return _converter.ConvertHtml(html, "");
' }
'
' public byte[] ConvertUrlToPdf(string url)
' {
' Return _converter.ConvertUrl(url);
' }
'}
Conclusion: Making the Right Choice for Your Project
Both IronPDF and EvoPdf serve important roles in the .NET PDF library ecosystem, but they target different use cases and development philosophies.
Choose IronPDF when you need:
- Modern web standard support (CSS3, JavaScript frameworks)
- Comprehensive PDF manipulation beyond just generation
- Enterprise security features and compliance tools
- Cross-platform deployment flexibility
- Extensive documentation and direct engineering support
- Integration with other document processing tools
Choose EvoPdf when you need:
- Simple HTML to PDF conversion at lower cost
- Basic PDF generation for straightforward documents
- Unlimited developer licenses for large teams
- Faster processing of simple HTML content
- Windows-centric deployment environment
The decision ultimately depends on your specific requirements, budget constraints, and long-term scalability needs. For most modern applications requiring robust PDF capabilities, IronPDF's comprehensive feature set and superior rendering engine justify the investment. However, EvoPdf remains a viable option for simpler use cases where cost is the primary concern.
Consider starting with the 30-day free trial of IronPDF to evaluate its capabilities in your specific use case. The trial includes all features without limitations, allowing you to make an informed decision based on actual performance in your environment.
Remember that the true cost of a PDF library extends beyond the license price—factor in development time, maintenance overhead, and the potential need for additional features as your application grows. Choose the library that not only meets your current needs but can scale with your future requirements.
Please note
Frequently Asked Questions
What are the key differences in HTML to PDF rendering between the two libraries?
IronPDF uses a full Chrome V8 rendering engine providing 98%+ browser fidelity with complete CSS3, HTML5, and JavaScript support. It handles modern frameworks like React and Angular seamlessly. EvoPdf uses a custom rendering engine with good support for standard HTML and CSS, achieving about 90% coverage of modern web standards. For complex JavaScript-heavy pages, IronPDF delivers more reliable results, while EvoPdf processes simple HTML documents 30-40% faster.
How do the libraries compare for PDF security and encryption?
Both libraries support AES-256 encryption, but IronPDF offers more comprehensive security features. IronPDF provides 15+ granular permission settings, visual digital signatures with custom images and timestamps, and integrated certificate management. EvoPdf offers 8 standard permissions and basic digital signature support. IronPDF's SecuritySettings
class provides a unified API for all security configurations, while EvoPdf requires separate configuration steps.
Which library is better for cross-platform deployment?
IronPDF offers superior cross-platform support with native compatibility for Windows, Linux, macOS, and Docker containers without additional configuration. It includes all dependencies in the NuGet package, enabling zero-configuration deployment. EvoPdf supports multiple platforms but requires platform-specific setup, particularly when moving between Windows and Linux environments. For cloud deployments on Azure or AWS, IronPDF provides optimized configurations.
What are the performance differences for batch PDF processing?
For simple HTML documents, EvoPdf completes conversions in 0.8-1.2 seconds compared to IronPDF's 1.2-1.8 seconds. However, IronPDF excels in parallel processing with native async/await optimization and better memory management for large batches. When processing 1000+ page documents, IronPDF performs 30% faster. IronPDF also handles memory more efficiently with automatic garbage collection, while EvoPdf maintains a lower baseline memory footprint.
How do licensing costs compare for different team sizes?
EvoPdf offers lower entry costs with its Deployment License at $450 versus IronPDF's Lite License at $749. For teams, EvoPdf's Company License at $1,200 covers unlimited developers, while IronPDF's Professional License at $2,999 covers 10 developers. However, IronPDF includes features like DOCX to PDF conversion built-in, while EvoPdf requires additional purchases. The Iron Suite at $1,498 provides exceptional value with 9 products including IronOCR and IronBarcode.
Can both libraries handle PDF redaction for compliance requirements?
IronPDF includes comprehensive redaction capabilities with true content removal using the RedactTextOnAllPages()
method. It supports regex patterns for SSNs and credit cards, selective page redaction, and OCR-based redaction for scanned documents. EvoPdf does not include built-in redaction functionality, which can be a significant limitation for applications requiring GDPR, HIPAA, or other privacy compliance.
What support and documentation options are available?
IronPDF provides 24/5 engineering support with direct access to developers, comprehensive API documentation, 100+ code examples, video tutorials, and migration guides. Response times typically range from 24-48 hours with priority support for Professional licenses. EvoPdf includes standard support for the first year with email and phone options, API documentation, and a support forum. IronPDF's extensive learning resources significantly reduce development time.
How do the libraries handle complex JavaScript and modern web features?
IronPDF's Chrome V8 engine fully executes JavaScript including frameworks like Chart.js, D3.js, and React components. It supports dynamic content rendering with configurable delays using RenderDelay
. The library handles Google Fonts, CSS animations, and responsive designs. EvoPdf provides good JavaScript support but may struggle with complex frameworks or dynamic chart generation, making it better suited for static or server-rendered content.
Which library is better for converting DOCX files to PDF?
IronPDF includes built-in DOCX to PDF conversion through its DocxToPdfRenderer
class at no additional cost. Simply use renderer.RenderDocxAsPdf()
to convert Word documents while preserving formatting. EvoPdf requires purchasing the separate Evo Word to PDF converter tool, adding $450+ to the total cost. This makes IronPDF more cost-effective for applications needing multiple format conversions.
What are the best use cases for each library?
IronPDF excels in modern web applications, compliance-heavy industries (healthcare, finance), complex document processing, and cross-platform deployments. It's ideal for SaaS platforms, e-commerce sites generating dynamic invoices, and applications requiring digital signatures or redaction. EvoPdf suits simple HTML to PDF conversion, static report generation, budget-conscious teams with many developers, and Windows-centric deployments where advanced features aren't required.