MarkdownToPdf.NET 2.1.0

dotnet add package MarkdownToPdf.NET --version 2.1.0
                    
NuGet\Install-Package MarkdownToPdf.NET -Version 2.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="MarkdownToPdf.NET" Version="2.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="MarkdownToPdf.NET" Version="2.1.0" />
                    
Directory.Packages.props
<PackageReference Include="MarkdownToPdf.NET" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add MarkdownToPdf.NET --version 2.1.0
                    
#r "nuget: MarkdownToPdf.NET, 2.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package MarkdownToPdf.NET@2.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=MarkdownToPdf.NET&version=2.1.0
                    
Install as a Cake Addin
#tool nuget:?package=MarkdownToPdf.NET&version=2.1.0
                    
Install as a Cake Tool

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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.1.0 93 8/17/2025
2.0.1 120 8/14/2025
2.0.0 115 8/13/2025
1.4.0 179 8/8/2025
1.3.2 210 8/6/2025
1.3.1 91 8/1/2025
1.3.0 113 7/31/2025
1.2.1 118 7/30/2025
1.2.0 96 7/29/2025
1.1.0 97 7/28/2025
1.0.1 95 7/18/2025