Convert HTML to PDF in .NET Core: End-to-End Guide for URLs, Razor Views, Security & Docker

Generating high-fidelity PDFs directly from HTML is a routine requirement in modern .NET applications—reports, invoices, and tickets all need pixel-perfect output that matches the web UI. IronPDF streamlines this workflow by exposing a single C# API for rendering HTML, Razor views, and full websites into standards-compliant PDF documents. By the end of this guide a developer will be able to convert URLs, raw HTML, or MVC views in an ASP.NET Core project, and deploy the same code to Windows, Linux, Docker, or serverless environments.

TipsFor layout issues, IronPDF ships a headless-Chrome debugger that helps diagnose CSS, JavaScript, and media-query quirks before the PDF is rendered. Review the dedicated pixel-perfect HTML-to-PDF guide for deep-dive techniques.

Quick-Start Checklist

  1. InstallInstall-Package IronPdf
  2. Render a URLChromePdfRenderer.RenderUrlAsPdf()
  3. Render raw HTMLChromePdfRenderer.RenderHtmlAsPdf()
  4. Export a Razor viewChromePdfRenderer.RenderHtmlAsPdfAsync()
  5. Fine-tune output – leverage ChromePdfRenderer.RenderingOptions

What This Tutorial Covers

  • URL, HTML string, and Razor view conversion
  • Paper, margin, and media-type configuration
  • Cross-platform deployment (Windows, Linux, Docker)
  • Post-processing: merge, watermark, password-protect, and digitally sign PDFs
  • End-to-end sample: ticket-booking MVC app

Get Started with IronPDF

Start using IronPDF in your project today with a free trial.

First Step:
green arrow pointer


How do I install the PDF library in .NET Core?

Installing the library is a one-liner in any .NET 8 project and remains forward-compatible with .NET 9 preview and the upcoming .NET 10 release. Use NuGet’s Package Manager Console and the package manager will resolve every dependency automatically for Windows, Linux, Docker, and serverless targets.

PM> Install-Package IronPdf             # .NET 8 LTS and higher
PM> Install-Package IronPdf             # .NET 8 LTS and higher
SHELL

Please noteNeed CLI? The same command works with dotnet add package IronPdf inside your project folder.

Once installed, confirm everything is wired up by converting any public URL:

// Program.cs — .NET 8 LTS
using IronPdf;

var renderer = new ChromePdfRenderer();

// Render a live website to PDF
using PdfDocument pdf = renderer.RenderUrlAsPdf("https://example.com");

// Persist to disk
pdf.SaveAs("website-snapshot.pdf");
// Program.cs — .NET 8 LTS
using IronPdf;

var renderer = new ChromePdfRenderer();

// Render a live website to PDF
using PdfDocument pdf = renderer.RenderUrlAsPdf("https://example.com");

// Persist to disk
pdf.SaveAs("website-snapshot.pdf");
' Program.cs — .NET 8 LTS
Imports IronPdf

Private renderer = New ChromePdfRenderer()

' Render a live website to PDF
Private PdfDocument As using

' Persist to disk
pdf.SaveAs("website-snapshot.pdf")
$vbLabelText   $csharpLabel

How it works

  • ChromePdfRenderer spins up a sandboxed Chromium instance under the hood--no separate Chrome install is required.
  • RenderUrlAsPdf captures the fully rendered DOM, including JavaScript-driven content, CSS media queries, and fonts.
  • The resulting PdfDocument exposes helper methods for merging, password-protecting, or digitally signing the output--capabilities covered later in this tutorial.

For more detail on deployment nuances (Azure App Service, AWS Lambda, on-prem Linux), see the dedicated installation guide and the advanced NuGet setup pages. Internal CI/CD tips for Docker and K8s clusters are covered in Docker deployment best practices.


How can a .NET Core service convert a live website URL to PDF?

A single call to RenderUrlAsPdf is enough: pass any publicly reachable URL and IronPDF returns a fully rendered, standards-compliant PDF. The code below targets .NET 8 LTS and compiles unchanged on .NET 9 preview as well as the forthcoming .NET 10 release in 2025.

Step-by-step example

// Program.cs — .NET 8 LTS-compatible
using IronPdf;

// 1. Activate a license (or trial key)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";

// 2. Create a reusable renderer instance
var renderer = new ChromePdfRenderer
{
    RenderingOptions =
    {
        // Force A4 portrait output and apply @media print styles
        PaperSize    = PdfPaperSize.A4,
        CssMediaType = PdfCssMediaType.Print
    }
};

// 3. Convert Microsoft Docs home page to PDF
using PdfDocument pdf = renderer.RenderUrlAsPdf("https://learn.microsoft.com/");

// 4. Save the PDF or stream it from a Web API
pdf.SaveAs("docs-offline-copy.pdf");
// Program.cs — .NET 8 LTS-compatible
using IronPdf;

// 1. Activate a license (or trial key)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";

// 2. Create a reusable renderer instance
var renderer = new ChromePdfRenderer
{
    RenderingOptions =
    {
        // Force A4 portrait output and apply @media print styles
        PaperSize    = PdfPaperSize.A4,
        CssMediaType = PdfCssMediaType.Print
    }
};

// 3. Convert Microsoft Docs home page to PDF
using PdfDocument pdf = renderer.RenderUrlAsPdf("https://learn.microsoft.com/");

// 4. Save the PDF or stream it from a Web API
pdf.SaveAs("docs-offline-copy.pdf");
' Program.cs — .NET 8 LTS-compatible
Imports IronPdf

' 1. Activate a license (or trial key)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"

' 2. Create a reusable renderer instance
Dim renderer = New ChromePdfRenderer With {
	.RenderingOptions = {
		PaperSize = PdfPaperSize.A4,
		CssMediaType = PdfCssMediaType.Print
	}
}

' 3. Convert Microsoft Docs home page to PDF
Using pdf As PdfDocument = renderer.RenderUrlAsPdf("https://learn.microsoft.com/")
	
	' 4. Save the PDF or stream it from a Web API
	pdf.SaveAs("docs-offline-copy.pdf")
