MarkdownToPdf.NET
2.1.0
dotnet add package MarkdownToPdf.NET --version 2.1.0
NuGet\Install-Package MarkdownToPdf.NET -Version 2.1.0
<PackageReference Include="MarkdownToPdf.NET" Version="2.1.0" />
<PackageVersion Include="MarkdownToPdf.NET" Version="2.1.0" />
<PackageReference Include="MarkdownToPdf.NET" />
paket add MarkdownToPdf.NET --version 2.1.0
#r "nuget: MarkdownToPdf.NET, 2.1.0"
#:package MarkdownToPdf.NET@2.1.0
#addin nuget:?package=MarkdownToPdf.NET&version=2.1.0
#tool nuget:?package=MarkdownToPdf.NET&version=2.1.0
MarkdownToPdf.NET v2.0
A portable .NET library for converting Markdown, HTML, and plain text to PDF using embedded wkhtmltopdf. Windows-only, with no external dependencies required.
What's New in v2.0
- 🔄 Direct wkhtmltopdf execution - Uses wkhtmltopdf.exe directly for better control and performance
- 🪟 Windows-only focus - Optimized specifically for Windows environments
- 📦 Fully portable - All binaries embedded in the NuGet package
- 🔧 Async API - All operations are asynchronous with cancellation support
- 📊 Enhanced logging - Detailed step-by-step logging for debugging
- ⚡ Better error handling - Specific exception types with detailed error information
- 🎛️ More control options - Fine-grained control over PDF generation settings
Features
- ✅ Convert Markdown to PDF with full formatting support
- ✅ Convert HTML to PDF with CSS styling
- ✅ Convert plain text to PDF with proper paragraph formatting
- ✅ Fully portable - no external dependencies or installations required
- ✅ Windows-optimized - includes wkhtmltopdf.exe and wkhtmltox.dll
- ✅ Async/await support with cancellation tokens
- ✅ Comprehensive logging using Microsoft.Extensions.Logging
- ✅ Dependency injection support for ASP.NET applications
- ✅ Enhanced error handling with specific exception types
- ✅ Both file output and byte array output options
Installation
Install the package via NuGet Package Manager:
dotnet add package MarkdownToPdf.NET
Or via Package Manager Console:
Install-Package MarkdownToPdf.NET
Note: Version 2.0+ requires .NET 6.0 or later and Windows operating system.
Quick Start
Basic Usage
using PdfTools.Services;
using PdfTools.Models;
using Microsoft.Extensions.Logging;
// Create logger (or use DI)
using var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole());
var logger = loggerFactory.CreateLogger<PdfGenerator>();
// Create generator instance
var generator = new PdfGenerator(logger);
// Generate PDF from Markdown
string markdown = @"
# My Document
This is a **sample** document with *formatting*.
## Features
- Beautiful styling
- Easy to use
- Professional output
";
await generator.GeneratePdfFromMarkdownAsync(markdown, "output.pdf");
With Custom Options
var options = new PdfOptions
{
Title = "My Custom Document",
Author = "John Doe",
Subject = "Sample PDF Generation",
PageSize = "A4",
Orientation = "Portrait",
Margins = new PdfMargins
{
Top = 25,
Bottom = 25,
Left = 20,
Right = 20
},
UseEnhancedStyling = true,
CustomCss = @"
body { font-family: 'Arial'; }
h1 { color: #ff6b6b; }
"
};
await generator.GeneratePdfFromMarkdownAsync(markdown, "custom-output.pdf", options);
Generate to Byte Array
// Get PDF as byte array (useful for web applications)
var pdfBytes = await generator.GeneratePdfBytesFromMarkdownAsync(markdown, options);
// In ASP.NET Controller
return File(pdfBytes, "application/pdf", "document.pdf");
HTML and Text Conversion
// Convert HTML to PDF
string html = "<h1>Hello World</h1><p>This is HTML content.</p>";
await generator.GeneratePdfFromHtmlAsync(html, "html-output.pdf", options);
// Convert plain text to PDF
string text = "This is plain text that will be converted to a nicely formatted PDF.";
await generator.GeneratePdfFromTextAsync(text, "text-output.pdf", options);
ASP.NET Integration
Startup Configuration
using PdfTools.Extensions;
// In Program.cs
builder.Services.AddPdfToolsV2();
// Or with custom logging configuration
builder.Services.AddPdfToolsV2(logging =>
{
logging.AddConsole();
logging.SetMinimumLevel(LogLevel.Information);
});
Controller Usage
[ApiController]
[Route("api/[controller]")]
public class PdfController : ControllerBase
{
private readonly IPdfGenerator _pdfGenerator;
private readonly ILogger<PdfController> _logger;
public PdfController(IPdfGenerator pdfGenerator, ILogger<PdfController> logger)
{
_pdfGenerator = pdfGenerator;
_logger = logger;
}
[HttpPost("from-markdown")]
public async Task<IActionResult> GenerateFromMarkdown(
[FromBody] MarkdownRequest request,
CancellationToken cancellationToken)
{
try
{
var options = new PdfOptions
{
Title = request.Title,
Author = request.Author,
UseEnhancedStyling = true
};
var pdfBytes = await _pdfGenerator.GeneratePdfBytesFromMarkdownAsync(
request.Markdown, options, cancellationToken);
return File(pdfBytes, "application/pdf", "document.pdf");
}
catch (PdfGenerationException ex)
{
_logger.LogError(ex, "PDF generation failed");
return BadRequest($"PDF generation failed: {ex.Message}");
}
}
}
public class MarkdownRequest
{
public string Markdown { get; set; } = string.Empty;
public string? Title { get; set; }
public string? Author { get; set; }
}
Configuration Options
PdfOptions
public class PdfOptions
{
public string? Title { get; set; } // PDF metadata
public string? Author { get; set; } // PDF metadata
public string? Subject { get; set; } // PDF metadata
public string Orientation { get; set; } // "Portrait" or "Landscape"
public string PageSize { get; set; } // "A4", "Letter", "Legal", etc.
public string? CustomCss { get; set; } // Custom CSS styles
public PdfMargins Margins { get; set; } // Page margins
public bool UseEnhancedStyling { get; set; } // Use enhanced CSS
public int Dpi { get; set; } // Output DPI (default: 200)
public bool EnableJavaScript { get; set; } // Enable JS execution
public bool PrintBackground { get; set; } // Print background colors
public int TimeoutMs { get; set; } // Page load timeout
}
Error Handling
The library provides specific exception types:
try
{
await generator.GeneratePdfFromMarkdownAsync(markdown, outputPath);
}
catch (InvalidInputException ex)
{
// Handle invalid input parameters
Console.WriteLine($"Invalid input: {ex.Message}");
}
catch (PdfConversionException ex)
{
// Handle PDF conversion errors
Console.WriteLine($"Conversion failed: {ex.Message}");
Console.WriteLine($"wkhtmltopdf stderr: {ex.StandardError}");
Console.WriteLine($"Exit code: {ex.ExitCode}");
}
catch (WkhtmltopdfNotFoundException ex)
{
// Handle missing wkhtmltopdf binaries
Console.WriteLine($"Binary extraction failed: {ex.Message}");
}
catch (FileOperationException ex)
{
// Handle file I/O errors
Console.WriteLine($"File operation failed: {ex.Message}");
}
Logging
The library provides detailed logging at each step:
// Configure logging to see conversion details
using var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddConsole();
builder.SetMinimumLevel(LogLevel.Debug); // For detailed logs
});
var logger = loggerFactory.CreateLogger<PdfGenerator>();
var generator = new PdfGenerator(logger);
// Logs will show:
// - Conversion start/end times
// - Binary extraction process
// - wkhtmltopdf command arguments
// - PDF file size and generation time
// - Any errors with full details
Differences from v1.x
Feature | v1.x (DinkToPdf) | v2.0 (Direct wkhtmltopdf) |
---|---|---|
Platform Support | Windows, Linux, macOS | Windows only |
Dependencies | DinkToPdf wrapper | Direct executable |
API Style | Synchronous | Asynchronous |
Error Handling | Generic exceptions | Specific exception types |
Logging | Basic | Comprehensive step-by-step |
Package Size | ~15MB (multi-platform) | ~8MB (Windows-only) |
Performance | Good | Better (direct execution) |
Control | Limited | Full wkhtmltopdf options |
Requirements
- .NET 6.0 or later
- Windows operating system (x64)
- No additional installations required
License
MIT License - see LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net6.0
- Markdig (>= 0.37.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 7.0.0)
- Microsoft.Extensions.Logging (>= 7.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 7.0.1)
- System.Diagnostics.Process (>= 4.3.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.