ASP.NET Core  

PDF Generation in ASP.NET Core MVC using Puppeteer Sharp

Introduction

In today’s digital era, online activities are an integral part of our daily lives. This is driving the increasing need for web-based applications. A frequent requirement of these web-based applications is the ability to generate PDFs from HTML. Everyday use cases include online ticketing, certificates, invoices for online purchases, and many more.

While libraries like iTextSharp or DinkToPdf can convert HTML to PDF, they often struggle with modern CSS and JavaScript rendering. This is where Puppeteer Sharp shines.

Puppeteer Sharp provides browser-quality PDFs, supports dynamic content, and integrates seamlessly into .NET apps, making it a significant improvement over traditional PDF generation libraries for web content.

Puppeteer Sharp is a .NET port of Google’s Puppeteer, a Node.js library for controlling Chrome or Chromium. It allows developers to.

  1. Render HTML just like a browser would.
  2. Apply advanced CSS styling.
  3. Run JavaScript before capturing.
  4. Export the rendered page to a PDF.

Benefits of using Puppeteer Sharp

  1. Accurate Rendering: It uses the Chromium browser engine to maintain the accuracy of rendering.
  2. Modern CSS and JavaScript Support: It can handle dynamic pages and animations.
  3. Custom Layouts: Paper sizes, margins, headers and footers can be customized.
  4. Automation Ready: It can be used in background tasks.

Installing Puppeteer Sharp

  1. Using Visual Studio (NuGet Package Manager UI)
    1. Right-click on your project in Solution Explorer.
    2. Select Manage NuGet Packages for Solution.
    3. Go to the Browse tab.
    4. Search for PuppeteerSharp.
    5. Select the latest stable version.
    6. Click Install.
  2. Using Package Manager Console: Open Tools > NuGet Package Manager > Package Manager Console, then run.
    Install-Package PuppeteerSharp
    
  3. Using .NET CLI: If you prefer the terminal/command line, run.
    dotnet add package PuppeteerSharp

Generating a PDF from a Web page

  1. Generate Invoice Example.
    [HttpPost]
    [Route("generate-invoice-pdf")]
    public async Task<IActionResult> GenerateInvoicePdf()
    {
        // Downloads Chromium if it's not already available
        await new BrowserFetcher().DownloadAsync();
    
        // Launch headless Chromium
        await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true });
    
        // Open a new page
        await using var page = await browser.NewPageAsync();
    
        // Navigate to a URL (can also be a local MVC view)
        var url = $"{Request.Scheme}://{Request.Host}/pdf";
        await page.GoToAsync(url, WaitUntilNavigation.Networkidle0);
    
        // Generate PDF
        var pdfBytes = await page.PdfDataAsync(new PdfOptions
        {
            Format = PaperFormat.A4,
            PrintBackground = true,
            MarginOptions = new MarginOptions
            {
                Top = "20px",
                Bottom = "20px",
                Left = "20px",
                Right = "20px"
            }
        });
    
        // Close the browser
        await browser.CloseAsync();
    
        // Returns downloadable file
        var fileName = $"PDF_{DateTime.Now:yyyyMMdd_HHmm}.pdf";
        return File(pdfBytes, "application/pdf", fileName);
    }
  2. Generate an External Web Page as a PDF.
    [HttpPost]
    [Route("generate-html-pdf")]
    public async Task<IActionResult> GenerateHtmlPdf()
    {
        // Downloads Chromium if it's not already available
        await new BrowserFetcher().DownloadAsync();
    
        // Launch headless Chromium
        await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true });
    
        // Open a new page
        await using var page = await browser.NewPageAsync();
    
        // Navigate to a URL (can also be a local MVC view)
        var url = "https://www.google.com/";
        await page.GoToAsync(url, WaitUntilNavigation.Networkidle0);
    
        // Generate PDF
        var pdfBytes = await page.PdfDataAsync(new PdfOptions
        {
            Format = PaperFormat.A4,
            PrintBackground = true,
            MarginOptions = new MarginOptions
            {
                Top = "20px",
                Bottom = "20px",
                Left = "20px",
                Right = "20px"
            }
        });
    
        // Close the browser
        await browser.CloseAsync();
    
        // Returns downloadable file
        var fileName = $"PDF_{DateTime.Now:yyyyMMdd_HHmm}.pdf";
        return File(pdfBytes, "application/pdf", fileName);
    }
    
  3. Razor View.
    <h2>Generate PDF using Puppeteer Sharp</h2>
    
    <div style="display: flex; justify-content: space-between; align-items: center; width: 33%; margin: 50px auto 0 auto;">
        <form asp-controller="Pdf" asp-action="GenerateInvoicePdf" method="post" style="margin: 0;">
            <button type="submit" class="btn btn-primary">Download Invoice PDF</button>
        </form>
        <form asp-controller="Pdf" asp-action="GenerateHtmlPdf" method="post" style="margin: 0;">
            <button type="submit" class="btn btn-primary">Download Web PDF</button>
        </form>
    </div>
    

How does it work?

  1. First BrowserFetcher downloads a compatible chromium browser if needed.
  2. The LaunchAsync method starts a headless instance of Chromium
  3. NewPageAsync opens a new tab in Chromium. If Headless is set to false then you will see the browser's window with tab.
  4. GoToAsync navigates to the target URL
  5. PDFDataAsync captures the page as a PDF in memory.
  6. The PDF is returned as a downloadable file to the client

Additional Tips

For the first time the PDF generation is slow and it’s the common issue with Puppeteer Sharp. To solve this problem, pre-download Chromium. This way, you can avoid first-request delays.

// Pre-download Chromium at startup
var fetcher = new BrowserFetcher();
await fetcher.DownloadAsync();

Suppose you add the above lines of code to your Program.cs, Chromium is downloaded during the application initialization for the first time.

Conclusion

Puppeteer Sharp is one of the powerful tools for PDF generation with modern web compatibility. It brings the flexibility of Chromium automation into the .NET ecosystem. Whether you are adding a PDF export feature or generating screenshots for preview, Puppeteer Sharp is a robust choice in .NET. With just a few lines of code, you can easily automate complex HTML to PDF.

Note. Project source code can be downloaded from GitHub