Cómo construir un servicio centralizado de generación de PDF con ASP.NET Core e IronPDF
Cree una API de PDF .NET lista para producción usando ASP.NET Core e IronPDF para centralizar la lógica de generación de PDF, lo que permite la creación consistente de documentos en todas sus aplicaciones con puntos finales RESTful para conversión de HTML a PDF, fusión, marca de agua y procesamiento dinámico de plantillas.
Al trabajar con aplicaciones modernas, los desarrolladores .NET suelen necesitar crear un servicio centralizado de generación de PDF. Ya sea que generen facturas, informes, certificados o contratos, contar con una API .NET PDF dedicada mejora su flujo de trabajo de generación de PDF. ¿Cómo ayuda? Proporciona consistencia, facilidad de mantenimiento y escalabilidad en tus aplicaciones de escritorio y web. Administrar el contenido de documentos, páginas PDF y campos de formularios PDF se vuelve sencillo.
En este tutorial, aprenderá a crear una API PDF lista para producción utilizando ASP.NET Core e IronPDF, una potente biblioteca PDF .NET. Crearemos puntos finales RESTful que generarán archivos PDF a partir de HTML, fusionarán documentos , agregarán marcas de agua y manejarán varios escenarios de PDF del mundo real en su API web.
¿Por qué crear una API PDF dedicada?

Antes de sumergirnos en el código, entendamos por qué tiene sentido crear una API dedicada de PDF:
- Lógica centralizada : toda la lógica de generación de PDF reside en un solo lugar, lo que simplifica el mantenimiento y las actualizaciones.
- Arquitectura de microservicios : perfecta para arquitecturas orientadas a servicios donde diferentes aplicaciones necesitan capacidades de PDF.
- Optimización del rendimiento : es más fácil escalar y optimizar un servicio dedicado para archivos PDF grandes, páginas múltiples y datos dinámicos mediante operaciones asincrónicas y técnicas de rendimiento .
- Agnóstico del lenguaje : cualquier aplicación cliente puede consumir la API independientemente del lenguaje de programación.
- Salida consistente : garantiza que todos los archivos PDF de su organización mantengan un diseño, formato y contenido consistentes.
¿Listo para empezar a construir? Descargue la prueba gratuita de IronPDF y siga este tutorial para crear archivos PDF programáticamente en sus proyectos de .NET Framework.
¿Qué hace que IronPDF sea la biblioteca PDF .NET completa?

IronPDF destaca como la principal biblioteca PDF para desarrolladores .NET, ya que ofrece un completo conjunto de funciones que hacen que la generación de PDF en proyectos de API web sea sencilla y fiable. Construido sobre un motor de renderizado Chrome , garantiza conversiones de HTML a PDF con píxeles perfectos en solo unas pocas líneas de código mientras mantiene todo el estilo, la ejecución de JavaScript y los diseños responsivos .
Las capacidades clave que hacen que IronPDF sea ideal para el desarrollo de API de PDF para .NET:
- Representación basada en Chrome : utiliza el motor de Google Chrome para una conversión precisa de HTML a PDF con soporte completo para imágenes incrustadas y activos web.
- Amplio conjunto de funciones : edite documentos con firmas digitales , formularios PDF , anotaciones , cifrado , compresión y más.
- Cree archivos PDF seguros : administre contenido confidencial con cifrado , firmas digitales y protección de documentos.
- Múltiples formatos de entrada : utilice HTML, URL, imágenes y documentos de Office para crear archivos PDF.
- Manipulación avanzada : fusione páginas , divida documentos , aplique marcas de agua , cree formularios interactivos y manipule archivos PDF mediante programación.
- Compatibilidad multiplataforma : funciona en Windows , Linux , macOS , Docker y plataformas en la nube .
- Rendimiento optimizado : operaciones asincrónicas , gestión de memoria eficiente y renderizado rápido con opciones de retraso de renderizado .
¿Cómo configurar su proyecto de API de documentos PDF?
Comencemos creando un nuevo proyecto API web de ASP.NET Core e instalando los paquetes necesarios.
¿Cuáles son los requisitos previos?
- SDK de .NET 6.0 o posterior
- Visual Studio 2022 or Visual Studio Code
- Postman o una herramienta de prueba de API similar para probar su API REST de PDF
¿Cómo creo el proyecto?
Primero, creemos el proyecto donde construiremos nuestra herramienta de generación de PDF.
dotnet new webapi -n PdfApiService
cd PdfApiService
dotnet new webapi -n PdfApiService
cd PdfApiService
¿Cómo instalo IronPDF?
A continuación, agregue IronPDF a su proyecto a través de NuGet:
dotnet add package IronPDF
dotnet add package IronPDF
O, utilizando el Consola del Administrador de Paquetes de NuGet en Visual Studio:
Install-Package IronPDF
Para conocer opciones de instalación avanzadas, incluidos paquetes específicos de la plataforma , configuración de Docker o configuraciones de Linux , consulte la documentación de instalación de IronPDF .
¿Qué estructura de proyecto debo utilizar?
Un buen desarrollo de C# requiere mantener una carpeta de proyecto limpia y bien estructurada. Por ejemplo:

