Convert HTML to PDF in .NET Core using C# with IronPDF
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 simplifies 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.
Effortlessly convert HTML to PDF in .NET Core using the IronPDF library. This guide provides a simple example to get you started quickly by rendering HTML content into a high-quality PDF with minimal code. Perfect for developers looking to integrate PDF creation into their applications with ease.
-
1Install IronPDF with NuGet Package Manager
-
2Copy and run this code snippet.
var pdf = new IronPdf.ChromePdfRenderer().RenderHtmlAsPdf("<h1>Hello World</h1>");Dim pdf = New IronPdf.ChromePdfRenderer().RenderHtmlAsPdf("<h1>Hello World</h1>")Dim pdf = New IronPdf.ChromePdfRenderer().RenderHtmlAsPdf("<h1>Hello World</h1>") -
3Deploy to test on your live environment
Start using IronPDF in your project today with a free trial
Minimal Workflow (5 steps)
- Install the
IronPdfNuGet package - Convert a website URL with
RenderUrlAsPdf - Render raw HTML via
RenderHtmlAsPdf - Export an MVC view to PDF
- Tune paper size, margins, headers, and footers
Quick-Start Checklist
- Install -
Install-Package IronPdf - Render a URL -
ChromePdfRenderer.RenderUrlAsPdf() - Render raw HTML -
ChromePdfRenderer.RenderHtmlAsPdf() - Export a Razor view -
ChromePdfRenderer.RenderHtmlAsPdfAsync() - 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
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 STS and .NET 10 LTS. Use NuGet's Package Manager Console and the package manager will resolve every dependency automatically for Windows, Linux, Docker, and serverless targets.
:ProductInstall # .NET 8 LTS and higher
dotnet add package IronPdf inside your project folder.Once installed, confirm everything is wired up by converting any public URL:
public class ClientModel
{
[Required]
public string Name { get; set; }
[Required]
public string Phone { get; set; }
[Required]
public string Email { get; set; }
}public class ClientModel
{
[Required]
public string Name { get; set; }
[Required]
public string Phone { get; set; }
[Required]
public string Email { get; set; }
}Public Class ClientModel
<Required>
Public Property Name() As String
<Required>
Public Property Phone() As String
<Required>
Public Property Email() As String
End ClassPublic Class ClientModel
<Required>
Public Property Name() As String
<Required>
Public Property Phone() As String
<Required>
Public Property Email() As String
End ClassHow it works
ChromePdfRendererspins up a sandboxed Chromium instance under the hood; no separate Chrome install is required.RenderUrlAsPdfcaptures the fully rendered DOM, including JavaScript-driven content, CSS media queries, and fonts.- The resulting
PdfDocumentexposes 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 STS as well as the forthcoming .NET 10 release in 2025.
Step-by-step example
public class ClientServices
{
private static ClientModel _clientModel;
public static void AddClient(ClientModel clientModel)
{
_clientModel = clientModel;
}
public static ClientModel GetClient()
{
return _clientModel;
}
}public class ClientServices
{
private static ClientModel _clientModel;
public static void AddClient(ClientModel clientModel)
{
_clientModel = clientModel;
}
public static ClientModel GetClient()
{
return _clientModel;
}
}Public Class ClientServices
Private Shared _clientModel As ClientModel
Public Shared Sub AddClient(ByVal clientModel As ClientModel)
_clientModel = clientModel
End Sub
Public Shared Function GetClient() As ClientModel
Return _clientModel
End Function
End ClassPublic Class ClientServices
Private Shared _clientModel As ClientModel
Public Shared Sub AddClient(ByVal clientModel As ClientModel)
_clientModel = clientModel
End Sub
Public Shared Function GetClient() As ClientModel
Return _clientModel
End Function
End ClassWhy it works
ChromePdfRendererspins up a sandboxed Chromium instance: no system Chrome dependency, keeping Docker images slim.RenderUrlAsPdfwaits for the DOM and JavaScript to finish before snapshotting, so single-page apps render correctly.- Setting
CssMediaTypeto Print tells the engine to use print-specific rules, matching a browser's Print → Save as PDF output. - The resulting
PdfDocumentcan be encrypted, digitally signed, merged, or rasterized: capabilities covered in later sections.
IronPdf.Logging.Logger.LoggingMode and follow the Headless Chrome debug guide to inspect live DevTools during rendering.Related resources
- API reference -
ChromePdfRenderer.RenderUrlAsPdf - API reference -
PdfDocument.SaveAs - Tutorial - Deploy IronPDF in Docker containers
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
@model IronPdfMVCHelloWorld.Models.ClientModel
@{
ViewBag.Title = "Book Ticket";
}
<h2>Index</h2>
@using (Html.BeginForm())
{
<div class="form-horizontal">
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Phone, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Phone, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Phone, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Email, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Email, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Email, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-10 pull-right">
<button type="submit" value="Save" class="btn btn-sm">
<i class="fa fa-plus"></i>
<span>
Save
</span>
</button>
</div>
</div>
</div>
}@model IronPdfMVCHelloWorld.Models.ClientModel
@{
ViewBag.Title = "Book Ticket";
}
<h2>Index</h2>
@using (Html.BeginForm())
{
<div class="form-horizontal">
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Phone, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Phone, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Phone, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Email, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Email, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Email, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-10 pull-right">
<button type="submit" value="Save" class="btn btn-sm">
<i class="fa fa-plus"></i>
<span>
Save
</span>
</button>
</div>
</div>
</div>
}model ReadOnly Property () As IronPdfMVCHelloWorld.Models.ClientModel
ViewBag.Title = "Book Ticket"
End Property
'INSTANT VB TODO TASK: The following line could not be converted:
(Of h2) Index</h2> [using](Html.BeginForm())
If True Then
'INSTANT VB TODO TASK: The following line uses invalid syntax:
' <div class="form-horizontal"> @Html.ValidationSummary(True, "", New { @class = "text-danger" }) <div class="form-group"> @Html.LabelFor(model => model.Name, htmlAttributes: New { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Name, New { htmlAttributes = New { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Name, "", New { @class = "text-danger" }) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Phone, htmlAttributes: New { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Phone, New { htmlAttributes = New { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Phone, "", New { @class = "text-danger" }) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Email, htmlAttributes: New { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Email, New { htmlAttributes = New { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Email, "", New { @class = "text-danger" }) </div> </div> <div class="form-group"> <div class="col-md-10 pull-right"> <button type="submit" value="Save" class="btn btn-sm"> <i class="fa fa-plus"></i> <span> Save </span> </button> </div> </div> </div> }model ReadOnly Property () As IronPdfMVCHelloWorld.Models.ClientModel
ViewBag.Title = "Book Ticket"
End Property
'INSTANT VB TODO TASK: The following line could not be converted:
(Of h2) Index</h2> [using](Html.BeginForm())
If True Then
'INSTANT VB TODO TASK: The following line uses invalid syntax:
' <div class="form-horizontal"> @Html.ValidationSummary(True, "", New { @class = "text-danger" }) <div class="form-group"> @Html.LabelFor(model => model.Name, htmlAttributes: New { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Name, New { htmlAttributes = New { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Name, "", New { @class = "text-danger" }) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Phone, htmlAttributes: New { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Phone, New { htmlAttributes = New { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Phone, "", New { @class = "text-danger" }) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Email, htmlAttributes: New { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Email, New { htmlAttributes = New { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Email, "", New { @class = "text-danger" }) </div> </div> <div class="form-group"> <div class="col-md-10 pull-right"> <button type="submit" value="Save" class="btn btn-sm"> <i class="fa fa-plus"></i> <span> Save </span> </button> </div> </div> </div> }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, andRenderDelaymirror 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:
PdfDocumentexposes 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 STS, 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,
FitToPaperMode = IronPdf.Engines.Chrome.FitToPaperModes.AutomaticFit,
CssMediaType = PdfCssMediaType.Print,
MarginTop = 5, MarginBottom = 10, MarginLeft = 5, MarginRight = 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,
FitToPaperMode = IronPdf.Engines.Chrome.FitToPaperModes.AutomaticFit,
CssMediaType = PdfCssMediaType.Print,
MarginTop = 5, MarginBottom = 10, MarginLeft = 5, MarginRight = 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");
}
}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 = New ChromePdfRenderOptions With {
.PaperSize = PdfPaperSize.A5, ' Compact ticket size
.PaperOrientation = PdfPaperOrientation.Portrait,
.FitToPaperMode = IronPdf.Engines.Chrome.FitToPaperModes.AutomaticFit,
.CssMediaType = PdfCssMediaType.Print,
.MarginTop = 5,
.MarginBottom = 10,
.MarginLeft = 5,
.MarginRight = 10
}
}
End Sub
' GET /Tickets/Print/42
Public Async Function Print(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 ClassImports 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 = New ChromePdfRenderOptions With {
.PaperSize = PdfPaperSize.A5, ' Compact ticket size
.PaperOrientation = PdfPaperOrientation.Portrait,
.FitToPaperMode = IronPdf.Engines.Chrome.FitToPaperModes.AutomaticFit,
.CssMediaType = PdfCssMediaType.Print,
.MarginTop = 5,
.MarginBottom = 10,
.MarginLeft = 5,
.MarginRight = 10
}
}
End Sub
' GET /Tickets/Print/42
Public Async Function Print(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 ClassWhat 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 = A5and narrow margins keep print-at-home tickets compact. - Consistent print styles:
CssMediaType = Printapplies the same@media printCSS rules that browsers use. - Binary streaming:
pdf.BinaryDatastreams the document without touching the file-system; ideal for API endpoints and Lambda functions. - Re-usable renderer:
ChromePdfRendereris instantiated once per controller, then reused, minimizing process-spawn overhead.
Paper & Orientation
PaperSize, PaperOrientation, FitToPaperMode
Margins & Headers / Footers
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
[HttpPost]
public ActionResult Index(ClientModel model)
{
if (ModelState.IsValid)
{
ClientServices.AddClient(model);
return RedirectToAction("TicketView");
}
return View(model);
}[HttpPost]
public ActionResult Index(ClientModel model)
{
if (ModelState.IsValid)
{
ClientServices.AddClient(model);
return RedirectToAction("TicketView");
}
return View(model);
}<HttpPost>
Public Function Index(ByVal model As ClientModel) As ActionResult
If ModelState.IsValid Then
ClientServices.AddClient(model)
Return RedirectToAction("TicketView")
End If
Return View(model)
End Function<HttpPost>
Public Function Index(ByVal model As ClientModel) As ActionResult
If ModelState.IsValid Then
ClientServices.AddClient(model)
Return RedirectToAction("TicketView")
End If
Return View(model)
End FunctionWhy these options matter
PaperSize,Margins, andCssMediaTypemirror 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.
ApplyStamplets a single line create branded watermarks with full HTML + CSS control.- Security options enable 128-bit RC4 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
ExtractAllTextandExtractAllImagesreverse the process when analysis is required.
Quick reference: Popular settings
Page Layout & Media
PaperSize, PaperOrientation, Margins, CssMediaType, RenderDelay
Headers & Footers
HtmlHeader, HtmlFooter, dynamic Razor placeholders, page-number tokens
Watermarking
Watermark, HtmlStamper, opacity, alignment
Encryption & Signatures
SecurityOptions, SignAndStamp, owner / user passwords, 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)
####### ---------- 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"]
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
- The API action internally calls
ChromePdfRenderer.RenderUrlAsPdfjust 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 modest even during large renders.
libnss3 and libatk1.0-0 are present. Alpine images are not supported because the musl C library lacks required symbols.Internal resources
- Tutorial - Deploy IronPDF in Docker containers
- How-to - Run IronPDF on Azure App Service Linux
- API reference -
ChromePdfRendererclass
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 .NET 9 STS and the forthcoming .NET 10 release.
Unified sample: open → merge → watermark → extract
[HttpPost]
public ActionResult TicketView(TicketModel model)
{
IronPdf.Installation.TempFolderPath = $@"{Directory.GetParent}/irontemp/";
IronPdf.Installation.LinuxAndDockerDependenciesAutoConfig = true;
var html = this.RenderViewAsync("_TicketPdf", model);
var renderer = new IronPdf.ChromePdfRenderer();
using var pdf = renderer.RenderHtmlAsPdf(html.Result, @"wwwroot/css");
return File(pdf.Stream.ToArray(), "application/pdf");
}[HttpPost]
public ActionResult TicketView(TicketModel model)
{
IronPdf.Installation.TempFolderPath = $@"{Directory.GetParent}/irontemp/";
IronPdf.Installation.LinuxAndDockerDependenciesAutoConfig = true;
var html = this.RenderViewAsync("_TicketPdf", model);
var renderer = new IronPdf.ChromePdfRenderer();
using var pdf = renderer.RenderHtmlAsPdf(html.Result, @"wwwroot/css");
return File(pdf.Stream.ToArray(), "application/pdf");
}<HttpPost>
Public Function TicketView(ByVal model As TicketModel) As ActionResult
IronPdf.Installation.TempFolderPath = $"{AddressOf Directory.GetParent}/irontemp/"
IronPdf.Installation.LinuxAndDockerDependenciesAutoConfig = True
Dim html = Me.RenderViewAsync("_TicketPdf", model)
Dim renderer = New IronPdf.ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html.Result, "wwwroot/css")
Return File(pdf.Stream.ToArray(), "application/pdf")
End Function<HttpPost>
Public Function TicketView(ByVal model As TicketModel) As ActionResult
IronPdf.Installation.TempFolderPath = $"{AddressOf Directory.GetParent}/irontemp/"
IronPdf.Installation.LinuxAndDockerDependenciesAutoConfig = True
Dim html = Me.RenderViewAsync("_TicketPdf", model)
Dim renderer = New IronPdf.ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html.Result, "wwwroot/css")
Return File(pdf.Stream.ToArray(), "application/pdf")
End FunctionWhy this matters
- Open & merge –
PdfDocument.FromFileloads any standards-compliant PDF, including encrypted files, whilePdfDocument.Mergeconcatenates an arbitrary number of documents in a single call. - Watermark –
ApplyStamp(new HtmlStamper(...))embeds fully styled HTML/CSS overlays (logo, QR code, or diagonal text) on selected pages without rasterisation. - Content extraction –
ExtractAllTextandExtractAllImagespull raw UTF-8 text or binary image streams for downstream archiving or AI pipelines, whileExtractTextFromLayerscopes extraction to a named layer (OCG) in layered PDFs. - Digital signatures ready – the same
PdfDocumentinstance can be sealed by creating aPdfSignatureand callingpdf.Sign(signature), 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: password-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 STS and the forthcoming .NET 10 release.
Example: encrypt a document, lock print rights, and add a visible signature
using IronPdf;
using IronPdf.Signing;
using System.Drawing;
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Confidential Report</h1>");
// Password-protect the document.
pdf.SecuritySettings.OwnerPassword = "owner-secret";
pdf.SecuritySettings.UserPassword = "user-secret";
// Lock print rights. An owner password is required for this to take effect.
pdf.SecuritySettings.AllowUserPrinting = IronPdf.Security.PdfPrintSecurity.NoPrint;
// Sign the document and stamp a visible signature image onto page 1.
var signature = new PdfSignature("cert123.pfx", "password")
{
SigningContact = "support@ironsoftware.com",
SigningLocation = "Chicago, USA",
SigningReason = "Confidential Report Approval",
SignatureImage = new PdfSignatureImage("IronSoftware.png", 0, new Rectangle(350, 750, 200, 100))
};
pdf.Sign(signature);
pdf.SaveAs("SecuredSignedReport.pdf");using IronPdf;
using IronPdf.Signing;
using System.Drawing;
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Confidential Report</h1>");
// Password-protect the document.
pdf.SecuritySettings.OwnerPassword = "owner-secret";
pdf.SecuritySettings.UserPassword = "user-secret";
// Lock print rights. An owner password is required for this to take effect.
pdf.SecuritySettings.AllowUserPrinting = IronPdf.Security.PdfPrintSecurity.NoPrint;
// Sign the document and stamp a visible signature image onto page 1.
var signature = new PdfSignature("cert123.pfx", "password")
{
SigningContact = "support@ironsoftware.com",
SigningLocation = "Chicago, USA",
SigningReason = "Confidential Report Approval",
SignatureImage = new PdfSignatureImage("IronSoftware.png", 0, new Rectangle(350, 750, 200, 100))
};
pdf.Sign(signature);
pdf.SaveAs("SecuredSignedReport.pdf");Imports IronPdf
Imports IronPdf.Signing
Imports System.Drawing
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Confidential Report</h1>")
' Password-protect the document.
pdf.SecuritySettings.OwnerPassword = "owner-secret"
pdf.SecuritySettings.UserPassword = "user-secret"
' Lock print rights. An owner password is required for this to take effect.
pdf.SecuritySettings.AllowUserPrinting = IronPdf.Security.PdfPrintSecurity.NoPrint
' Sign the document and stamp a visible signature image onto page 1.
Dim signature = New PdfSignature("cert123.pfx", "password") With {
.SigningContact = "support@ironsoftware.com",
.SigningLocation = "Chicago, USA",
.SigningReason = "Confidential Report Approval",
.SignatureImage = New PdfSignatureImage("IronSoftware.png", 0, New Rectangle(350, 750, 200, 100))
}
pdf.Sign(signature)
pdf.SaveAs("SecuredSignedReport.pdf")Imports IronPdf
Imports IronPdf.Signing
Imports System.Drawing
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Confidential Report</h1>")
' Password-protect the document.
pdf.SecuritySettings.OwnerPassword = "owner-secret"
pdf.SecuritySettings.UserPassword = "user-secret"
' Lock print rights. An owner password is required for this to take effect.
pdf.SecuritySettings.AllowUserPrinting = IronPdf.Security.PdfPrintSecurity.NoPrint
' Sign the document and stamp a visible signature image onto page 1.
Dim signature = New PdfSignature("cert123.pfx", "password") With {
.SigningContact = "support@ironsoftware.com",
.SigningLocation = "Chicago, USA",
.SigningReason = "Confidential Report Approval",
.SignatureImage = New PdfSignatureImage("IronSoftware.png", 0, New Rectangle(350, 750, 200, 100))
}
pdf.Sign(signature)
pdf.SaveAs("SecuredSignedReport.pdf")Behind the scenes
- Password encryption: IronPDF encrypts the document with 128-bit RC4, blocking unauthorized opening, printing, or copy-paste.
- Permissions granularity: properties such as
AllowUserPrintingandAllowUserFormDatatoggle per-action rights; an owner password is required for any restriction to take effect. - Digital signatures: creating a
PdfSignatureand callingpdf.Sign(signature)embeds a certificate chain and a visibleSignatureImage, creating tamper-evident hashes recognized by Adobe® Acrobat and other ISO 32000-2 viewers. - One-stop API: both encryption and signing modify the same
PdfDocumentinstance, avoiding multiple file passes and preserving internal fonts, layers, and metadata.
reason/location strings are ASCII-clean.Core security settings
Encryption & Passwords
PdfSecuritySettings → OwnerPassword, UserPassword, AllowUserPrinting
Digital Signatures
PdfDocument.Sign(PdfSignature): PFX path, authority, location, reason, timestamp
Internal resources for deeper dives
- Tutorial - Password-protect a PDF
- Example - Digitally sign a PDF
- API reference -
PdfSecuritySettings
How can HTML-to-PDF performance be optimized and scaled in .NET Core?
IronPDF's Chromium engine already renders quickly 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
IronPdf.License.LicenseKey = "YourLicenseKey";
ChromePdfRenderer renderer = new ChromePdfRenderer();
// Set rendering options
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;
renderer.RenderingOptions.PaperOrientation = IronPdf.Rendering.PdfPaperOrientation.Portrait;
renderer.RenderHtmlFileAsPdf(@"testFile.html").SaveAs("GeneratedFile.pdf");IronPdf.License.LicenseKey = "YourLicenseKey";
ChromePdfRenderer renderer = new ChromePdfRenderer();
// Set rendering options
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;
renderer.RenderingOptions.PaperOrientation = IronPdf.Rendering.PdfPaperOrientation.Portrait;
renderer.RenderHtmlFileAsPdf(@"testFile.html").SaveAs("GeneratedFile.pdf");Imports IronPdf
License.LicenseKey = "YourLicenseKey"
Dim renderer As New ChromePdfRenderer()
' Set rendering options
renderer.RenderingOptions.PaperSize = Rendering.PdfPaperSize.A4
renderer.RenderingOptions.PaperOrientation = Rendering.PdfPaperOrientation.Portrait
renderer.RenderHtmlFileAsPdf("testFile.html").SaveAs("GeneratedFile.pdf")Imports IronPdf
License.LicenseKey = "YourLicenseKey"
Dim renderer As New ChromePdfRenderer()
' Set rendering options
renderer.RenderingOptions.PaperSize = Rendering.PdfPaperSize.A4
renderer.RenderingOptions.PaperOrientation = Rendering.PdfPaperOrientation.Portrait
renderer.RenderHtmlFileAsPdf("testFile.html").SaveAs("GeneratedFile.pdf")ChromePdfRendereris thread-safe; a single instance may serve dozens of concurrent tasks without deadlocks.Parallel.ForEachsaturates every CPU core, improving throughput compared with a single-thread loop.- If ASP.NET requests queue up, move heavy renders to a hosted background service or message queue to keep response times low.
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.WaitFor.JavaScript("window.doneLoading === true");renderer.RenderingOptions.RenderDelay = 200; // ms
// OR: renderer.RenderingOptions.WaitFor.JavaScript("window.doneLoading === true");renderer.RenderingOptions.RenderDelay = 200 ' ms
' OR: renderer.RenderingOptions.WaitFor.JavaScript("window.doneLoading = true")renderer.RenderingOptions.RenderDelay = 200 ' ms
' OR: renderer.RenderingOptions.WaitFor.JavaScript("window.doneLoading = true")See the dedicated WaitFor tutorial for custom promises and DOM polling.
4. Enable debug logging for one request
IronPdf.License.LicenseKey = "YourLicenseKey";
PdfDocument pdf = PdfDocument.FromFile("1.pdf");
PdfDocument pdf2 = PdfDocument.FromFile("2.pdf");
pdf.AppendPdf(pdf2);
pdf.SaveAs("appendedFile.pdf");IronPdf.License.LicenseKey = "YourLicenseKey";
PdfDocument pdf = PdfDocument.FromFile("1.pdf");
PdfDocument pdf2 = PdfDocument.FromFile("2.pdf");
pdf.AppendPdf(pdf2);
pdf.SaveAs("appendedFile.pdf");IronPdf.License.LicenseKey = "YourLicenseKey"
Dim pdf As PdfDocument = PdfDocument.FromFile("1.pdf")
Dim pdf2 As PdfDocument = PdfDocument.FromFile("2.pdf")
pdf.AppendPdf(pdf2)
pdf.SaveAs("appendedFile.pdf")IronPdf.License.LicenseKey = "YourLicenseKey"
Dim pdf As PdfDocument = PdfDocument.FromFile("1.pdf")
Dim pdf2 As PdfDocument = PdfDocument.FromFile("2.pdf")
pdf.AppendPdf(pdf2)
pdf.SaveAs("appendedFile.pdf")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 avoids re-rendering complex HTML and is memory-light.
Quick-Tuning Checklist
Multi-Thread & Async
Parallel.ForEach, async/await, reuse a single ChromePdfRenderer
Docker-Optimised Images
Use aspnet:8.0-jammy; install libnss3 + libatk1.0-0; flags --no-sandbox, --disable-gpu
JavaScript Timing
RenderDelay, WaitFor(), log DevTools timeline for slow SPA hydrations
Further Reading
- How-to - Generate PDFs with async / multithreading
- Troubleshooting - Performance assistance centre
- Example - Threaded rendering demo
Where can I download a free trial, choose a license, and find expert support?
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.
Quick links
| 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
- Clone the sample repo that demonstrates every major feature, from MVC view rendering to password-based encryption.
- Plug the trial key into an existing solution and run the unit tests to validate cross-platform compatibility.
- 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 do I convert HTML to PDF using IronPDF in .NET Core?
To convert HTML to PDF using IronPDF in .NET Core, you can use the ChromePdfRenderer class methods such as RenderHtmlAsPdf or RenderUrlAsPdf. This allows you to render HTML content, URLs, or ASP.NET MVC views into high-quality PDFs, suitable for cross-platform development on Windows, Linux, and Docker.
What are the steps to install IronPDF in a .NET Core project?
Installing IronPDF in a .NET Core project requires adding it via the NuGet Package Manager Console with the command Install-Package IronPdf. This resolves all necessary dependencies and enables using IronPDF's features in your application.
Can IronPDF be used with Docker and Linux containers?
Yes, IronPDF can be deployed in Docker and Linux containers. It requires a couple of native libraries on Linux, specifically libnss3 and libatk1.0-0. The documentation includes a sample Dockerfile to assist with this setup.
What are the key features of IronPDF for handling PDF documents?
IronPDF supports a variety of features including converting HTML, URLs, and Razor views to PDF; adding headers and footers; applying watermarks; AES-256 encryption; digital signatures; and post-processing like merging and extracting content from existing PDFs.
How can an ASP.NET Core MVC view be exported to PDF using IronPDF?
IronPDF allows exporting an ASP.NET Core MVC view to PDF by rendering the Razor view as an HTML string and then converting it using the RenderHtmlAsPdf method. This process is kept simple to maintain clean controller logic and requires no browser plugins.
How can I optimize IronPDF's HTML-to-PDF rendering performance?
You can optimize IronPDF's performance by batching renders, leveraging multi-threading, and configuring Chromium to reduce overhead. Using methods like Parallel.ForEach or async/await can help maximize throughput.
Are there specific configuration settings for fine-tuning PDF output in IronPDF?
Yes, IronPDF provides a ChromePdfRenderOptions object that allows you to define settings such as paper size, orientation, margins, CSS media type, headers, footers, watermarks, and security options for detailed control over the PDF output.
What is required to create a Docker image for an ASP.NET Core app using IronPDF?
Creating a Docker image requires a multi-stage build process where the SDK compiles the project and the runtime image runs it. For Linux, installing libnss3 and libatk1.0-0 is necessary. For Windows, using an aspnet:8.0-windowsservercore image simplifies the process as Chromium DLLs are included.
How can PDFs be merged, watermarked, or signed with IronPDF?
IronPDF allows merging, watermarking, and signing PDFs by treating them as PdfDocument objects. You can use methods like ApplyStamp for watermarks and PdfSignature for digital signatures, while PdfDocument.Merge handles merging multiple PDF files.
What licensing options are available for IronPDF?
IronPDF offers a 30-day trial with full functionality, and various licensing options including developer, deployment, or enterprise licenses. Each provides features like minor updates, dev/staging/production rights, and a 30-day money-back guarantee.
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, and global government agencies.