Cómo generar archivos PDF en .NET Core

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

This article was translated from English: Does it need improvement?
Translated
View the article in English

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.

ConsejosFor 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.

Quickstart: Create a PDF from HTML in .NET Core

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.

Nuget IconGet started making PDFs with NuGet now:

  1. Install IronPDF with NuGet Package Manager

    PM > Install-Package IronPdf

  2. Copy and run this code snippet.

    var pdf = new IronPdf.ChromePdfRenderer().RenderHtmlAsPdf("<h1>Hello World</h1>");
  3. Deploy to test on your live environment

    Start using IronPDF in your project today with a free trial
    arrow pointer

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

Comience a usar IronPDF en su proyecto hoy con una prueba gratuita.

Primer Paso:
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

Por favor notaNeed 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.

ConsejosPixel-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)

Por favor notaWhy 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"]

Por favor notaWindows 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.

ConsejosTroubleshooting 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.

ConsejosTroubleshooting 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.

Preguntas Frecuentes

¿Cómo puedo convertir HTML a PDF en .NET Core?

Puedes convertir HTML a PDF en .NET Core usando la biblioteca IronPDF. Primero, instala el paquete NuGet de IronPDF, luego crea una instancia de ChromePdfRenderer. Usa el método RenderHtmlAsPdf para convertir cadenas HTML en PDFs.

¿Cómo convierto un URL de sitio web a un documento PDF?

Para convertir un URL de sitio web a un documento PDF, instala el paquete NuGet de IronPDF, crea una instancia de ChromePdfRenderer, y usa el método RenderUrlAsPdf para renderizar el URL en un PDF. El resultado se puede guardar usando el método SaveAs.

¿Cuál es la mejor manera de convertir vistas de Razor a PDFs?

La mejor manera de convertir vistas de Razor a PDFs es usando IronPDF. Primero, renderiza la vista Razor a una cadena HTML, luego pasa esta cadena al método RenderHtmlAsPdf para crear un documento PDF.

¿Cómo puedo mejorar la seguridad de mis documentos PDF?

Mejora la seguridad de PDF usando IronPDF aplicando cifrado AES-256, estableciendo contraseñas y controlando permisos de usuario. Configura estas opciones a través de la propiedad SecuritySettings para restringir acciones como impresión y edición.

¿Qué opciones están disponibles para personalizar el renderizado de PDF?

IronPDF proporciona varias opciones de renderización a través de la clase ChromePdfRenderOptions, incluidas configuraciones de tamaño de papel, orientación, márgenes y aplicación de tipos de medios CSS. También puedes agregar encabezados, pies de página, y marcas de agua para una salida de documentos personalizada.

¿Cómo implemento una aplicación de generación de PDF en un contenedor Docker?

Para implementar una aplicación de generación de PDF en un contenedor Docker, configura dependencias de Linux en tu Dockerfile y establece permisos de usuario. Utiliza IronPdf.Installation.LinuxAndDockerDependenciesAutoConfig para la gestión automática de dependencias.

¿Cómo puedo agregar marcas de agua a un PDF usando C#?

Puedes agregar marcas de agua a PDFs usando IronPDF utilizando la propiedad Watermark con objetos HtmlStamp. Para opciones avanzadas, la clase HtmlStamper permite un posicionamiento personalizado y efectos de transparencia.

¿Puedo agregar firmas digitales a documentos PDF?

Sí, puedes agregar firmas digitales a PDFs usando la clase PdfSignature de IronPDF. Usa el método Sign en un PdfDocument y proporciona un archivo de certificado para asegurar la integridad y autenticidad del documento.

¿Cómo puedo optimizar el rendimiento de generación de PDFs en .NET Core?

Optimiza el rendimiento de generación de PDFs reutilizando una instancia segura para hilos de ChromePdfRenderer, habilitando multi-threading y eliminando banderas innecesarias de inicio de Chrome sin cabeza. Estas prácticas ayudan a mejorar la eficiencia de tu aplicación.

¿Funciona el ejemplo de HTML a PDF de .NET Core en este tutorial con .NET 10?

Sí. IronPDF es totalmente compatible con .NET 10, por lo que puedes usar el ejemplo de HTML a PDF de ChromePdfRenderer de este tutorial en proyectos de .NET 10 sin cambiar el código principal. La principal diferencia es que debes orientar a .NET 10 al crear el proyecto y luego instalar el paquete más reciente de IronPdf desde NuGet para generar PDFs perfectos a partir de HTML, vistas Razor o URLs.

Jacob Mellor, Director de Tecnología @ Team Iron
Director de Tecnología

Jacob Mellor es Director de Tecnología en Iron Software y un ingeniero visionario que lidera la tecnología PDF en C#. Como el desarrollador original detrás de la base de código central de Iron Software, ha moldeado la arquitectura de productos de la compañía desde ...

Leer más
Revisado por
Jeff Fritz
Jeffrey T. Fritz
Gerente Principal de Programas - Equipo de la Comunidad .NET
Jeff también es Gerente Principal de Programas para los equipos de .NET y Visual Studio. Es el productor ejecutivo de la serie de conferencias virtuales .NET Conf y anfitrión de 'Fritz and Friends', una transmisión en vivo para desarrolladores que se emite dos veces a la semana donde habla sobre tecnología y escribe código junto con la audiencia. Jeff escribe talleres, presentaciones, y planifica contenido para los eventos de desarrolladores más importantes de Microsoft, incluyendo Microsoft Build, Microsoft Ignite, .NET Conf y la Cumbre de Microsoft MVP.
¿Listo para empezar?
Nuget Descargas 16,154,058 | Versión: 2025.11 recién lanzado