¿Cómo crear su primer punto final PDF?
Construyamos un endpoint simple que convierta HTML al formato PDF. Primero, cree la interfaz del servicio y la implementación:
¿Cómo creo el servicio PDF?
Primero, agregue lo siguiente a su archivo IPdfService.cs:
public interface IPdfService
{
byte[] GeneratePdfFromHtml(string htmlContent);
byte[] GeneratePdfFromUrl(string url);
}
public interface IPdfService
{
byte[] GeneratePdfFromHtml(string htmlContent);
byte[] GeneratePdfFromUrl(string url);
}
Public Interface IPdfService
Function GeneratePdfFromHtml(htmlContent As String) As Byte()
Function GeneratePdfFromUrl(url As String) As Byte()
End Interface
En el archivo PdfService.cs, agregue esto:
using IronPdf;
public class PdfService : IPdfService
{
private readonly ChromePdfRenderer _renderer;
public PdfService()
{
_renderer = new ChromePdfRenderer();
// Configure rendering options for optimal PDF generation in .NET
_renderer.RenderingOptions.MarginTop = 20;
_renderer.RenderingOptions.MarginBottom = 20;
_renderer.RenderingOptions.PrintHtmlBackgrounds = true;
}
public byte[] GeneratePdfFromHtml(string htmlContent)
{
// Generate PDF from HTML using the .NET PDF API
var pdf = _renderer.RenderHtmlAsPdf(htmlContent);
return pdf.BinaryData;
}
public byte[] GeneratePdfFromUrl(string url)
{
// Convert URL to PDF in the REST API
var pdf = _renderer.RenderUrlAsPdf(url);
return pdf.BinaryData;
}
}
using IronPdf;
public class PdfService : IPdfService
{
private readonly ChromePdfRenderer _renderer;
public PdfService()
{
_renderer = new ChromePdfRenderer();
// Configure rendering options for optimal PDF generation in .NET
_renderer.RenderingOptions.MarginTop = 20;
_renderer.RenderingOptions.MarginBottom = 20;
_renderer.RenderingOptions.PrintHtmlBackgrounds = true;
}
public byte[] GeneratePdfFromHtml(string htmlContent)
{
// Generate PDF from HTML using the .NET PDF API
var pdf = _renderer.RenderHtmlAsPdf(htmlContent);
return pdf.BinaryData;
}
public byte[] GeneratePdfFromUrl(string url)
{
// Convert URL to PDF in the REST API
var pdf = _renderer.RenderUrlAsPdf(url);
return pdf.BinaryData;
}
}
Imports IronPdf
Public Class PdfService
Implements IPdfService
Private ReadOnly _renderer As ChromePdfRenderer
Public Sub New()
_renderer = New ChromePdfRenderer()
' Configure rendering options for optimal PDF generation in .NET
_renderer.RenderingOptions.MarginTop = 20
_renderer.RenderingOptions.MarginBottom = 20
_renderer.RenderingOptions.PrintHtmlBackgrounds = True
End Sub
Public Function GeneratePdfFromHtml(htmlContent As String) As Byte()
' Generate PDF from HTML using the .NET PDF API
Dim pdf = _renderer.RenderHtmlAsPdf(htmlContent)
Return pdf.BinaryData
End Function
Public Function GeneratePdfFromUrl(url As String) As Byte()
' Convert URL to PDF in the REST API
Dim pdf = _renderer.RenderUrlAsPdf(url)
Return pdf.BinaryData
End Function
End Class
El PdfService maneja la conversión de HTML a PDF. Utilizando ChromePdfRenderer de IronPDF, esta clase configura valores predeterminados como márgenes de página y representación de fondo para obtener resultados profesionales. Para configuraciones de renderizado avanzadas, explore las opciones de renderizado de IronPDF .
Cuando el controlador pasa HTML sin procesar, el servicio lo convierte en un PDF de alta calidad y devuelve los datos de bytes para descargar. También convierte páginas web enteras directamente en archivos PDF mediante la conversión de URL a PDF .
¿Cómo creo el controlador?
Ahora crea el controlador para tu API. Esto proporciona un punto final que genera archivos PDF a partir de HTML y le permite descargar y guardar documentos PDF en su sistema.
// Controllers/PdfController.cs
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class PdfController : ControllerBase
{
private readonly IPdfService _pdfService;
public PdfController(IPdfService pdfService)
{
_pdfService = pdfService;
}
[HttpPost("html-to-pdf")]
public IActionResult ConvertHtmlToPdf([FromBody] HtmlRequest request)
{
try
{
var pdfBytes = _pdfService.GeneratePdfFromHtml(request.HtmlContent);
// Return as downloadable file
return File(pdfBytes, "application/pdf", "document.pdf");
}
catch (Exception ex)
{
return BadRequest($"Error generating PDF: {ex.Message}");
}
}
}
// Controllers/PdfController.cs
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class PdfController : ControllerBase
{
private readonly IPdfService _pdfService;
public PdfController(IPdfService pdfService)
{
_pdfService = pdfService;
}
[HttpPost("html-to-pdf")]
public IActionResult ConvertHtmlToPdf([FromBody] HtmlRequest request)
{
try
{
var pdfBytes = _pdfService.GeneratePdfFromHtml(request.HtmlContent);
// Return as downloadable file
return File(pdfBytes, "application/pdf", "document.pdf");
}
catch (Exception ex)
{
return BadRequest($"Error generating PDF: {ex.Message}");
}
}
}
Imports Microsoft.AspNetCore.Mvc
<ApiController>
<Route("api/[controller]")>
Public Class PdfController
Inherits ControllerBase
Private ReadOnly _pdfService As IPdfService
Public Sub New(pdfService As IPdfService)
_pdfService = pdfService
End Sub
<HttpPost("html-to-pdf")>
Public Function ConvertHtmlToPdf(<FromBody> request As HtmlRequest) As IActionResult
Try
Dim pdfBytes = _pdfService.GeneratePdfFromHtml(request.HtmlContent)
' Return as downloadable file
Return File(pdfBytes, "application/pdf", "document.pdf")
Catch ex As Exception
Return BadRequest($"Error generating PDF: {ex.Message}")
End Try
End Function
End Class
Luego, en el archivo HtmlRequest.cs, agregue esto:
// Models/HtmlRequest.cs
public class HtmlRequest
{
public string HtmlContent { get; set; }
public string FileName { get; set; } = "document.pdf";
}
// Models/HtmlRequest.cs
public class HtmlRequest
{
public string HtmlContent { get; set; }
public string FileName { get; set; } = "document.pdf";
}
' Models/HtmlRequest.vb
Public Class HtmlRequest
Public Property HtmlContent As String
Public Property FileName As String = "document.pdf"
End Class
Esto configura un punto final de API que convierte HTML en un PDF descargable. Cuando alguien envía HTML a api/pdf/html-to-pdf, el PdfController delega la conversión al servicio.
Una vez creado, el controlador devuelve el PDF como archivo descargable. La solicitud utiliza el modelo HtmlRequest, que contiene el HTML y un nombre de archivo opcional. Esto hace que sea fácil para los clientes enviar HTML y recibir un PDF pulido.
¿Cómo registro servicios?
Actualice su Program.cs para registrar el servicio PDF:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Register PDF service
builder.Services.AddSingleton<IPdfService, PdfService>();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.MapControllers();
app.Run();
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Register PDF service
builder.Services.AddSingleton<IPdfService, PdfService>();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.MapControllers();
app.Run();
Imports Microsoft.AspNetCore.Builder
Imports Microsoft.Extensions.DependencyInjection
Dim builder = WebApplication.CreateBuilder(args)
builder.Services.AddControllers()
builder.Services.AddEndpointsApiExplorer()
builder.Services.AddSwaggerGen()
' Register PDF service
builder.Services.AddSingleton(Of IPdfService, PdfService)()
Dim app = builder.Build()
If app.Environment.IsDevelopment() Then
app.UseSwagger()
app.UseSwaggerUI()
End If
app.UseHttpsRedirection()
app.MapControllers()
app.Run()
¿Cómo manejar diferentes tipos de respuesta?
Su API debería soportar diferentes formas de devolver PDFs en función de las necesidades del cliente:
[HttpPost("generate")]
public IActionResult GeneratePdf([FromBody] PdfRequest request)
{
var pdfBytes = _pdfService.GeneratePdfFromHtml(request.HtmlContent);
switch (request.ResponseType?.ToLower())
{
case "base64":
return Ok(new
{
data = Convert.ToBase64String(pdfBytes),
filename = request.FileName
});
case "inline":
return File(pdfBytes, "application/pdf");
default: // download
return File(pdfBytes, "application/pdf", request.FileName);
}
}
[HttpPost("generate")]
public IActionResult GeneratePdf([FromBody] PdfRequest request)
{
var pdfBytes = _pdfService.GeneratePdfFromHtml(request.HtmlContent);
switch (request.ResponseType?.ToLower())
{
case "base64":
return Ok(new
{
data = Convert.ToBase64String(pdfBytes),
filename = request.FileName
});
case "inline":
return File(pdfBytes, "application/pdf");
default: // download
return File(pdfBytes, "application/pdf", request.FileName);
}
}
Imports Microsoft.AspNetCore.Mvc
<HttpPost("generate")>
Public Function GeneratePdf(<FromBody> request As PdfRequest) As IActionResult
Dim pdfBytes = _pdfService.GeneratePdfFromHtml(request.HtmlContent)
Select Case request.ResponseType?.ToLower()
Case "base64"
Return Ok(New With {
.data = Convert.ToBase64String(pdfBytes),
.filename = request.FileName
})
Case "inline"
Return File(pdfBytes, "application/pdf")
Case Else ' download
Return File(pdfBytes, "application/pdf", request.FileName)
End Select
End Function
Esto agrega un punto final de generación de PDF flexible. En lugar de forzar las descargas, el método GeneratePdf permite a los clientes elegir cómo reciben los resultados: como una descarga, en línea en el navegador o codificados en Base64 para el uso de la API.
El modelo PdfRequest extiende HtmlRequest con una opción ResponseType. Esto permite a los usuarios controlar la entrega de PDF, lo que aumenta la versatilidad de la API. Para gestionar archivos PDF en memoria sin acceso al sistema de archivos, consulte la documentación de flujo de memoria de IronPDF .
Cuando ejecutamos nuestro programa, veremos esta salida en Swagger:

