Cómo migrar de Rotativa a IronPDF en C#
Migrar de Rotativaa IronPDF: Guía completa de migración a C
La migración de RotativaaIronPDFresuelve vulnerabilidades de seguridad críticas a la vez que moderniza el flujo de trabajo de generación de PDF. Esta guía proporciona una ruta de migración completa, paso a paso, que elimina la dependencia wkhtmltopdf abandonada, permite la compatibilidad con CSS y JavaScript modernos y proporciona compatibilidad entre plataformas más allá de ASP.NET MVC.
Por qué migrar de Rotativaa IronPDF
Entendiendo Rotativa
Rotativa ha sido durante mucho tiempo una opción popular entre los desarrolladores para generar archivos PDF en C#. Aprovecha la herramienta wkhtmltopdf para convertir contenido HTML a formato PDF. Rotativaes una biblioteca de código abierto diseñada específicamente para aplicaciones ASP.NET MVC. Sin embargo, aunque ha atraído a un público significativo, la dependencia de Rotativade una pila tecnológica obsoleta presenta retos que pueden no ser evidentes de inmediato para todos los desarrolladores.
En esencia, Rotativaproporciona una forma sencilla de integrar la generación de PDF en proyectos ASP.NET MVC, aprovechando wkhtmltopdf para sus funcionalidades de backend.
Aviso de seguridad crítico
Rotativa envuelve wkhtmltopdf, que tiene VULNERABILIDADES CRÍTICAS DE SEGURIDAD NO COMPLETADAS.
| Atributo | Valor |
|---|---|
| CVE ID | CVE-2022-35583 |
| Severity | CRÍTICO (9,8/10) |
| Vector de ataque | Red |
| Estado | NUNCA SERÁ PARCHEADO |
| Afectados | TODAS las versiones de Rotativa |
wkhtmltopdf fue oficialmente abandonado en diciembre de 2022. Los mantenedores declararon explícitamente que NO corregirán las vulnerabilidades de seguridad. Todas las aplicaciones que utilizan Rotativaestán permanentemente expuestas.
Cómo funciona el ataque
<!-- Attacker submits this content via your MVC model -->
<iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/"></iframe>
<img src="http://internal-database:5432/admin" /><!-- Attacker submits this content via your MVC model -->
<iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/"></iframe>
<img src="http://internal-database:5432/admin" />Impacto:
- Acceso a los puntos finales de metadatos de la nube de AWS/Azure/GCP
- Robo de datos y credenciales de API internas
- Escaneado de puertos de redes internas
- Exfiltrar configuración sensible
La crisis tecnológica
Rotativa envuelve wkhtmltopdf, que utiliza:
- Qt WebKit 4.8 (desde 2012)
- No es compatible con Flexbox
- No es compatible con CSS Grid
- Ejecución rota de JavaScript
- No es compatible con ES6+
Comparación entre Rotativae IronPDF
| Característica | Rotativa | IronPDF |
|---|---|---|
| Compatibilidad de proyectos | Sólo ASP.NET MVC | Cualquier tipo de proyecto .NET (MVC, Razor Pages, Blazor, etc.) |
| Mantenimiento | Abandonado | Mantenimiento activo |
| Seguridad | Vulnerable debido a las dependencias de wkhtmltopdf (CVE-2022-35583) | Actualizaciones periódicas y parches de seguridad |
| Representación HTML | WebKit obsoleto | Chromium moderno |
| CSS3 | Parcial | Soporte completo |
| Flexbox/Grid | No soportado | Soporte completo |
| JavaScript | Poco fiable | ES6+ completo |
| Páginas de Razor | No soportado | Soporte completo |
| Blazor | No soportado | Soporte completo |
| Manipulación de PDF | No disponible | Completo |
| Firmas digitales | No disponible | Completo |
| Cumplimiento de PDF/A | No disponible | Completo |
| Async/Await | Sólo sincrónico | Async completo |
| Código abierto | Sí, licencia MIT | No, Licencia comercial |
Para los equipos que planifican la adopción de .NET 10 y C# 14 hasta 2025 y 2026,IronPDFproporciona un moderno renderizado en Chromium y una compatibilidad multiplataforma que Rotativano puede ofrecer.
Antes de empezar
Prerrequisitos
- <Entorno .NET: .NET Framework 4.6.2+ o .NET Core 3.1+ / .NET 5/6/7/8/9+
- Acceso a NuGet: Capacidad para instalar paquetes NuGet
- Licencia IronPDF: Obtenga su clave de licencia en ironpdf.com
Cambios en el paquete NuGet
# Remove Rotativa
dotnet remove package Rotativa
dotnet remove package Rotativa.AspNetCore
# Install IronPDF
dotnet add package IronPdf# Remove Rotativa
dotnet remove package Rotativa
dotnet remove package Rotativa.AspNetCore
# Install IronPDF
dotnet add package IronPdfQuitar los binarios de wkhtmltopdf
Elimine estos archivos de su proyecto:
- <código>wkhtmltopdf.exe</código
- <código>wkhtmltox.dll</código
- Cualquier carpeta
Rotativa/
Estas son el origen de CVE-2022-35583.IronPDFno necesita binarios nativos.
Configuración de licencias
// Add in Program.cs or Startup.cs
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";// Add in Program.cs or Startup.cs
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";IRON VB CONVERTER ERROR developers@ironsoftware.comReferencia completa de la API
Cambios en el espacio de nombres
// Before: Rotativa
using Rotativa;
using Rotativa.Options;
using Rotativa.AspNetCore;
// After: IronPDF
using IronPdf;
using IronPdf.Rendering;// Before: Rotativa
using Rotativa;
using Rotativa.Options;
using Rotativa.AspNetCore;
// After: IronPDF
using IronPdf;
using IronPdf.Rendering;IRON VB CONVERTER ERROR developers@ironsoftware.comCore Class Mappings
| Clase Rotativa | Equivalente de IronPDF | Notas |
|---|---|---|
| <código>VerComoPdf</código | <código>ChromePdfRenderer</código | Renderizar HTML |
| <código>ActionAsPdf</código | <código>ChromePdfRenderer.RenderUrlAsPdf()</código | Renderizar URL |
| <código>UrlAsPdf</código | <código>ChromePdfRenderer.RenderUrlAsPdf()</código | Renderizar URL |
Orientación enum | PdfPaperOrientation enum | Orientación |
Tamaño enum | PdfPaperSize enum | Tamaño del papel |
Conversión de marcadores de posición
| Marcador de posición de Rotativa | Marcador de posición IronPDF |
|---|---|
| <código>[página]</código> | {page} |
[topage] | {total de páginas} |
| <código>[fecha]</código> | {fecha} |
| <código>[tiempo]</código> | {time} |
| <código>[título]</código> | {html-title} |
[sitepage] | {url} |
Ejemplos de migración de código
Ejemplo 1: Conversión de HTML a PDF
Antes (Rotativa):
// NuGet: Install-Package Rotativa.Core
using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using System.Threading.Tasks;
namespace RotativaExample
{
public class PdfController : Controller
{
public async Task<IActionResult> GeneratePdf()
{
var htmlContent = "<h1>Hello World</h1><p>This is a PDF document.</p>";
// Rotativarequires returning a ViewAsPdf result from MVC controller
return new ViewAsPdf()
{
ViewName = "PdfView",
PageSize = Rotativa.AspNetCore.Options.Size.A4
};
}
}
}// NuGet: Install-Package Rotativa.Core
using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using System.Threading.Tasks;
namespace RotativaExample
{
public class PdfController : Controller
{
public async Task<IActionResult> GeneratePdf()
{
var htmlContent = "<h1>Hello World</h1><p>This is a PDF document.</p>";
// Rotativarequires returning a ViewAsPdf result from MVC controller
return new ViewAsPdf()
{
ViewName = "PdfView",
PageSize = Rotativa.AspNetCore.Options.Size.A4
};
}
}
}IRON VB CONVERTER ERROR developers@ironsoftware.comDespués (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
namespace IronPdfExample
{
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
var htmlContent = "<h1>Hello World</h1><p>This is a PDF document.</p>";
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("output.pdf");
Console.WriteLine("PDF generated successfully!");
}
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using System;
namespace IronPdfExample
{
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
var htmlContent = "<h1>Hello World</h1><p>This is a PDF document.</p>";
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("output.pdf");
Console.WriteLine("PDF generated successfully!");
}
}
}IRON VB CONVERTER ERROR developers@ironsoftware.comEste ejemplo demuestra la diferencia arquitectónica fundamental. Rotativarequiere devolver un resultado <código>VerComoPdf</códigode una acción de controlador MVC, lo que le vincula al marco ASP.NET MVC. El patrón sólo funciona dentro del canal de solicitudes MVC y requiere una vista Razor para su representación.
IronPDF funciona en cualquier lugar: aplicaciones de consola, API web, Blazor, Razor Pages o cualquier tipo de proyecto .NET. Se llama a RenderHtmlAsPdf() con una cadena HTML y se guarda el resultado. No requiere controlador MVC, ni dependencia de vistas. Consulte la documentación HTML a PDF para ver ejemplos completos.
Ejemplo 2: Conversión de URL a PDF
Antes (Rotativa):
// NuGet: Install-Package Rotativa.Core
using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using System.Threading.Tasks;
namespace RotativaExample
{
public class UrlPdfController : Controller
{
public async Task<IActionResult> ConvertUrlToPdf()
{
// Rotativaworks within MVC framework and returns ActionResult
return new UrlAsPdf("https://www.example.com")
{
FileName = "webpage.pdf",
PageSize = Rotativa.AspNetCore.Options.Size.A4,
PageOrientation = Rotativa.AspNetCore.Options.Orientation.Portrait
};
}
}
}// NuGet: Install-Package Rotativa.Core
using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using System.Threading.Tasks;
namespace RotativaExample
{
public class UrlPdfController : Controller
{
public async Task<IActionResult> ConvertUrlToPdf()
{
// Rotativaworks within MVC framework and returns ActionResult
return new UrlAsPdf("https://www.example.com")
{
FileName = "webpage.pdf",
PageSize = Rotativa.AspNetCore.Options.Size.A4,
PageOrientation = Rotativa.AspNetCore.Options.Orientation.Portrait
};
}
}
}IRON VB CONVERTER ERROR developers@ironsoftware.comDespués (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
namespace IronPdfExample
{
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
pdf.SaveAs("webpage.pdf");
Console.WriteLine("URL converted to PDF successfully!");
}
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using System;
namespace IronPdfExample
{
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
pdf.SaveAs("webpage.pdf");
Console.WriteLine("URL converted to PDF successfully!");
}
}
}IRON VB CONVERTER ERROR developers@ironsoftware.comLa clase <código>UrlAsPdf</códigode Rotativarequiere devolver un ActionResult desde un controlador MVC. El método RenderUrlAsPdf() deIronPDFpuede invocarse desde cualquier contexto y devuelve directamente un objeto PdfDocument. El renderizado de URL utiliza el moderno Chromium en lugar del vulnerable y anticuado motor WebKit de wkhtmltopdf. Obtenga más información en nuestros tutoriales.
Ejemplo 3: Encabezados y pies de página con números de página
Antes (Rotativa):
// NuGet: Install-Package Rotativa.Core
using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using Rotativa.AspNetCore.Options;
using System.Threading.Tasks;
namespace RotativaExample
{
public class HeaderFooterController : Controller
{
public async Task<IActionResult> GeneratePdfWithHeaderFooter()
{
return new ViewAsPdf("Report")
{
PageSize = Size.A4,
PageMargins = new Margins(20, 10, 20, 10),
CustomSwitches = "--header-center \"Page Header\" --footer-center \"Page [page] of [toPage]\""
};
}
}
}// NuGet: Install-Package Rotativa.Core
using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using Rotativa.AspNetCore.Options;
using System.Threading.Tasks;
namespace RotativaExample
{
public class HeaderFooterController : Controller
{
public async Task<IActionResult> GeneratePdfWithHeaderFooter()
{
return new ViewAsPdf("Report")
{
PageSize = Size.A4,
PageMargins = new Margins(20, 10, 20, 10),
CustomSwitches = "--header-center \"Page Header\" --footer-center \"Page [page] of [toPage]\""
};
}
}
}IRON VB CONVERTER ERROR developers@ironsoftware.comDespués (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;
namespace IronPdfExample
{
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.TextHeader = new TextHeaderFooter()
{
CenterText = "Page Header",
DrawDividerLine = true
};
renderer.RenderingOptions.TextFooter = new TextHeaderFooter()
{
CenterText = "Page {page} of {total-pages}",
DrawDividerLine = true
};
var htmlContent = "<h1>Report Title</h1><p>Report content goes here.</p>";
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("report.pdf");
Console.WriteLine("PDF with headers and footers created successfully!");
}
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;
namespace IronPdfExample
{
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.TextHeader = new TextHeaderFooter()
{
CenterText = "Page Header",
DrawDividerLine = true
};
renderer.RenderingOptions.TextFooter = new TextHeaderFooter()
{
CenterText = "Page {page} of {total-pages}",
DrawDividerLine = true
};
var htmlContent = "<h1>Report Title</h1><p>Report content goes here.</p>";
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("report.pdf");
Console.WriteLine("PDF with headers and footers created successfully!");
}
}
}IRON VB CONVERTER ERROR developers@ironsoftware.comRotativa utiliza CustomSwitches para pasar argumentos de línea de comandos a wkhtmltopdf, incluida la configuración de encabezados y pies de página con marcadores de posición como <código>[página]</código>y [toPage]. Este enfoque basado en cadenas es propenso a errores y difícil de validar en tiempo de compilación.
IronPDF utiliza objetos TextHeaderFooter con propiedades como CenterText y DrawDividerLine. La sintaxis del marcador de posición cambia de <código>[página]</código>a {page}y de [toPage] a {total-pages}. Las propiedades tipificadas ofrecen IntelliSense, comprobación en tiempo de compilación y ausencia de riesgo de errores tipográficos.
El problema de la arquitectura MVC
Rotativa se ha diseñado para ASP.NET MVC 5 y versiones anteriores:
// ❌ Rotativa- Only works with classic MVC pattern
public class InvoiceController : Controller
{
public ActionResult InvoicePdf(int id)
{
var model = GetInvoice(id);
return new ViewAsPdf("Invoice", model); // Tied to MVC Views
}
}
// Problems:
// - No Razor Pages support
// - No Blazor support
// - No minimal APIs support
// - No ASP.NET Core native integration// ❌ Rotativa- Only works with classic MVC pattern
public class InvoiceController : Controller
{
public ActionResult InvoicePdf(int id)
{
var model = GetInvoice(id);
return new ViewAsPdf("Invoice", model); // Tied to MVC Views
}
}
// Problems:
// - No Razor Pages support
// - No Blazor support
// - No minimal APIs support
// - No ASP.NET Core native integrationIRON VB CONVERTER ERROR developers@ironsoftware.comIronPDF separa la renderización de vistas de la generación de PDF, lo que en realidad es más flexible: se puede renderizar cualquier HTML, no sólo vistas MVC.
Migración de patrones asíncronos
Rotativa bloquea el hilo;IronPDFes totalmente compatible con async/await:
// ❌ Rotativa- Blocks the thread
public ActionResult GeneratePdf()
{
return new ViewAsPdf("Report");
// This blocks the request thread until PDF is complete
// Poor scalability under load
}
// ✅IronPDF- Async completosupport
public async Task<IActionResult> GeneratePdf()
{
var renderer = new ChromePdfRenderer();
var pdf = await renderer.RenderHtmlAsPdfAsync(html);
return File(pdf.BinaryData, "application/pdf");
// Non-blocking, better scalability
}// ❌ Rotativa- Blocks the thread
public ActionResult GeneratePdf()
{
return new ViewAsPdf("Report");
// This blocks the request thread until PDF is complete
// Poor scalability under load
}
// ✅IronPDF- Async completosupport
public async Task<IActionResult> GeneratePdf()
{
var renderer = new ChromePdfRenderer();
var pdf = await renderer.RenderHtmlAsPdfAsync(html);
return File(pdf.BinaryData, "application/pdf");
// Non-blocking, better scalability
}IRON VB CONVERTER ERROR developers@ironsoftware.comNuevas capacidades tras la migración
Tras migrar a IronPDF, obtendrá funciones que Rotativano puede ofrecer:
Fusión de PDF
var merged = PdfDocument.Merge(pdf1, pdf2, pdf3);
merged.SaveAs("complete.pdf");var merged = PdfDocument.Merge(pdf1, pdf2, pdf3);
merged.SaveAs("complete.pdf");IRON VB CONVERTER ERROR developers@ironsoftware.comFirmas digitales
var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);IRON VB CONVERTER ERROR developers@ironsoftware.comProtección con contraseña
pdf.SecuritySettings.UserPassword = "secret";pdf.SecuritySettings.UserPassword = "secret";IRON VB CONVERTER ERROR developers@ironsoftware.comMarcas de agua
pdf.ApplyWatermark("<h1 style='color:red; opacity:0.3;'>DRAFT</h1>");pdf.ApplyWatermark("<h1 style='color:red; opacity:0.3;'>DRAFT</h1>");IRON VB CONVERTER ERROR developers@ironsoftware.comCumplimiento de la normativa sobre archivos PDF/A
pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b);pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b);IRON VB CONVERTER ERROR developers@ironsoftware.comSoporte CSS moderno
// This now works (broke in Rotativa)
var html = @"
<div style='display: flex; justify-content: space-between;'>
<div>Left</div>
<div>Right</div>
</div>
<div style='display: grid; grid-template-columns: 1fr 1fr 1fr;'>
<div>Col 1</div><div>Col 2</div><div>Col 3</div>
</div>";
var pdf = renderer.RenderHtmlAsPdf(html); // Works!// This now works (broke in Rotativa)
var html = @"
<div style='display: flex; justify-content: space-between;'>
<div>Left</div>
<div>Right</div>
</div>
<div style='display: grid; grid-template-columns: 1fr 1fr 1fr;'>
<div>Col 1</div><div>Col 2</div><div>Col 3</div>
</div>";
var pdf = renderer.RenderHtmlAsPdf(html); // Works!IRON VB CONVERTER ERROR developers@ironsoftware.comLista de comprobación de la migración
Pre-Migración
- [ ] Identificar todos los usos de Rotativaen el código base
- [ ] Documento CustomSwitches utilizado para la conversión a RenderingOptions
- [ ] Tenga en cuenta la sintaxis del marcador de posición de encabezado/pie de página para la conversión (
[página]→{página}) - [ ] Obtenga la clave de licencia deIronPDFen ironpdf.com
Cambios en el paquete
- [Eliminar los paquetes NuGet
RotativayRotativa.AspNetCore - [ ] Eliminar los binarios de wkhtmltopdf (
wkhtmltopdf.exe,wkhtmltox.dll) - [ ] Instalar
IronPdfpaquete NuGet
Cambios de código
- [ ] Actualizar las importaciones de espacios de nombres (
usando Rotativa;→usando IronPDF;) - [Reemplace <código>VerComoPdf</códigopor <código>ChromePdfRenderer</código+
RenderHtmlAsPdf() - [Reemplace <código>UrlAsPdf</códigopor
RenderUrlAsPdf() - [Convertir
CustomSwitchesen propiedadesRenderingOptions - [ ] Actualizar la sintaxis de los marcadores de posición (
[page]→{page},[topage]→{total-pages}) - [ ] Sustituir
MargenesDePáginaporMarginTop/MarginBottom/MarginLeft/MarginRightindividuales - [ ] Cambiar al patrón async cuando proceda
- [ ] Añadir inicialización de licencia al inicio de la aplicación
Posmigración
- [ ] Verificar que toda la generación de PDF funciona correctamente
- [ ] Comparar la calidad de salida de PDF (Chromium renderiza con más precisión)
- [ ] Verificar las mejoras de renderizado CSS (Flexbox/Grid ahora funcionan)
- [ ] Prueba de ejecución de JavaScript (ahora fiable con Chromium)
- [ ] Comprobar que el análisis de seguridad ha pasado (no más indicadores CVE-2022-35583)
- [ ] Actualizar las configuraciones de Docker para eliminar la instalación de wkhtmltopdf
Conclusión
Aunque Rotativaha proporcionado históricamente una solución sencilla para la generación de PDF en aplicaciones ASP.NET MVC, su dependencia de una pila tecnológica obsoleta y su abandono en términos de mantenimiento plantean importantes retos. La vulnerabilidad de seguridad crítica CVE-2022-35583nunca será parcheada, exponiendo permanentemente cada aplicación Rotativa.
Los cambios clave en esta migración son:
- Seguridad: Vulnerabilidad crítica SSRF (CVE-2022-35583) → Protegido
- Arquitectura: Solo MVC → Cualquier tipo de proyecto .NET
- Motor de renderizado: WebKit anticuado (2012) → Chromium moderno
- Soporte CSS: Parcial (sin Flexbox/Grid) → Compatibilidad total con CSS3
- JavaScript: Poco fiable → Compatibilidad total con ES6+
- Patrón: <código>VerComoPdf</códigotipo de retorno → <código>ChromePdfRenderer</código+
RenderHtmlAsPdf() - Renderización de URL: <código>UrlAsPdf</código→
RenderUrlAsPdf() - Cabeceras/Pies de página:
CustomSwitchescadenas →TextHeaderFooterobjetos tipificados - Placeholders:
[page],[topage]→{page},{total-pages} - Soporte asíncrono: sólo síncrono → asíncrono/espera completo
- Mantenimiento: Abandonado → Actualizaciones semanales
Los desarrolladores interesados en la generación versátil y segura de PDF en diversas aplicaciones .NET encontrarán enIronPDFuna opción más convincente.IronPDFno sólo garantiza la compatibilidad con una amplia gama de aplicaciones, sino que también proporciona asistencia y actualizaciones continuas, que son cruciales en el panorama tecnológico actual en rápida evolución.
Explore la documentación completa de IronPDF, tutoriales y referencia de API para acelerar su migración a Rotativa.