End Using
$vbLabelText   $csharpLabel

Why it works

  • ChromePdfRenderer spins up a sandboxed Chromium instance--no system Chrome dependency, keeping Docker images slim.
  • RenderUrlAsPdf waits for the DOM and JavaScript to finish before snapshotting, so single-page apps render correctly .
  • Setting CssMediaType to Print tells the engine to use print-specific rules, matching a browser's Print → Save as PDF output.
  • The resulting PdfDocument can be encrypted, digitally signed, merged, or rasterized--capabilities covered in later sections.

TipsPixel-perfect debugging: enable renderer.LoggingOptions.DebugMode = true and follow the headless-Chrome debug guide to inspect live DevTools during rendering.


How do I convert raw HTML into a PDF in .NET Core?

Passing an HTML string—or a Razor view’s rendered markup—to ChromePdfRenderer.RenderHtmlAsPdf instantly produces a standards-compliant PDF. The method spins up IronPDF’s embedded Chromium engine, so no external browser installation or WebView dependency is required. The same code shown below compiles on .NET 8 LTS today and remains forward-compatible with .NET 9 and the scheduled .NET 10 release in November 2025.

Example — generate a PDF from an HTML fragment

// Program.cs — compatible with .NET 8 and newer
using IronPdf;

// Sample HTML fragment (could also be read from a file, Razor view, or CMS)
const string html = """
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Quarterly Report</title>
  <style>
     body { font-family:'Segoe UI', sans-serif; margin:1.2rem; }
     header { margin-bottom:2rem; }
     h1 { color:#3056d3; }
     table { width:100%; border-collapse:collapse; margin-top:1rem; }
     th,td { border:1px solid #ddd; padding:0.5rem; text-align:right; }
     tr:nth-child(even){ background-color:#f8f9fa; }
  </style>
</head>
<body>
  <header><h1>Q2 Revenue Summary</h1></header>
  <table>
    <thead><tr><th>Product</th><th>Revenue ($)</th></tr></thead>
    <tbody>
      <tr><td>IronPDF for .NET</td><td>1,200,000</td></tr>
      <tr><td>IronOCR for .NET</td><td>890,000</td></tr>
      <tr><td>IronXL for .NET</td><td>610,000</td></tr>
    </tbody>
  </table>
</body>
</html>
""";

// 1. Create a renderer once and reuse it across conversions
var renderer = new ChromePdfRenderer
{
    RenderingOptions =
    {
        PaperSize    = PdfPaperSize.A4,                  // ISO-standard paper size
        PaperOrientation = PdfPaperOrientation.Portrait,
        CssMediaType = PdfCssMediaType.Screen,           // Respect on-screen CSS
        RenderDelay  = 100,                              // Wait 100 ms for JS/animations
        FallbackEncoding = "utf-8"                       // Handle non-ASCII correctly
    }
};

// 2. Render the HTML fragment
using PdfDocument pdf = renderer.RenderHtmlAsPdf(html);

// 3. Persist to disk or return via ASP.NET Core FileStreamResult
pdf.SaveAs("q2-report.pdf");
// Program.cs — compatible with .NET 8 and newer
using IronPdf;

// Sample HTML fragment (could also be read from a file, Razor view, or CMS)
const string html = """
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Quarterly Report</title>
  <style>
     body { font-family:'Segoe UI', sans-serif; margin:1.2rem; }
     header { margin-bottom:2rem; }
     h1 { color:#3056d3; }
     table { width:100%; border-collapse:collapse; margin-top:1rem; }
     th,td { border:1px solid #ddd; padding:0.5rem; text-align:right; }
     tr:nth-child(even){ background-color:#f8f9fa; }
  </style>
</head>
<body>
  <header><h1>Q2 Revenue Summary</h1></header>
  <table>
    <thead><tr><th>Product</th><th>Revenue ($)</th></tr></thead>
    <tbody>
      <tr><td>IronPDF for .NET</td><td>1,200,000</td></tr>
      <tr><td>IronOCR for .NET</td><td>890,000</td></tr>
      <tr><td>IronXL for .NET</td><td>610,000</td></tr>
    </tbody>
  </table>
</body>
</html>
""";

// 1. Create a renderer once and reuse it across conversions
var renderer = new ChromePdfRenderer
{
    RenderingOptions =
    {
        PaperSize    = PdfPaperSize.A4,                  // ISO-standard paper size
        PaperOrientation = PdfPaperOrientation.Portrait,
        CssMediaType = PdfCssMediaType.Screen,           // Respect on-screen CSS
        RenderDelay  = 100,                              // Wait 100 ms for JS/animations
        FallbackEncoding = "utf-8"                       // Handle non-ASCII correctly
    }
};

// 2. Render the HTML fragment
using PdfDocument pdf = renderer.RenderHtmlAsPdf(html);

// 3. Persist to disk or return via ASP.NET Core FileStreamResult
pdf.SaveAs("q2-report.pdf");
' Program.cs — compatible with .NET 8 and newer
Imports IronPdf