¿Cómo implementar operaciones PDF comunes?
Ampliemos nuestro servicio para manejar varios escenarios de generación de PDF:
¿Cómo convierto URL a PDF?
[HttpPost("url-to-pdf")]
public async Task<IActionResult> ConvertUrlToPdf([FromBody] UrlRequest request)
{
try
{
var pdfBytes = await Task.Run(() =>
_pdfService.GeneratePdfFromUrl(request.Url));
return File(pdfBytes, "application/pdf",
$"{request.FileName ?? "website"}.pdf");
}
catch (Exception ex)
{
return BadRequest($"Failed to convert URL: {ex.Message}");
}
}
public class UrlRequest
{
public string Url { get; set; }
public string FileName { get; set; }
}
[HttpPost("url-to-pdf")]
public async Task<IActionResult> ConvertUrlToPdf([FromBody] UrlRequest request)
{
try
{
var pdfBytes = await Task.Run(() =>
_pdfService.GeneratePdfFromUrl(request.Url));
return File(pdfBytes, "application/pdf",
$"{request.FileName ?? "website"}.pdf");
}
catch (Exception ex)
{
return BadRequest($"Failed to convert URL: {ex.Message}");
}
}
public class UrlRequest
{
public string Url { get; set; }
public string FileName { get; set; }
}
Imports System.Threading.Tasks
Imports Microsoft.AspNetCore.Mvc
<HttpPost("url-to-pdf")>
Public Async Function ConvertUrlToPdf(<FromBody> request As UrlRequest) As Task(Of IActionResult)
Try
Dim pdfBytes = Await Task.Run(Function() _pdfService.GeneratePdfFromUrl(request.Url))
Return File(pdfBytes, "application/pdf", $"{If(request.FileName, "website")}.pdf")
Catch ex As Exception
Return BadRequest($"Failed to convert URL: {ex.Message}")
End Try
End Function
Public Class UrlRequest
Public Property Url As String
Public Property FileName As String
End Class
Este punto final convierte las URL en archivos PDF descargables. Cuando una solicitud POST llega a /api/pdf/url-to-pdf, el controlador usa _pdfService para convertir la URL en bytes PDF en segundo plano y luego los devuelve para su descarga. Si la conversión falla, responde con un mensaje de error claro. Para sitios web con autenticación, consulte la documentación de inicio de sesión de IronPDF .
Intentemos usar la URL "https://www.apple.com/nz " y probamos la solicitud POST. A continuación, el resultado que obtuvimos:
¿Qué aspecto tiene el resultado?

¿Cómo agrego marcas de agua personalizadas?
public byte[] AddWatermarkFromFile(string filePath, string watermarkText)
{
// Load PDF directly from file
var pdf = PdfDocument.FromFile(filePath);
pdf.ApplyWatermark(
$"<h1 style='color:red;font-size:72px;'>{watermarkText}</h1>",
75,
IronPdf.Editing.VerticalAlignment.Middle,
IronPdf.Editing.HorizontalAlignment.Center
);
return pdf.BinaryData;
}
public byte[] AddWatermarkFromFile(string filePath, string watermarkText)
{
// Load PDF directly from file
var pdf = PdfDocument.FromFile(filePath);
pdf.ApplyWatermark(
$"<h1 style='color:red;font-size:72px;'>{watermarkText}</h1>",
75,
IronPdf.Editing.VerticalAlignment.Middle,
IronPdf.Editing.HorizontalAlignment.Center
);
return pdf.BinaryData;
}
Imports IronPdf
Public Function AddWatermarkFromFile(filePath As String, watermarkText As String) As Byte()
' Load PDF directly from file
Dim pdf = PdfDocument.FromFile(filePath)
pdf.ApplyWatermark(
$"<h1 style='color:red;font-size:72px;'>{watermarkText}</h1>",
75,
IronPdf.Editing.VerticalAlignment.Middle,
IronPdf.Editing.HorizontalAlignment.Center
)
Return pdf.BinaryData
End Function
Esto carga manualmente un archivo local para realizar pruebas. Puede ajustar esto para que su API de PDF genere un PDF y luego aplique marcas de agua personalizadas fácilmente. Para conocer opciones avanzadas de marca de agua, incluidas marcas de agua de imágenes y posicionamiento personalizado, consulte la guía de marca de agua .
¿Cómo se ve la salida de la marca de agua?