' Sample HTML fragment (could also be read from a file, Razor view, or CMS)
Private Const html As String = "<!DOCTYPE html>
<html lang=""en"">
<head>
  <meta charset=""utf-8"">
  <title>Quarterly Report</title>
  <style>
     body { font-family:'Segoe UI', sans-serif; margin:1.2rem; }
     header { margin-bottom:2rem; }
     h1 { color:#3056d3; }
     table { width:100%; border-collapse:collapse; margin-top:1rem; }
     th,td { border:1px solid #ddd; padding:0.5rem; text-align:right; }
     tr:nth-child(even){ background-color:#f8f9fa; }
  </style>
</head>
<body>
  <header><h1>Q2 Revenue Summary</h1></header>
  <table>
    <thead><tr><th>Product</th><th>Revenue ($)</th></tr></thead>
    <tbody>
      <tr><td>IronPDF for .NET</td><td>1,200,000</td></tr>
      <tr><td>IronOCR for .NET</td><td>890,000</td></tr>
      <tr><td>IronXL for .NET</td><td>610,000</td></tr>
    </tbody>
  </table>
</body>
</html>"

' 1. Create a renderer once and reuse it across conversions
Private renderer = New ChromePdfRenderer With {
	.RenderingOptions = {
		PaperSize = PdfPaperSize.A4,
		PaperOrientation = PdfPaperOrientation.Portrait,
		CssMediaType = PdfCssMediaType.Screen,
		RenderDelay = 100,
		FallbackEncoding = "utf-8"
	}
}

' 2. Render the HTML fragment
Private PdfDocument As using

' 3. Persist to disk or return via ASP.NET Core FileStreamResult
pdf.SaveAs("q2-report.pdf")
$vbLabelText   $csharpLabel

What the code demonstrates

  • Embedded Chromium -- IronPDF bundles the Chromium engine, guaranteeing HTML5, CSS3, and JavaScript parity with modern browsers.
  • Single dependency -- A lightweight NuGet install covers Windows, Linux, Docker, and Azure/AWS without extra system libraries.
  • Rendering options -- PaperSize, CssMediaType, and RenderDelay mirror browser print settings so PDFs match on-screen layouts.
  • Future-proof targeting -- The API surface is the same across .NET 8, .NET 9 STS, and the upcoming .NET 10, so long-term maintenance is minimal.
  • Post-processing hooks -- PdfDocument exposes helpers for merging, password protection, and digital signatures--each covered later in this guide.

Further reading: see the step-by-step HTML-string-to-PDF tutorial and the full ChromePdfRenderer API documentation.


How can an ASP .NET Core MVC view be exported to PDF?

IronPDF renders a fully-processed Razor view ( .cshtml ) the same way a browser would and streams the result as a PdfDocument. The workflow below keeps controller logic clean, requires no browser plugins, and works on .NET 8 LTS, .NET 9 preview, and the scheduled .NET 10 release in November 2025.

End-to-end controller example

// TicketsController.cs — .NET 8 LTS / MVC
using IronPdf;
using Microsoft.AspNetCore.Mvc;
using YourApp.Models;           // TicketViewModel

public class TicketsController : Controller
{
    private readonly ChromePdfRenderer _renderer;

    public TicketsController()
    {
        _renderer = new ChromePdfRenderer
        {
            RenderingOptions =
            {
                PaperSize        = PdfPaperSize.A5,            // Compact ticket size
                PaperOrientation = PdfPaperOrientation.Portrait,
                FitToPaperWidth  = true,
                CssMediaType     = PdfCssMediaType.Print,
                Margins = new PdfMargins(5, 10, 5, 10)         // mm
            }
        };
    }

    // GET /Tickets/Print/42
    public async Task<IActionResult> Print(int id)
    {
        TicketViewModel vm = await _service.GetTicketAsync(id);

        // 1. Render the Razor view to an HTML string
        string html  = await RazorTemplateEngine.RenderViewAsync(
                           HttpContext, "~/Views/Tickets/Print.cshtml", vm);

        // 2. Convert HTML → PDF
        using PdfDocument pdf = _renderer.RenderHtmlAsPdf(html);

        // 3. Stream back as a file
        return File(pdf.BinaryData, "application/pdf",
                    $"ticket-{id}.pdf");
    }
}
// TicketsController.cs — .NET 8 LTS / MVC
using IronPdf;
using Microsoft.AspNetCore.Mvc;
using YourApp.Models;           // TicketViewModel

public class TicketsController : Controller
{
    private readonly ChromePdfRenderer _renderer;

    public TicketsController()
    {
        _renderer = new ChromePdfRenderer
        {
            RenderingOptions =
            {
                PaperSize        = PdfPaperSize.A5,            // Compact ticket size
                PaperOrientation = PdfPaperOrientation.Portrait,
                FitToPaperWidth  = true,
                CssMediaType     = PdfCssMediaType.Print,
                Margins = new PdfMargins(5, 10, 5, 10)         // mm
            }
        };
    }

    // GET /Tickets/Print/42
    public async Task<IActionResult> Print(int id)
    {
        TicketViewModel vm = await _service.GetTicketAsync(id);

        // 1. Render the Razor view to an HTML string
        string html  = await RazorTemplateEngine.RenderViewAsync(
                           HttpContext, "~/Views/Tickets/Print.cshtml", vm);

        // 2. Convert HTML → PDF
        using PdfDocument pdf = _renderer.RenderHtmlAsPdf(html);

        // 3. Stream back as a file
        return File(pdf.BinaryData, "application/pdf",
                    $"ticket-{id}.pdf");
    }
}
' TicketsController.cs — .NET 8 LTS / MVC
Imports IronPdf
Imports Microsoft.AspNetCore.Mvc
Imports YourApp.Models ' TicketViewModel

Public Class TicketsController
	Inherits Controller

	Private ReadOnly _renderer As ChromePdfRenderer

	Public Sub New()
		_renderer = New ChromePdfRenderer With {
			.RenderingOptions = {
				PaperSize = PdfPaperSize.A5,
				PaperOrientation = PdfPaperOrientation.Portrait,
				FitToPaperWidth = True,
				CssMediaType = PdfCssMediaType.Print,
				Margins = New PdfMargins(5, 10, 5, 10)
			}
		}
	End Sub

	' GET /Tickets/Print/42
	Public Async Function Print(ByVal id As Integer) As Task(Of IActionResult)
		Dim vm As TicketViewModel = Await _service.GetTicketAsync(id)

		' 1. Render the Razor view to an HTML string
		Dim html As String = Await RazorTemplateEngine.RenderViewAsync(HttpContext, "~/Views/Tickets/Print.cshtml", vm)

		' 2. Convert HTML → PDF
		Using pdf As PdfDocument = _renderer.RenderHtmlAsPdf(html)
	
			' 3. Stream back as a file
			Return File(pdf.BinaryData, "application/pdf", $"ticket-{id}.pdf")
		End Using
	End Function
End Class
$vbLabelText   $csharpLabel

What this code illustrates

  • No temporary files -- the Razor view is rendered in-memory, then passed directly to RenderHtmlAsPdf, avoiding disk I/O and temp-folder race conditions.
  • Ticket-sized output -- PaperSize = A5 and narrow margins keep print-at-home tickets compact.
  • Consistent print styles -- CssMediaType = Print applies the same @media print CSS rules that browsers use.
  • Binary streaming -- pdf.BinaryData streams the document without touching the file-system; ideal for API endpoints and Lambda functions.
  • Re-usable renderer -- ChromePdfRenderer is instantiated once per controller, then reused, minimising process-spawn overhead.

PaperSize, PaperOrientation, FitToPaperWidth

Margins, Header, Footer, Watermark

Next step: add encryption, digital signatures, or merge multiple tickets into a single file. See the merge example and the digital-signature how-to.


How can I fine-tune paper size, margins, headers, watermarks, and security before rendering?

IronPDF exposes a single ChromePdfRenderOptions object that controls every aspect of the output—paper dimensions, orientation, headers & footers, JavaScript timing, watermarks, encryption, and digital signatures—all without extra browser plugins.

Code sample — apply multiple options at once

// AdvancedOptions.cs — .NET 8 compatible
using IronPdf;

var renderer = new ChromePdfRenderer();

// Configure everything in one place
renderer.RenderingOptions = new ChromePdfRenderOptions
{
    // 1. Page layout
    PaperSize        = PdfPaperSize.A4,                     // ISO size
    PaperOrientation = PdfPaperOrientation.Portrait,
    Margins          = new PdfMargins { Top = 20, Bottom = 25, Left = 15, Right = 15 }, // mm

    // 2. Timing & media
    CssMediaType     = PdfCssMediaType.Print,               // Respect @media print
    EnableJavaScript = true,
    RenderDelay      = 200,                                 // Wait 200 ms for animations

    // 3. Headers & footers (HTML gives full design freedom)
    HtmlHeader       = "<header style='font:14px Segoe UI'>Invoice — {{date}}</header>",
    HtmlFooter       = "<footer style='text-align:right;font-size:10px'>Page {{page}} / {{total-pages}}</footer>",

    // 4. Watermark
    Watermark        = new HtmlStamp
    {
        HtmlTemplate = "<div style='font-size:50px;color:#cccccc;opacity:0.3;'>CONFIDENTIAL</div>",
        VerticalAlignment = VerticalAlignment.Center,
        HorizontalAlignment = HorizontalAlignment.Center
    },

    // 5. Security
    SecurityOptions = new PdfSecurityOptions
    {
        OwnerPassword = "StrongOwnerPwd!",
        UserPassword  = "ReadOnly",
        AllowUserPrinting = false,
        AllowUserCopyPasteContent = false
    }
};

// Render any HTML
using PdfDocument pdf = renderer.RenderHtmlAsPdf("<h1>Advanced Options Demo</h1>");

// Digitally sign with a PFX certificate (optional)
pdf.SignAndStamp("./certs/company.pfx", "Iron Software", "Bangkok", "Approval");

// Save
pdf.SaveAs("advanced-options-demo.pdf");
// AdvancedOptions.cs — .NET 8 compatible
using IronPdf;

var renderer = new ChromePdfRenderer();

// Configure everything in one place
renderer.RenderingOptions = new ChromePdfRenderOptions
{
    // 1. Page layout
    PaperSize        = PdfPaperSize.A4,                     // ISO size
    PaperOrientation = PdfPaperOrientation.Portrait,
    Margins          = new PdfMargins { Top = 20, Bottom = 25, Left = 15, Right = 15 }, // mm

    // 2. Timing & media
    CssMediaType     = PdfCssMediaType.Print,               // Respect @media print
    EnableJavaScript = true,
    RenderDelay      = 200,                                 // Wait 200 ms for animations

    // 3. Headers & footers (HTML gives full design freedom)
    HtmlHeader       = "<header style='font:14px Segoe UI'>Invoice — {{date}}</header>",
    HtmlFooter       = "<footer style='text-align:right;font-size:10px'>Page {{page}} / {{total-pages}}</footer>",

    // 4. Watermark
    Watermark        = new HtmlStamp
    {
        HtmlTemplate = "<div style='font-size:50px;color:#cccccc;opacity:0.3;'>CONFIDENTIAL</div>",
        VerticalAlignment = VerticalAlignment.Center,
        HorizontalAlignment = HorizontalAlignment.Center
    },

    // 5. Security
    SecurityOptions = new PdfSecurityOptions
    {
        OwnerPassword = "StrongOwnerPwd!",
        UserPassword  = "ReadOnly",
        AllowUserPrinting = false,
        AllowUserCopyPasteContent = false
    }
};

// Render any HTML
using PdfDocument pdf = renderer.RenderHtmlAsPdf("<h1>Advanced Options Demo</h1>");

// Digitally sign with a PFX certificate (optional)
pdf.SignAndStamp("./certs/company.pfx", "Iron Software", "Bangkok", "Approval");

// Save
pdf.SaveAs("advanced-options-demo.pdf");
' AdvancedOptions.cs — .NET 8 compatible
Imports IronPdf

Private renderer = New ChromePdfRenderer()

' Configure everything in one place
renderer.RenderingOptions = New ChromePdfRenderOptions With {
	.PaperSize = PdfPaperSize.A4,
	.PaperOrientation = PdfPaperOrientation.Portrait,
	.Margins = New PdfMargins With {
		.Top = 20,
		.Bottom = 25,
		.Left = 15,
		.Right = 15
	},
	.CssMediaType = PdfCssMediaType.Print,
	.EnableJavaScript = True,
	.RenderDelay = 200,
	.HtmlHeader = "<header style='font:14px Segoe UI'>Invoice — {{date}}</header>",
	.HtmlFooter = "<footer style='text-align:right;font-size:10px'>Page {{page}} / {{total-pages}}</footer>",
	.Watermark = New HtmlStamp With {
		.HtmlTemplate = "<div style='font-size:50px;color:#cccccc;opacity:0.3;'>CONFIDENTIAL</div>",
		.VerticalAlignment = VerticalAlignment.Center,
		.HorizontalAlignment = HorizontalAlignment.Center
	},
	.SecurityOptions = New PdfSecurityOptions With {
		.OwnerPassword = "StrongOwnerPwd!",
		.UserPassword = "ReadOnly",
		.AllowUserPrinting = False,
		.AllowUserCopyPasteContent = False
	}
}

' Render any HTML
Using pdf As PdfDocument = renderer.RenderHtmlAsPdf("<h1>Advanced Options Demo</h1>")
	
	' Digitally sign with a PFX certificate (optional)
	pdf.SignAndStamp("./certs/company.pfx", "Iron Software", "Bangkok", "Approval")
	
	' Save
	pdf.SaveAs("advanced-options-demo.pdf")
End Using
$vbLabelText   $csharpLabel

Why these options matter

  • PaperSize, Margins, and CssMediaType mirror a browser's print dialog so on-screen layouts and the PDF remain identical on Windows, Linux, and Docker.
  • HTML headers and footers support Razor tokens, CSS, and JavaScript--handy for dynamic page numbers or branding.
  • HtmlStamp lets a single line create branded watermarks with full HTML + CSS control.
  • Security options enable 128-bit encryption, owner/user passwords, and granular permissions without third-party tools.
  • Digital signatures add a cryptographic seal directly in code, maintaining legal authenticity and tamper evidence.
  • Extraction helpers such as ExtractAllText and ExtractAllImages reverse the process when analysis is required.

PaperSize, PaperOrientation, Margins, CssMediaType, RenderDelay

HtmlHeader, HtmlFooter, dynamic Razor placeholders, page-number tokens

Watermark, HtmlStamp, opacity, alignment

SecurityOptions, SignAndStamp, owner / user passwords, 128-bit AES, certificate sealing

Next tasks: merge multiple PDFs, extract text & images, and deploy to Docker or serverless. Continue to the deployment section to ensure cross-platform parity.


How can I deploy PDF-generation code to Docker on Linux and Windows?

IronPDF ships as a single self-contained NuGet package, so containerizing an ASP.NET Core (or console) app is straightforward on both Windows and Linux. The key is to copy the published binaries into a slim runtime image and, on Linux, add the two native libraries IronPDF requires (libnss3 and libatk1.0-0).

Multi-stage Dockerfile (Ubuntu 22.04)

Please noteWhy multi-stage? The SDK image (stage 1) compiles the project; the final runtime image (stage 2) stays lean—< 120 MB—because build tools are discarded.

####### ---------- stage 1 ----------
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["MyPdfApp.csproj", "."]
RUN dotnet restore

COPY . .
RUN dotnet publish -c Release -o /app/publish

####### ---------- stage 2 ----------
FROM mcr.microsoft.com/dotnet/aspnet:8.0-jammy
######## Install two native libs required by Chromium
RUN apt-get update && \
    apt-get install -y --no-install-recommends libnss3 libatk1.0-0 && \
    rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "MyPdfApp.dll"]

Please noteWindows containers? Replace the second stage with mcr.microsoft.com/dotnet/aspnet:8.0-windowsservercore-ltsc2022—no additional packages are needed because Chromium DLLs are bundled.

End-to-end validation script

docker build -t pdf-demo .
docker run --rm -p 8080:80 pdf-demo
######### ↳ Navigate to http://localhost:8080/api/pdf?url=https://example.com
docker build -t pdf-demo .
docker run --rm -p 8080:80 pdf-demo
######### ↳ Navigate to http://localhost:8080/api/pdf?url=https://example.com
SHELL
  • The API action internally calls ChromePdfRenderer.RenderUrlAsPdf just like in Section2.
  • IronPDF spins up its sandboxed Chromium process inside the container—no X server is required because it renders headlessly.
  • Memory footprint stays under 200 MB even during large renders.

TipsTroubleshooting tip: If the container logs show a “libnss3.so not found” error, confirm both libnss3 and libatk1.0-0 are present. Alpine images are not supported because the musl C library lacks required symbols.

Internal resources


How can I open, merge, watermark, and extract content from existing PDFs in .NET Core?

IronPDF treats every PDF—whether generated by IronPDF, Adobe® Acrobat, or third-party tools—as a first-class PdfDocument object that can be opened, edited, secured, and re-saved without quality loss. The same API surface works on .NET 8 LTS today and compiles unchanged on the .NET 9 preview and the forthcoming .NET 10 release.

Unified sample — open → merge → watermark → extract

// ManipulateExistingPdf.cs — .NET 8 LTS compatible
using IronPdf;
using System.Linq;

// Step 1: Open two existing files (password-protected PDFs are supported)
PdfDocument invoice  = PdfDocument.FromFile("invoice.pdf", "ReadOnly");   // open with user pwd
PdfDocument tAndCs   = PdfDocument.FromFile("terms.pdf");                 // no pwd required

// Step 2: Merge them (invoice pages first, then T&Cs)
PdfDocument mergedPdf = PdfDocument.Merge(invoice, tAndCs);               // 1-liner merge

// Step 3: Apply a diagonal CONFIDENTIAL watermark to every page
mergedPdf.ApplyStamp(
    "<div style='font-size:60px;color:#d9534f;opacity:0.2;transform:rotate(-45deg);"
  + "width:100%;text-align:center;'>CONFIDENTIAL</div>",
    verticalAlignment   : VerticalAlignment.Center,
    horizontalAlignment : HorizontalAlignment.Center);

// Step 4: Extract all text and the first image for audit purposes
string fullText = mergedPdf.ExtractAllText();
var    image    = mergedPdf.ExtractAllImages().FirstOrDefault();

// Step 5: Save or stream
mergedPdf.SaveAs("invoice-with-terms.pdf");
// ManipulateExistingPdf.cs — .NET 8 LTS compatible
using IronPdf;
using System.Linq;

// Step 1: Open two existing files (password-protected PDFs are supported)
PdfDocument invoice  = PdfDocument.FromFile("invoice.pdf", "ReadOnly");   // open with user pwd
PdfDocument tAndCs   = PdfDocument.FromFile("terms.pdf");                 // no pwd required

// Step 2: Merge them (invoice pages first, then T&Cs)
PdfDocument mergedPdf = PdfDocument.Merge(invoice, tAndCs);               // 1-liner merge

// Step 3: Apply a diagonal CONFIDENTIAL watermark to every page
mergedPdf.ApplyStamp(
    "<div style='font-size:60px;color:#d9534f;opacity:0.2;transform:rotate(-45deg);"
  + "width:100%;text-align:center;'>CONFIDENTIAL</div>",
    verticalAlignment   : VerticalAlignment.Center,
    horizontalAlignment : HorizontalAlignment.Center);

// Step 4: Extract all text and the first image for audit purposes
string fullText = mergedPdf.ExtractAllText();
var    image    = mergedPdf.ExtractAllImages().FirstOrDefault();

// Step 5: Save or stream
mergedPdf.SaveAs("invoice-with-terms.pdf");
' ManipulateExistingPdf.cs — .NET 8 LTS compatible
Imports IronPdf
Imports System.Linq

' Step 1: Open two existing files (password-protected PDFs are supported)
Private invoice As PdfDocument = PdfDocument.FromFile("invoice.pdf", "ReadOnly") ' open with user pwd
Private tAndCs As PdfDocument = PdfDocument.FromFile("terms.pdf") ' no pwd required

' Step 2: Merge them (invoice pages first, then T&Cs)
Private mergedPdf As PdfDocument = PdfDocument.Merge(invoice, tAndCs) ' 1-liner merge

' Step 3: Apply a diagonal CONFIDENTIAL watermark to every page
mergedPdf.ApplyStamp("<div style='font-size:60px;color:#d9534f;opacity:0.2;transform:rotate(-45deg);" & "width:100%;text-align:center;'>CONFIDENTIAL</div>", verticalAlignment := VerticalAlignment.Center, horizontalAlignment := HorizontalAlignment.Center)

' Step 4: Extract all text and the first image for audit purposes
Dim fullText As String = mergedPdf.ExtractAllText()
Dim image = mergedPdf.ExtractAllImages().FirstOrDefault()

' Step 5: Save or stream
mergedPdf.SaveAs("invoice-with-terms.pdf")
$vbLabelText   $csharpLabel

Why this matters

  • Open & mergePdfDocument.FromFile loads any standards-compliant PDF, including encrypted files, while PdfDocument.Merge concatenates an arbitrary number of documents in a single call.
  • WatermarkApplyStamp (alias HtmlStamp) embeds fully styled HTML/CSS overlays--logo, QR code, or diagonal text--on selected pages without rasterisation.
  • Content extractionExtractAllText and ExtractAllImages pull raw UTF-8 text or binary image streams for downstream archiving or AI pipelines.
  • Digital signatures ready – the same PdfDocument instance can be sealed with SignAndStamp, producing RFC 3161-compliant hashes aligned with ISO 32000-2 digital-signature requirements.
  • Open standard compliance – IronPDF preserves the original PDF structure (fonts, layers, XMP metadata) so the output remains compatible with Adobe® Reader and other ISO 32000-1 viewers.
  • Future-proof – The API avoids interop assemblies and Win32 GDI calls, so code runs unchanged on Windows, Linux, Docker, and upcoming .NET 10 serverless SKUs.

Need split, rotate, or delete pages? See the page-level edit tutorial for granular operations.


How can PDFs be encrypted and digitally signed in .NET Core?

IronPDF secures a document in two steps: AES-based encryption (user/owner passwords + granular permissions) and X.509 digital signatures that seal the file with a cryptographic hash. Both APIs live on the same PdfDocument object, so the workflow is identical on .NET 8 LTS today and compiles unchanged on .NET 9 preview and the forthcoming .NET 10 release.

Example — apply 256-bit AES, lock print rights, and add a visible signature

// SecureAndSign.cs — .NET 8 LTS compatible
using IronPdf;

// Step 1: Load an existing PDF (or produce one with RenderHtmlAsPdf)
PdfDocument pdf = PdfDocument.FromFile("financial-report.pdf");

// Step 2: Configure AES-256 encryption & permissions
pdf.SecuritySettings = new PdfSecuritySettings
{
    EncryptionAlgorithm   = PdfEncryptionAlgorithm.AES256Bit,
    OwnerPassword         = "IronAdmin!2025",
    UserPassword          = "ReadOnly",
    AllowUserPrinting     = PdfPrintSecurity.Disabled,
    AllowUserCopyPasteContent = false,
    AllowUserAnnotations  = false
};

// Step 3: Digitally sign with a PFX certificate
pdf.SignAndStamp(
    certificatePath : "./certs/ironsoftware.pfx",
    authority       : "Iron Software Ltd.",
    location        : "Chicago, IL",
    reason          : "Final approval"
);

// Step 4: Persist or stream
pdf.SaveAs("financial-report-secured-signed.pdf");
// SecureAndSign.cs — .NET 8 LTS compatible
using IronPdf;

// Step 1: Load an existing PDF (or produce one with RenderHtmlAsPdf)
PdfDocument pdf = PdfDocument.FromFile("financial-report.pdf");

// Step 2: Configure AES-256 encryption & permissions
pdf.SecuritySettings = new PdfSecuritySettings
{
    EncryptionAlgorithm   = PdfEncryptionAlgorithm.AES256Bit,
    OwnerPassword         = "IronAdmin!2025",
    UserPassword          = "ReadOnly",
    AllowUserPrinting     = PdfPrintSecurity.Disabled,
    AllowUserCopyPasteContent = false,
    AllowUserAnnotations  = false
};

// Step 3: Digitally sign with a PFX certificate
pdf.SignAndStamp(
    certificatePath : "./certs/ironsoftware.pfx",
    authority       : "Iron Software Ltd.",
    location        : "Chicago, IL",
    reason          : "Final approval"
);

// Step 4: Persist or stream
pdf.SaveAs("financial-report-secured-signed.pdf");
' SecureAndSign.cs — .NET 8 LTS compatible
Imports IronPdf

' Step 1: Load an existing PDF (or produce one with RenderHtmlAsPdf)
Private pdf As PdfDocument = PdfDocument.FromFile("financial-report.pdf")

' Step 2: Configure AES-256 encryption & permissions
pdf.SecuritySettings = New PdfSecuritySettings With {
	.EncryptionAlgorithm = PdfEncryptionAlgorithm.AES256Bit,
	.OwnerPassword = "IronAdmin!2025",
	.UserPassword = "ReadOnly",
	.AllowUserPrinting = PdfPrintSecurity.Disabled,
	.AllowUserCopyPasteContent = False,
	.AllowUserAnnotations = False
}

' Step 3: Digitally sign with a PFX certificate
pdf.SignAndStamp(certificatePath := "./certs/ironsoftware.pfx", authority := "Iron Software Ltd.", location := "Chicago, IL", reason := "Final approval")

' Step 4: Persist or stream
pdf.SaveAs("financial-report-secured-signed.pdf")
$vbLabelText   $csharpLabel

Behind the scenes

  • AES-256 encryption -- IronPDF wraps the payload with NIST-approved AES keys, blocking unauthorised opening, printing, or copy-paste.
  • Permissions granularity -- properties such as AllowUserPrinting and AllowUserFormData toggle per-action rights; an owner password is required for any restriction to take effect.
  • Digital signatures -- SignAndStamp embeds an RFC 3161 timestamp and certificate chain, creating tamper-evident hashes recognised by Adobe® Acrobat and other ISO 32000-2 viewers.
  • One-stop API -- both encryption and signing modify the same PdfDocument instance, avoiding multiple file passes and preserving internal fonts, layers, and metadata.

TipsTroubleshooting tip: if Adobe Reader reports “invalid signature,” ensure the PFX contains a trusted root certificate and the reason/location strings are ASCII-clean.

Core security settings

PdfSecuritySettingsOwnerPassword, UserPassword, EncryptionAlgorithm, AllowUserPrinting

PdfDocument.SignAndStamp — PFX path, authority, location, reason, timestamp

Internal resources for deeper dives


How can HTML-to-PDF performance be optimized and scaled in .NET Core?

IronPDF’s Chromium engine already renders most pages in < 1 s on modern hardware, but throughput can be multiplied by batching renders, enabling multi-threading, and trimming headless-Chrome overhead. The tips below apply equally to all .NET versions.

1. Batch renders on a background thread pool

// BatchRender.cs — Thread-safe on .NET 8+
using IronPdf;
using System.Threading.Tasks;

var htmlSources = Directory.GetFiles("./html", "*.html");
var renderer    = new ChromePdfRenderer();                 // reuse 1 instance

Parallel.ForEach(htmlSources, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, file =>
{
    string html = File.ReadAllText(file);
    using PdfDocument pdf = renderer.RenderHtmlAsPdf(html);
    pdf.SaveAs(Path.ChangeExtension(file, ".pdf"));
});
// BatchRender.cs — Thread-safe on .NET 8+
using IronPdf;
using System.Threading.Tasks;

var htmlSources = Directory.GetFiles("./html", "*.html");
var renderer    = new ChromePdfRenderer();                 // reuse 1 instance

Parallel.ForEach(htmlSources, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, file =>
{
    string html = File.ReadAllText(file);
    using PdfDocument pdf = renderer.RenderHtmlAsPdf(html);
    pdf.SaveAs(Path.ChangeExtension(file, ".pdf"));
});
' BatchRender.cs — Thread-safe on .NET 8+
Imports IronPdf
Imports System.Threading.Tasks

Private htmlSources = Directory.GetFiles("./html", "*.html")
Private renderer = New ChromePdfRenderer() ' reuse 1 instance

Parallel.ForEach(htmlSources, New ParallelOptions With {.MaxDegreeOfParallelism = Environment.ProcessorCount}, Sub(file)
	Dim html As String = File.ReadAllText(file)
	Using pdf As PdfDocument = renderer.RenderHtmlAsPdf(html)
		pdf.SaveAs(Path.ChangeExtension(file, ".pdf"))
	End Using
End Sub)
$vbLabelText   $csharpLabel

2. Trim headless-Chrome startup cost

IronPDF ships its own Chromium build, but each render incurs a small startup tax. Pooling helps, and Linux containers must include two native libs:

RUN apt-get update && \
    apt-get install -y --no-install-recommends libnss3 libatk1.0-0

Missing either library manifests as a libnss3.so not found” error in Docker logs.

Recommended Chrome flags (automatically applied by IronPDF) include --disable-gpu and --no-sandbox to reduce memory and root-user issues in containers.

3. Wait for late JavaScript with RenderDelay or WaitFor

Pages that animate counters or fetch data after DOMContentLoaded may need a short delay:

renderer.RenderingOptions.RenderDelay = 200;        // ms
// OR: renderer.RenderingOptions.JavaScript = "WaitFor('window.doneLoading')";
renderer.RenderingOptions.RenderDelay = 200;        // ms
// OR: renderer.RenderingOptions.JavaScript = "WaitFor('window.doneLoading')";
renderer.RenderingOptions.RenderDelay = 200 ' ms
' OR: renderer.RenderingOptions.JavaScript = "WaitFor('window.doneLoading')";
$vbLabelText   $csharpLabel

See the dedicated WaitFor tutorial for custom promises and DOM polling.

4. Enable debug logging for one request

renderer.LoggingOptions.DebugMode        = true;
renderer.LoggingOptions.LogsToConsole    = true;
renderer.LoggingOptions.LogFilePath      = "./logs/ironpdf-debug.log";
renderer.LoggingOptions.DebugMode        = true;
renderer.LoggingOptions.LogsToConsole    = true;
renderer.LoggingOptions.LogFilePath      = "./logs/ironpdf-debug.log";
renderer.LoggingOptions.DebugMode = True
renderer.LoggingOptions.LogsToConsole = True
renderer.LoggingOptions.LogFilePath = "./logs/ironpdf-debug.log"
$vbLabelText   $csharpLabel

Live DevTools traces expose missing fonts, 404 images, and timing events without re-compiling code.

5. Reuse template PDFs instead of re-rendering

For invoice runs, create a template PDF with placeholders like [[name]] and perform a text replace instead of rebuilding complex HTML. It’s 10× faster and memory-light.

Quick-Tuning Checklist

Parallel.ForEach, async/await, reuse a single ChromePdfRenderer

Use aspnet:8.0-jammy; install libnss3 + libatk1.0-0; flags --no-sandbox, --disable-gpu

RenderDelay, WaitFor(), log DevTools timeline for slow SPA hydrations

Further Reading


Where can I download a free trial, choose a license, and find expert support? {#anchor-10-resources}

A 30-day trial key is issued instantly from the Start Free Trial form and unlocks every feature—including HTML-to-PDF, digital signatures, and encryption—without watermarking.

After evaluating the library, pick a perpetual developer, deployment, or enterprise license; each plan includes free minor updates, dev/staging/production usage rights, and a 30-day money-back guarantee. Applying the key is a single line of code (IronPdf.License.LicenseKey = "YOUR-KEY";) and can be automated in CI/CD pipelines.

Comprehensive documentation—quick-start guides, API reference, and tutorial videos—lives at the docs portal and is updated for every .NET release.

Engineering questions receive one-business-day responses via live chat, email, or phone from the Chicago-based support team.

Performance tuning and deployment FAQs are aggregated in the Performance Assistance Centre.

Resource URL Why it matters
Get a 30-day trial key https://ironpdf.com/demos/ Unlocks every feature without watermarks
Licensing & pricing https://ironpdf.com/licensing/ Perpetual or subscription plans; Iron Suite bundles 10 libraries
API reference https://ironpdf.com/object-reference/api/ Full class docs, e.g. ChromePdfRenderer
Docs portal https://ironpdf.com/docs/ Guides, tutorials, sample projects
Performance assistance https://ironpdf.com/troubleshooting/ironpdf-performance-assistance/ Optimization and scaling tips
Contact support https://ironsoftware.com/contact-us/ Live chat, email, phone support

Next steps

  1. Clone the sample repo that demonstrates every major feature—from MVC view rendering to AES-256 encryption.
  2. Plug the trial key into an existing solution and run the unit tests to validate cross-platform compatibility.
  3. Book a live demo with the engineering team for project-specific recommendations.

With these resources in hand, any .NET team can ship pixel-perfect PDFs to production—on-prem, in Docker, or serverless—within a single sprint.

Frequently Asked Questions

How can I convert HTML to PDF in .NET Core?

You can convert HTML to PDF in .NET Core by using the IronPDF library. First, install the IronPDF NuGet package, then create a ChromePdfRenderer instance. Use the RenderHtmlAsPdf method to convert HTML strings into PDFs.

How do I convert a website URL to a PDF document?

To convert a website URL to a PDF document, install the IronPDF NuGet package, create a ChromePdfRenderer instance, and use the RenderUrlAsPdf method to render the URL into a PDF. The result can be saved using the SaveAs method.

What is the best way to convert Razor views to PDFs?

The best way to convert Razor views to PDFs is by using IronPDF. First, render the Razor view to an HTML string, then pass this string to the RenderHtmlAsPdf method to create a PDF document.

How can I enhance the security of my PDF documents?

Enhance PDF security using IronPDF by applying AES-256 encryption, setting passwords, and controlling user permissions. Configure these settings through the SecuritySettings property to restrict actions like printing and editing.

What options are available for customizing PDF rendering?

IronPDF provides various rendering options through the ChromePdfRenderOptions class, including setting paper size, orientation, margins, and applying CSS media types. You can also add headers, footers, and watermarks for customized document output.

How do I deploy a PDF generation application in a Docker container?

To deploy a PDF generation application in a Docker container, configure Linux dependencies in your Dockerfile and set user permissions. Utilize IronPdf.Installation.LinuxAndDockerDependenciesAutoConfig for automatic dependency management.

How can I add watermarks to a PDF using C#?

You can add watermarks to PDFs using IronPDF by utilizing the Watermark property with HtmlStamp objects. For advanced options, the HtmlStamper class allows for custom positioning and transparency effects.

Can I add digital signatures to PDF documents?

Yes, you can add digital signatures to PDFs using IronPDF's PdfSignature class. Use the Sign method on a PdfDocument and provide a certificate file to ensure document integrity and authenticity.

How can I optimize PDF generation performance in .NET Core?

Optimize PDF generation performance by re-using a thread-safe ChromePdfRenderer instance, enabling multi-threading, and trimming unnecessary headless-Chrome startup flags. These practices help improve the efficiency of your application.

Jacob Mellor, Chief Technology Officer @ Team Iron
Chief Technology Officer

Jacob Mellor is Chief Technology Officer at Iron Software and a visionary engineer pioneering C# PDF technology. As the original developer behind Iron Software's core codebase, he has shaped the company's product architecture since its inception, transforming it alongside CEO Cameron Rimington into a 50+ person company serving NASA, Tesla, ...Read More

Reviewed by
Jeff Fritz
Jeffrey T. Fritz
Principal Program Manager - .NET Community Team
Jeff is also a Principal Program Manager for the .NET and Visual Studio teams. He is the executive producer of the .NET Conf virtual conference series and hosts 'Fritz and Friends' a live stream for developers that airs twice weekly where he talks tech and writes code together with viewers. Jeff writes workshops, presentations, and plans content for the largest Microsoft developer events including Microsoft Build, Microsoft Ignite, .NET Conf, and the Microsoft MVP Summit