¿Cómo agregar datos dinámicos con plantillas?
Para aplicaciones del mundo real, a menudo necesitará generar PDFs a partir de plantillas con datos dinámicos:
[HttpPost("from-template")]
public IActionResult GenerateFromTemplate([FromBody] TemplateRequest request)
{
// Simple template replacement
var html = request.Template;
foreach (var item in request.Data)
{
html = html.Replace($"{{{{{item.Key}}}}}", item.Value);
}
var pdfBytes = _pdfService.GeneratePdfFromHtml(html);
return File(pdfBytes, "application/pdf", request.FileName);
}
public class TemplateRequest
{
public string Template { get; set; }
public Dictionary<string, string> Data { get; set; }
public string FileName { get; set; } = "document.pdf";
}
[HttpPost("from-template")]
public IActionResult GenerateFromTemplate([FromBody] TemplateRequest request)
{
// Simple template replacement
var html = request.Template;
foreach (var item in request.Data)
{
html = html.Replace($"{{{{{item.Key}}}}}", item.Value);
}
var pdfBytes = _pdfService.GeneratePdfFromHtml(html);
return File(pdfBytes, "application/pdf", request.FileName);
}
public class TemplateRequest
{
public string Template { get; set; }
public Dictionary<string, string> Data { get; set; }
public string FileName { get; set; } = "document.pdf";
}
Imports Microsoft.AspNetCore.Mvc
<HttpPost("from-template")>
Public Function GenerateFromTemplate(<FromBody> request As TemplateRequest) As IActionResult
' Simple template replacement
Dim html As String = request.Template
For Each item In request.Data
html = html.Replace($"{{{{{item.Key}}}}}", item.Value)
Next
Dim pdfBytes As Byte() = _pdfService.GeneratePdfFromHtml(html)
Return File(pdfBytes, "application/pdf", request.FileName)
End Function
Public Class TemplateRequest
Public Property Template As String
Public Property Data As Dictionary(Of String, String)
Public Property FileName As String = "document.pdf"
End Class
Para escenarios de plantillas avanzados con Razor, Handlebars u otros motores, consulte la documentación de HTML a PDF de IronPDF . También puede explorar la conversión de CSHTML a PDF para aplicaciones MVC y Razor a PDF para aplicaciones Blazor. Para la representación sin interfaz gráfica de Razor , consulte la guía CSHTML sin interfaz gráfica .
¿Cómo optimizar el rendimiento?
Al construir una API de PDF de producción, el rendimiento es crucial. Aquí hay estrategias clave de optimización:
¿Por qué utilizar operaciones asincrónicas?
Utilice codificación asincrónica cuando sus proyectos involucren operaciones de E/S. Esto ayuda especialmente cuando el contenido PDF proviene de recursos externos como:
- Descarga de páginas HTML (
RenderUrlAsPdf) - Recuperando imágenes, CSS o fuentes a través de HTTP
- Leyendo/escribiendo archivos en disco o almacenamiento en la nube
Estas operaciones pueden bloquear subprocesos, pero async evita que los subprocesos de API permanezcan inactivos. Para conocer patrones completos de generación de PDF asincrónicos, consulte la guía de generación de PDF asincrónicos .
Ejemplo:
public async Task<byte[]> GeneratePdfFromHtmlAsync(string htmlContent)
{
return await Task.Run(() =>
{
var pdf = _renderer.RenderHtmlAsPdf(htmlContent);
return pdf.BinaryData;
});
}
public async Task<byte[]> GeneratePdfFromHtmlAsync(string htmlContent)
{
return await Task.Run(() =>
{
var pdf = _renderer.RenderHtmlAsPdf(htmlContent);
return pdf.BinaryData;
});
}
Imports System.Threading.Tasks
Public Async Function GeneratePdfFromHtmlAsync(htmlContent As String) As Task(Of Byte())
Return Await Task.Run(Function()
Dim pdf = _renderer.RenderHtmlAsPdf(htmlContent)
Return pdf.BinaryData
End Function)
End Function
Para escenarios de generación de PDF en paralelo, explore técnicas de procesamiento paralelo y de subprocesos múltiples .
¿Qué opciones de renderizado debo configurar?
Configure IronPDF para un rendimiento óptimo:
_renderer.RenderingOptions.EnableJavaScript = false; // If JS not needed
_renderer.RenderingOptions.CssMediaType = PdfCssMediaType.Print;
_renderer.RenderingOptions.RenderDelay = 0; // Remove if no JS
_renderer.RenderingOptions.Timeout = 30; // Set reasonable timeout
_renderer.RenderingOptions.EnableJavaScript = false; // If JS not needed
_renderer.RenderingOptions.CssMediaType = PdfCssMediaType.Print;
_renderer.RenderingOptions.RenderDelay = 0; // Remove if no JS
_renderer.RenderingOptions.Timeout = 30; // Set reasonable timeout
Para obtener opciones de configuración de renderizado completas, incluidas las configuraciones de la ventana gráfica , los tamaños de papel personalizados y la orientación de la página , consulte la documentación de opciones de renderizado .
¿Cómo proteger su API PDF?
La seguridad es esencial para cualquier API de producción. Aquí hay un enfoque simple de autenticación con clave API:
// Middleware/ApiKeyMiddleware.cs
public class ApiKeyMiddleware
{
private readonly RequestDelegate _next;
private const string ApiKeyHeader = "X-API-Key";
public ApiKeyMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
if (!context.Request.Headers.TryGetValue(ApiKeyHeader, out var apiKey))
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("API Key required");
return;
}
// Validate API key (in production, check against database)
var validApiKey = context.RequestServices
.GetRequiredService<IConfiguration>()["ApiKey"];
if (apiKey != validApiKey)
{
context.Response.StatusCode = 403;
await context.Response.WriteAsync("Invalid API Key");
return;
}
await _next(context);
}
}
// In Program.cs
app.UseMiddleware<ApiKeyMiddleware>();
// Middleware/ApiKeyMiddleware.cs
public class ApiKeyMiddleware
{
private readonly RequestDelegate _next;
private const string ApiKeyHeader = "X-API-Key";
public ApiKeyMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
if (!context.Request.Headers.TryGetValue(ApiKeyHeader, out var apiKey))
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("API Key required");
return;
}
// Validate API key (in production, check against database)
var validApiKey = context.RequestServices
.GetRequiredService<IConfiguration>()["ApiKey"];
if (apiKey != validApiKey)
{
context.Response.StatusCode = 403;
await context.Response.WriteAsync("Invalid API Key");
return;
}
await _next(context);
}
}
// In Program.cs
app.UseMiddleware<ApiKeyMiddleware>();
Imports Microsoft.AspNetCore.Http
Imports Microsoft.Extensions.Configuration
Imports System.Threading.Tasks
' Middleware/ApiKeyMiddleware.vb
Public Class ApiKeyMiddleware
Private ReadOnly _next As RequestDelegate
Private Const ApiKeyHeader As String = "X-API-Key"
Public Sub New(next As RequestDelegate)
_next = next
End Sub
Public Async Function InvokeAsync(context As HttpContext) As Task
Dim apiKey As String = Nothing
If Not context.Request.Headers.TryGetValue(ApiKeyHeader, apiKey) Then
context.Response.StatusCode = 401
Await context.Response.WriteAsync("API Key required")
Return
End If
' Validate API key (in production, check against database)
Dim validApiKey As String = context.RequestServices.GetRequiredService(Of IConfiguration)()("ApiKey")
If apiKey <> validApiKey Then
context.Response.StatusCode = 403
Await context.Response.WriteAsync("Invalid API Key")
Return
End If
Await _next(context)
End Function
End Class
' In Program.vb
app.UseMiddleware(Of ApiKeyMiddleware)()
Para escenarios de autenticación avanzada, considere:
- Autenticación JWT : estándar de la industria para la autenticación de API
- OAuth 2.0 - Para integraciones de terceros
- Integración AD de Azure - Autenticación empresarial
- Limitación de Tasa API - Prevenir abusos y garantizar un uso justo
- Encabezados HTTP : configuración de encabezados personalizados para mayor seguridad
Para la seguridad específica de PDF, implemente protección con contraseña , firmas digitales y desinfección de PDF para eliminar contenido potencialmente malicioso.
¿Cómo crear una API de generación de facturas en el mundo real?
Construyamos un punto final de generación de facturas práctico que demuestre una implementación completa. Este ejemplo muestra cómo una API de PDF .NET de producción genera facturas profesionales con datos dinámicos.
Primero, crea un nuevo archivo en tu carpeta Modelos. Aquí, he llamado al mío Invoice.cs. Luego agrega el siguiente código:
public class Invoice
{
public string InvoiceNumber { get; set; }
public DateTime Date { get; set; }
public string CustomerName { get; set; }
public string CustomerAddress { get; set; }
public List<InvoiceItem> Items { get; set; }
public decimal Tax { get; set; }
}
public class InvoiceItem
{
public string Description { get; set; }
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
public decimal Total => Quantity * UnitPrice;
}
public class Invoice
{
public string InvoiceNumber { get; set; }
public DateTime Date { get; set; }
public string CustomerName { get; set; }
public string CustomerAddress { get; set; }
public List<InvoiceItem> Items { get; set; }
public decimal Tax { get; set; }
}
public class InvoiceItem
{
public string Description { get; set; }
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
public decimal Total => Quantity * UnitPrice;
}
Public Class Invoice
Public Property InvoiceNumber As String
Public Property [Date] As DateTime
Public Property CustomerName As String
Public Property CustomerAddress As String
Public Property Items As List(Of InvoiceItem)
Public Property Tax As Decimal
End Class
Public Class InvoiceItem
Public Property Description As String
Public Property Quantity As Integer
Public Property UnitPrice As Decimal
Public ReadOnly Property Total As Decimal
Get
Return Quantity * UnitPrice
End Get
End Property
End Class
A continuación, cree un nuevo archivo de servicio para el generador de facturas. En su carpeta de Servicios, añada el siguiente código. Creé un archivo llamado InvoiceService.cs. Este código maneja el estilo y el diseño de su factura PDF:
public class InvoiceService
{
private readonly ChromePdfRenderer _renderer;
public InvoiceService()
{
_renderer = new ChromePdfRenderer();
_renderer.RenderingOptions.MarginTop = 10;
_renderer.RenderingOptions.MarginBottom = 10;
_renderer.RenderingOptions.PrintHtmlBackgrounds = true;
}
public byte[] GenerateInvoice(Invoice invoice)
{
var html = BuildInvoiceHtml(invoice);
// Add footer with page numbers
_renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
MaxHeight = 15,
HtmlFragment = "<center><i>{page} of {total-pages}</i></center>",
DrawDividerLine = true
};
var pdf = _renderer.RenderHtmlAsPdf(html);
return pdf.BinaryData;
}
private string BuildInvoiceHtml(Invoice invoice)
{
var subtotal = invoice.Items.Sum(i => i.Total);
var taxAmount = subtotal * (invoice.Tax / 100);
var total = subtotal + taxAmount;
var itemsHtml = string.Join("", invoice.Items.Select(item =>
$@"<tr>
<td>{item.Description}</td>
<td class='text-center'>{item.Quantity}</td>
<td class='text-right'>${item.UnitPrice:F2}</td>
<td class='text-right'>${item.Total:F2}</td>
</tr>"));
return $@"
<!DOCTYPE html>
<html>
<head>
<style>
body {{ font-family: Arial, sans-serif; }}
.invoice-header {{
background-color: #f8f9fa;
padding: 20px;
margin-bottom: 20px;
}}
table {{
width: 100%;
border-collapse: collapse;
}}
th, td {{
padding: 10px;
border-bottom: 1px solid #ddd;
}}
th {{
background-color: #007bff;
color: white;
}}
.text-right {{ text-align: right; }}
.text-center {{ text-align: center; }}
.total-section {{
margin-top: 20px;
text-align: right;
}}
</style>
</head>
<body>
<div class='invoice-header'>
<h1>Invoice #{invoice.InvoiceNumber}</h1>
<p>Date: {invoice.Date:yyyy-MM-dd}</p>
</div>
<div>
<h3>Bill To:</h3>
<p>{invoice.CustomerName}<br/>{invoice.CustomerAddress}</p>
</div>
<table>
<thead>
<tr>
<th>Description</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Total</th>
</tr>
</thead>
<tbody>
{itemsHtml}
</tbody>
</table>
<div class='total-section'>
<p>Subtotal: ${subtotal:F2}</p>
<p>Tax ({invoice.Tax}%): ${taxAmount:F2}</p>
<h3>Total: ${total:F2}</h3>
</div>
</body>
</html>";
}
}
public class InvoiceService
{
private readonly ChromePdfRenderer _renderer;
public InvoiceService()
{
_renderer = new ChromePdfRenderer();
_renderer.RenderingOptions.MarginTop = 10;
_renderer.RenderingOptions.MarginBottom = 10;
_renderer.RenderingOptions.PrintHtmlBackgrounds = true;
}
public byte[] GenerateInvoice(Invoice invoice)
{
var html = BuildInvoiceHtml(invoice);
// Add footer with page numbers
_renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
MaxHeight = 15,
HtmlFragment = "<center><i>{page} of {total-pages}</i></center>",
DrawDividerLine = true
};
var pdf = _renderer.RenderHtmlAsPdf(html);
return pdf.BinaryData;
}
private string BuildInvoiceHtml(Invoice invoice)
{
var subtotal = invoice.Items.Sum(i => i.Total);
var taxAmount = subtotal * (invoice.Tax / 100);
var total = subtotal + taxAmount;
var itemsHtml = string.Join("", invoice.Items.Select(item =>
$@"<tr>
<td>{item.Description}</td>
<td class='text-center'>{item.Quantity}</td>
<td class='text-right'>${item.UnitPrice:F2}</td>
<td class='text-right'>${item.Total:F2}</td>
</tr>"));
return $@"
<!DOCTYPE html>
<html>
<head>
<style>
body {{ font-family: Arial, sans-serif; }}
.invoice-header {{
background-color: #f8f9fa;
padding: 20px;
margin-bottom: 20px;
}}
table {{
width: 100%;
border-collapse: collapse;
}}
th, td {{
padding: 10px;
border-bottom: 1px solid #ddd;
}}
th {{
background-color: #007bff;
color: white;
}}
.text-right {{ text-align: right; }}
.text-center {{ text-align: center; }}
.total-section {{
margin-top: 20px;
text-align: right;
}}
</style>
</head>
<body>
<div class='invoice-header'>
<h1>Invoice #{invoice.InvoiceNumber}</h1>
<p>Date: {invoice.Date:yyyy-MM-dd}</p>
</div>
<div>
<h3>Bill To:</h3>
<p>{invoice.CustomerName}<br/>{invoice.CustomerAddress}</p>
</div>
<table>
<thead>
<tr>
<th>Description</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Total</th>
</tr>
</thead>
<tbody>
{itemsHtml}
</tbody>
</table>
<div class='total-section'>
<p>Subtotal: ${subtotal:F2}</p>
<p>Tax ({invoice.Tax}%): ${taxAmount:F2}</p>
<h3>Total: ${total:F2}</h3>
</div>
</body>
</html>";
}
}
Imports System
Imports System.Linq
Public Class InvoiceService
Private ReadOnly _renderer As ChromePdfRenderer
Public Sub New()
_renderer = New ChromePdfRenderer()
_renderer.RenderingOptions.MarginTop = 10
_renderer.RenderingOptions.MarginBottom = 10
_renderer.RenderingOptions.PrintHtmlBackgrounds = True
End Sub
Public Function GenerateInvoice(invoice As Invoice) As Byte()
Dim html = BuildInvoiceHtml(invoice)
' Add footer with page numbers
_renderer.RenderingOptions.HtmlFooter = New HtmlHeaderFooter With {
.MaxHeight = 15,
.HtmlFragment = "<center><i>{page} of {total-pages}</i></center>",
.DrawDividerLine = True
}
Dim pdf = _renderer.RenderHtmlAsPdf(html)
Return pdf.BinaryData
End Function
Private Function BuildInvoiceHtml(invoice As Invoice) As String
Dim subtotal = invoice.Items.Sum(Function(i) i.Total)
Dim taxAmount = subtotal * (invoice.Tax / 100)
Dim total = subtotal + taxAmount
Dim itemsHtml = String.Join("", invoice.Items.Select(Function(item) _
$"<tr>
<td>{item.Description}</td>
<td class='text-center'>{item.Quantity}</td>
<td class='text-right'>${item.UnitPrice:F2}</td>
<td class='text-right'>${item.Total:F2}</td>
</tr>"))
Return $"
<!DOCTYPE html>
<html>
<head>
<style>
body {{ font-family: Arial, sans-serif; }}
.invoice-header {{
background-color: #f8f9fa;
padding: 20px;
margin-bottom: 20px;
}}
table {{
width: 100%;
border-collapse: collapse;
}}
th, td {{
padding: 10px;
border-bottom: 1px solid #ddd;
}}
th {{
background-color: #007bff;
color: white;
}}
.text-right {{ text-align: right; }}
.text-center {{ text-align: center; }}
.total-section {{
margin-top: 20px;
text-align: right;
}}
</style>
</head>
<body>
<div class='invoice-header'>
<h1>Invoice #{invoice.InvoiceNumber}</h1>
<p>Date: {invoice.Date:yyyy-MM-dd}</p>
</div>
<div>
<h3>Bill To:</h3>
<p>{invoice.CustomerName}<br/>{invoice.CustomerAddress}</p>
</div>
<table>
<thead>
<tr>
<th>Description</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Total</th>
</tr>
</thead>
<tbody>
{itemsHtml}
</tbody>
</table>
<div class='total-section'>
<p>Subtotal: ${subtotal:F2}</p>
<p>Tax ({invoice.Tax}%): ${taxAmount:F2}</p>
<h3>Total: ${total:F2}</h3>
</div>
</body>
</html>"
End Function
End Class
Por último, crea un nuevo Controlador para acceder y crear facturas usando la API:
[ApiController]
[Route("api/[controller]")]
public class InvoiceController : ControllerBase
{
private readonly InvoiceService _invoiceService;
public InvoiceController(InvoiceService invoiceService)
{
_invoiceService = invoiceService;
}
[HttpPost("generate")]
public IActionResult GenerateInvoice([FromBody] Invoice invoice)
{
try
{
var pdfBytes = _invoiceService.GenerateInvoice(invoice);
var fileName = $"Invoice_{invoice.InvoiceNumber}.pdf";
return File(pdfBytes, "application/pdf", fileName);
}
catch (Exception ex)
{
return StatusCode(500, $"Error generating invoice: {ex.Message}");
}
}
}
[ApiController]
[Route("api/[controller]")]
public class InvoiceController : ControllerBase
{
private readonly InvoiceService _invoiceService;
public InvoiceController(InvoiceService invoiceService)
{
_invoiceService = invoiceService;
}
[HttpPost("generate")]
public IActionResult GenerateInvoice([FromBody] Invoice invoice)
{
try
{
var pdfBytes = _invoiceService.GenerateInvoice(invoice);
var fileName = $"Invoice_{invoice.InvoiceNumber}.pdf";
return File(pdfBytes, "application/pdf", fileName);
}
catch (Exception ex)
{
return StatusCode(500, $"Error generating invoice: {ex.Message}");
}
}
}
Imports Microsoft.AspNetCore.Mvc
<ApiController>
<Route("api/[controller]")>
Public Class InvoiceController
Inherits ControllerBase
Private ReadOnly _invoiceService As InvoiceService
Public Sub New(invoiceService As InvoiceService)
_invoiceService = invoiceService
End Sub
<HttpPost("generate")>
Public Function GenerateInvoice(<FromBody> invoice As Invoice) As IActionResult
Try
Dim pdfBytes = _invoiceService.GenerateInvoice(invoice)
Dim fileName = $"Invoice_{invoice.InvoiceNumber}.pdf"
Return File(pdfBytes, "application/pdf", fileName)
Catch ex As Exception
Return StatusCode(500, $"Error generating invoice: {ex.Message}")
End Try
End Function
End Class
Para obtener funciones de facturación avanzadas, considere agregar códigos de barras , códigos QR , números de página y encabezados/pies de página personalizados . También puede implementar la compatibilidad con PDF/A para el archivo a largo plazo o integrarlo con flujos de trabajo de firma electrónica .
¿Cómo se ve la salida de la factura?

¿Cuáles son las consideraciones a tener en cuenta en la implementación de contenedores?
Aunque este tutorial se enfoca en el desarrollo local, aquí hay una breve descripción de cómo contenerizar su API de PDF:
¿Cómo creo un Dockerfile básico?
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["PdfApiService.csproj", "."]
RUN dotnet restore
COPY . .
RUN dotnet build -c Release -o /app/build
FROM build AS publish
RUN dotnet publish -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
# IronPDF requires additional dependencies on Linux
RUN apt-get update && apt-get install -y \
libgdiplus \
libc6-dev \
libx11-dev \
&& rm -rf /var/lib/apt/lists/*
ENTRYPOINT ["dotnet", "PdfApiService.dll"]
Para guías de despliegue detalladas para su API de PDF de .NET, vea:
- Documentación de Docker de IronPDF - Guía completa de contenerización
- Despliegue de IronPDF en Azure - Funciones de Azure y App Service
- Despliegue de IronPDF en AWS - Despliegue en Lambda y EC2
- Configuración de IronPDF en Linux - Configuración específica de Linux
- Ejecución como contenedor remoto - Contenedorización de IronPDF Engine
- Motor nativo vs. remoto : opciones de arquitectura de implementación
¿Cuáles son las mejores prácticas de manejo de errores?
Para programas tolerantes a fallos, implemente un controlador de errores global para obtener respuestas de error consistentes:
// Middleware/ErrorHandlingMiddleware.cs
public class ErrorHandlingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ErrorHandlingMiddleware> _logger;
public ErrorHandlingMiddleware(RequestDelegate next, ILogger<ErrorHandlingMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred processing request {Path}", context.Request.Path);
await HandleExceptionAsync(context, ex);
}
}
private static async Task HandleExceptionAsync(HttpContext context, Exception ex)
{
context.Response.ContentType = "application/json";
context.Response.StatusCode = ex switch
{
ArgumentNullException => 400,
UnauthorizedAccessException => 401,
_ => 500
};
var response = new
{
error = "An error occurred processing your request",
message = ex.Message,
statusCode = context.Response.StatusCode
};
await context.Response.WriteAsync(JsonSerializer.Serialize(response));
}
}
// Middleware/ErrorHandlingMiddleware.cs
public class ErrorHandlingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ErrorHandlingMiddleware> _logger;
public ErrorHandlingMiddleware(RequestDelegate next, ILogger<ErrorHandlingMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred processing request {Path}", context.Request.Path);
await HandleExceptionAsync(context, ex);
}
}
private static async Task HandleExceptionAsync(HttpContext context, Exception ex)
{
context.Response.ContentType = "application/json";
context.Response.StatusCode = ex switch
{
ArgumentNullException => 400,
UnauthorizedAccessException => 401,
_ => 500
};
var response = new
{
error = "An error occurred processing your request",
message = ex.Message,
statusCode = context.Response.StatusCode
};
await context.Response.WriteAsync(JsonSerializer.Serialize(response));
}
}
' Middleware/ErrorHandlingMiddleware.vb
Public Class ErrorHandlingMiddleware
Private ReadOnly _next As RequestDelegate
Private ReadOnly _logger As ILogger(Of ErrorHandlingMiddleware)
Public Sub New(ByVal [next] As RequestDelegate, ByVal logger As ILogger(Of ErrorHandlingMiddleware))
_next = [next]
_logger = logger
End Sub
Public Async Function InvokeAsync(ByVal context As HttpContext) As Task
Try
Await _next(context)
Catch ex As Exception
_logger.LogError(ex, "An error occurred processing request {Path}", context.Request.Path)
Await HandleExceptionAsync(context, ex)
End Try
End Function
Private Shared Async Function HandleExceptionAsync(ByVal context As HttpContext, ByVal ex As Exception) As Task
context.Response.ContentType = "application/json"
context.Response.StatusCode = If(TypeOf ex Is ArgumentNullException, 400, If(TypeOf ex Is UnauthorizedAccessException, 401, 500))
Dim response = New With {
.error = "An error occurred processing your request",
.message = ex.Message,
.statusCode = context.Response.StatusCode
}
Await context.Response.WriteAsync(JsonSerializer.Serialize(response))
End Function
End Class
Para escenarios específicos de solución de problemas de IronPDF , consulte:
¿Está listo para crear su API de PDF .NET de producción?
Ahora ha creado una sólida API de PDF .NET utilizando ASP.NET Core e IronPDF que maneja varios escenarios de generación de documentos. Esta API REST proporciona una base sólida para operaciones centralizadas de PDF en sus aplicaciones.
Conclusiones clave:
- IronPDF facilita la generación de PDF en proyectos de API web con renderizado basado en Chrome .
- Edite fácilmente archivos PDF existentes con las herramientas de edición avanzadas de IronPDF.
- Los principios de diseño RESTful garantizan que la API PDF sea intuitiva y fácil de mantener.
- El tratamiento adecuado de los errores y las medidas de seguridad son esenciales para la producción.
- La optimización del rendimiento a través de operaciones asincrónicas y almacenamiento en caché mejora la escalabilidad.
- Soporte completo para aplicaciones de escritorio y web con soluciones de documentos escalables.
IronPDF permite a los desarrolladores crear archivos PDF, guardar archivos PDF y convertir HTML de manera eficiente, lo que lo convierte en la API de PDF esencial para las aplicaciones modernas de .NET Framework .
¿Cuáles son los próximos pasos?
¿Listo para implementar IronPDF en su API de PDF de producción para .NET? Aquí están sus próximas acciones:
- Inicie su prueba gratuita - Pruebe IronPDF con funcionalidad completa en su entorno de desarrollo.
- Explore las funciones avanzadas : consulte las firmas digitales , los formularios PDF , la conformidad con PDF/A , la gestión de metadatos y otras funciones avanzadas de PDF .
- Escale con confianza : revise las opciones de licencia para sus necesidades de API de producción, incluidas extensiones y actualizaciones .
¡Construya su API de PDF para .NET hoy y optimice la generación de documentos en todo su ecosistema de aplicaciones con IronPDF!
Preguntas Frecuentes
¿Para qué se utiliza IronPDF en las aplicaciones .NET?
IronPDF se utiliza para generar, manipular y convertir archivos PDF dentro de aplicaciones .NET, por lo que es ideal para crear servicios PDF centralizados.
¿Cómo puede integrarse IronPDF con ASP.NET Core?
IronPDF puede integrarse con ASP.NET Core instalando el paquete IronPDF NuGet, lo que permite crear un servicio centralizado de generación de PDF.
¿Cuáles son las principales características de IronPDF para la generación de PDF?
Entre las principales funciones de IronPDF se incluyen la conversión de HTML a PDF, la fusión y división de PDF, la adición de encabezados y pies de página y la extracción de texto e imágenes.
¿Puede IronPDF manejar diseños PDF complejos?
Sí, IronPDF puede manejar diseños PDF complejos gracias a su capacidad para convertir contenido HTML y CSS en documentos PDF renderizados con precisión.
¿Es posible personalizar la creación de PDF con IronPDF?
Sí, IronPDF permite la personalización en la creación de PDF, incluida la configuración del tamaño de página, los márgenes y la adición de marcas de agua o anotaciones.
¿IronPDF soporta características de seguridad para PDF?
IronPDF es compatible con funciones de seguridad de PDF como la protección por contraseña y el cifrado para proteger los documentos PDF generados.
¿Qué formatos puede convertir IronPDF en PDF?
IronPDF puede convertir varios formatos en PDF, incluidos HTML, URL y archivos ASPX, lo que lo hace versátil para diferentes casos de uso.
¿Cómo gestiona IronPDF la generación de PDF a gran escala?
IronPDF está optimizado para el rendimiento, lo que le permite gestionar eficazmente tareas de generación de PDF a gran escala dentro de aplicaciones .NET.
¿Puede usarse IronPDF en aplicaciones basadas en la nube?
Sí, IronPDF se puede utilizar en aplicaciones basadas en la nube y admite la implementación en plataformas como Azure y AWS para servicios de PDF escalables.
¿Qué versiones de .NET admite IronPDF?
IronPDF es compatible con varias versiones de .NET, incluidas .NET Core y .NET Framework, lo que garantiza la compatibilidad con una amplia gama de proyectos.


