Cómo convertir vistas a PDF en ASP.NET Core MVC | IronPDF

Cómo convertir vistas a PDF en C# ASP.NET Core MVC

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

Convierte las vistas de ASP.NET Core MVC a PDFs usando el método RenderRazorViewToPdf de IronPDF, que transforma archivos .cshtml en documentos PDF de alta calidad con una sola línea de código en tu aplicación MVC.

Una Vista es un componente en el marco de ASP.NET utilizado para generar marcado HTML en aplicaciones web. Forma parte del patrón Modelo-Vista-Controlador (MVC), utilizado habitualmente en aplicaciones ASP.NET MVC y ASP.NET Core MVC. Las vistas se encargan de presentar datos a los usuarios mediante la representación dinámica de contenido HTML. Las vistas suelen utilizar la sintaxis Razor, una sintaxis de marcado para incrustar código basado en servidor en páginas web, lo que las convierte en potentes herramientas para crear documentos PDF basados en datos.

Inicio rápido: Convertir CSHTML a PDF en ASP.NET Core

Transformar ASP.NET Core MVC Views a PDFs utilizando IronPDF. Con una línea de código, renderiza tus archivos .cshtml en documentos PDF. Integre esta funcionalidad directamente en su aplicación MVC para generar PDF sin problemas a partir de vistas HTML dinámicas. Sigue esta guía para configurar tu entorno y empezar a convertir.

  1. Instala IronPDF con el Administrador de Paquetes NuGet

    PM > Install-Package IronPdf
  2. Copie y ejecute este fragmento de código.

    // using IronPdf.Extensions.Mvc.Core
    new IronPdf.ChromePdfRenderer().RenderRazorViewToPdf(HttpContext, "Views/Home/Report.cshtml", model).SaveAs("report.pdf");
  3. Despliegue para probar en su entorno real

    Comienza a usar IronPDF en tu proyecto hoy mismo con una prueba gratuita

    arrow pointer

ASP.NET Core Web App MVC (Model-View-Controller) es un marco de aplicaciones web proporcionado por Microsoft para crear aplicaciones web utilizando ASP.NET Core.

  • Model: Representa datos y lógica de negocio, gestiona interacciones de datos, se comunica con fuentes de datos.
  • View: Presenta la interfaz de usuario, muestra datos, renderiza información para los usuarios.
  • Controller: Maneja la entrada del usuario, responde a solicitudes, se comunica con el Model, orquesta las interacciones de Modelo-Vista.

IronPDF permite la creación directa de archivos PDF a partir de vistas en proyectos ASP.NET Core MVC. Esto hace que la generación de PDF sea sencilla en ASP.NET Core MVC, compatible con funciones modernas como estilos CSS, ejecución de JavaScript y fuentes personalizadas.

En el mercado español, los portales web de facturación electrónica desarrollados con ASP.NET Core MVC son una de las arquitecturas más comunes entre los ISVs que implementan los requisitos de VeriFactu y la ley Crea y Crece. La posibilidad de convertir directamente una vista Razor a PDF permite que el mismo controlador MVC que muestra la factura en el navegador genere el PDF de representación gráfica exigido por la normativa española, sin necesidad de un motor de generación independiente.

¿Qué paquete necesito para las extensiones IronPDF?

El paquete IronPdf.Extensions.Mvc.Core es una extensión del paquete principal IronPdf. Se necesitan ambos paquetes IronPdf.Extensions.Mvc.Core y IronPdf para renderizar las vistas en documentos PDF en ASP.NET Core MVC. El paquete de extensión proporciona funciones específicas para la integración con el sistema de inyección de dependencias de ASP.NET Core y el canal de renderización de vistas Razor.

Instalación del paquete IronPdf.Extensions.Mvc.Core

¿Por qué necesito tanto IronPDF como el paquete de extensiones?

El paquete principal de IronPDF contiene el motor de renderización de PDF y la funcionalidad fundamental, mientras que el paquete Extensions.Mvc.Core proporciona una integración especializada con el sistema de renderización de vistas de ASP.NET Core MVC. Esta separación permite una mejor modularidad y garantiza que solo se incluya la funcionalidad específica necesaria para el tipo de proyecto. El paquete de extensión incluye la interfaz IRazorViewRenderer y la implementación necesaria para convertir vistas de Razor a HTML antes de la generación de PDF.

¿Qué versión del paquete NuGet debo usar?

Siempre usa versiones coincidentes de IronPdf y IronPdf.Extensions.Mvc.Core para asegurar la compatibilidad. Para obtener las últimas versiones estables e información sobre compatibilidad de versiones, consulte la documentación de los paquetes NuGet. Al actualizar, asegúrese de que ambos paquetes se actualizan juntos para mantener la funcionalidad adecuada.

¿Cuáles son los problemas de instalación más comunes?

Entre los problemas de instalación más comunes se encuentran los desajustes de versión entre los paquetes del núcleo y de las extensiones, la falta de dependencias o los requisitos específicos de la plataforma. Si se encuentra con problemas, asegúrese de que su proyecto se dirige a una versión de .NET compatible y revise la descripción general de la instalación para conocer los pasos a seguir para la solución de problemas.

Biblioteca C# NuGet para PDF

Instalar con NuGet

Instalación del paquete IronPdf.Extensions.Mvc.Core

¿Cómo renderizar vistas en PDF?

Se necesita un proyecto ASP.NET Core Web App (Modelo-Vista-Controlador) para convertir Vistas en archivos PDF. El proceso implica crear una acción del controlador que utiliza el método RenderRazorViewToPdf de IronPDF para transformar tus vistas de Razor en documentos PDF. Este enfoque aprovecha toda la potencia de la sintaxis de Razor, lo que permite crear PDF complejos, basados en datos y con contenido dinámico.

¿Qué tipo de proyecto debo utilizar?

Utilice la plantilla ASP.NET Core Web App (Model-View-Controller) para una compatibilidad óptima con las funciones de representación de vistas de IronPDF. Este tipo de proyecto proporciona la infraestructura necesaria para la representación de vistas, incluido el motor de vistas Razor y el enrutamiento adecuado. Para los proyectos existentes, asegúrese de que siguen el patrón MVC y de que tienen instaladas las capacidades de renderizado de vistas necesarias.

¿Puedo usar esto con API mínimas?

Aunque las API mínimas no son compatibles con las vistas integradas, puede utilizar las funciones de conversión de HTML a PDF de IronPDF. Para la generación de PDF basados en vistas, utilice el enfoque MVC tradicional o considere Razor Pages como alternativa.

¿Cómo añado una clase modelo?

  • Navega a la carpeta "Models".
  • Cree un nuevo archivo de clase C# llamado "Persona" Esta clase actuará como modelo para representar datos individuales. Utiliza el siguiente fragmento de código:
:path=/static-assets/pdf/content-code-examples/how-to/cshtml-to-pdf-mvc-core-model.cs
namespace ViewToPdfMVCCoreSample.Models
{
    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
    }
}
Namespace ViewToPdfMVCCoreSample.Models
	Public Class Person
		Public Property Id() As Integer
		Public Property Name() As String
		Public Property Title() As String
		Public Property Description() As String
	End Class
End Namespace
$vbLabelText   $csharpLabel

¿Por qué necesito un modelo para la generación de PDF?

Los modelos proporcionan datos estructurados que pueden pasarse a las vistas para su representación. Esta separación de preocupaciones garantiza que la lógica de generación de PDF permanezca limpia y se pueda mantener. El modelo actúa como un contrato entre el controlador y la vista, garantizando la seguridad de tipos y permitiendo el soporte de IntelliSense en las vistas Razor.

¿Qué tipos de datos funcionan mejor con vistas?

Los tipos de datos y las colecciones simples son los más adecuados para la generación de PDF. Se pueden utilizar objetos anidados complejos, pero pueden requerir lógica de vista adicional. Para obtener un rendimiento óptimo, aplane las estructuras de datos complejas en el controlador antes de pasarlas a la vista. Considere la posibilidad de utilizar ViewModels diseñados específicamente para la salida de PDF cuando sus modelos de dominio sean demasiado complejos.

He aquí un ejemplo de una estructura de modelo más compleja adecuada para la generación de PDF:

public class InvoiceViewModel
{
    public string InvoiceNumber { get; set; }
    public DateTime InvoiceDate { get; set; }
    public decimal TotalAmount { get; set; }
    public List<InvoiceLineItem> LineItems { get; set; }
    public CustomerInfo Customer { get; set; }

    // Computed property for PDF display
    public string FormattedTotal => TotalAmount.ToString("C");
}

public class InvoiceLineItem
{
    public string Description { get; set; }
    public int Quantity { get; set; }
    public decimal UnitPrice { get; set; }
    public decimal LineTotal => Quantity * UnitPrice;
}

public class CustomerInfo
{
    public string Name { get; set; }
    public string Email { get; set; }
    public string Address { get; set; }
}
public class InvoiceViewModel
{
    public string InvoiceNumber { get; set; }
    public DateTime InvoiceDate { get; set; }
    public decimal TotalAmount { get; set; }
    public List<InvoiceLineItem> LineItems { get; set; }
    public CustomerInfo Customer { get; set; }

    // Computed property for PDF display
    public string FormattedTotal => TotalAmount.ToString("C");
}

public class InvoiceLineItem
{
    public string Description { get; set; }
    public int Quantity { get; set; }
    public decimal UnitPrice { get; set; }
    public decimal LineTotal => Quantity * UnitPrice;
}

public class CustomerInfo
{
    public string Name { get; set; }
    public string Email { get; set; }
    public string Address { get; set; }
}
Public Class InvoiceViewModel
    Public Property InvoiceNumber As String
    Public Property InvoiceDate As DateTime
    Public Property TotalAmount As Decimal
    Public Property LineItems As List(Of InvoiceLineItem)
    Public Property Customer As CustomerInfo

    ' Computed property for PDF display
    Public ReadOnly Property FormattedTotal As String
        Get
            Return TotalAmount.ToString("C")
        End Get
    End Property
End Class

Public Class InvoiceLineItem
    Public Property Description As String
    Public Property Quantity As Integer
    Public Property UnitPrice As Decimal
    Public ReadOnly Property LineTotal As Decimal
        Get
            Return Quantity * UnitPrice
        End Get
    End Property
End Class

Public Class CustomerInfo
    Public Property Name As String
    Public Property Email As String
    Public Property Address As String
End Class
$vbLabelText   $csharpLabel

¿Cómo edito el controlador?

Navega a la carpeta "Controllers" y abre el archivo HomeController.cs. Haremos cambios solo en el HomeController y añadiremos la acción Persons. Consulte el código siguiente como guía:

El código a continuación primero instancia la clase ChromePdfRenderer, pasando un IRazorViewRenderer, la ruta a nuestro Views/Home/Persons.cshtml, y el List que contiene los datos requeridos al método RenderRazorViewToPdf. Los usuarios pueden usar RenderingOptions para acceder a una gama de características, como la adición de texto personalizado, la inclusión de encabezados y pies de página HTML en el PDF resultante, definir márgenes personalizados y aplicar números de página. Para más opciones avanzadas de renderizado, consulte la documentación sobre opciones de renderizado.

Por favor notaEl documento PDF se puede ver en el navegador usando el siguiente código: File(pdf.BinaryData, "application/pdf"). Sin embargo, descargar el PDF después de verlo en el navegador resulta en un documento PDF dañado.

using IronPdf.Extensions.Mvc.Core;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using ViewToPdfMVCCoreSample.Models;

namespace ViewToPdfMVCCoreSample.Controllers
{
    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;
        private readonly IRazorViewRenderer _viewRenderService;
        private readonly IHttpContextAccessor _httpContextAccessor;

        public HomeController(ILogger<HomeController> logger, IRazorViewRenderer viewRenderService, IHttpContextAccessor httpContextAccessor)
        {
            _logger = logger;
            _viewRenderService = viewRenderService;
            _httpContextAccessor = httpContextAccessor;
        }

        public IActionResult Index()
        {
            return View();
        }

        public async Task<IActionResult> Persons()
        {
            // Example list of persons
            var persons = new List<Person>
            {
                new Person { Name = "Alice", Title = "Mrs.", Description = "Software Engineer" },
                new Person { Name = "Bob", Title = "Mr.", Description = "Software Engineer" },
                new Person { Name = "Charlie", Title = "Mr.", Description = "Software Engineer" }
            };

            // Check if the request method is POST
            if (_httpContextAccessor.HttpContext.Request.Method == HttpMethod.Post.Method)
            {
                // Create a new PDF renderer
                ChromePdfRenderer renderer = new ChromePdfRenderer();

                // Configure rendering options for better output
                renderer.RenderingOptions.MarginTop = 40;
                renderer.RenderingOptions.MarginBottom = 40;
                renderer.RenderingOptions.PaperOrientation = IronPdf.Rendering.PdfPaperOrientation.Portrait;
                renderer.RenderingOptions.Title = "Persons Report";

                // Render View to PDF document
                PdfDocument pdf = renderer.RenderRazorViewToPdf(_viewRenderService, "Views/Home/Persons.cshtml", persons);

                Response.Headers.Add("Content-Disposition", "inline");

                // Output PDF document
                return File(pdf.BinaryData, "application/pdf", "viewToPdfMVCCore.pdf");
            }

            return View(persons);
        }

        public IActionResult Privacy()
        {
            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}
using IronPdf.Extensions.Mvc.Core;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using ViewToPdfMVCCoreSample.Models;

namespace ViewToPdfMVCCoreSample.Controllers
{
    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;
        private readonly IRazorViewRenderer _viewRenderService;
        private readonly IHttpContextAccessor _httpContextAccessor;

        public HomeController(ILogger<HomeController> logger, IRazorViewRenderer viewRenderService, IHttpContextAccessor httpContextAccessor)
        {
            _logger = logger;
            _viewRenderService = viewRenderService;
            _httpContextAccessor = httpContextAccessor;
        }

        public IActionResult Index()
        {
            return View();
        }

        public async Task<IActionResult> Persons()
        {
            // Example list of persons
            var persons = new List<Person>
            {
                new Person { Name = "Alice", Title = "Mrs.", Description = "Software Engineer" },
                new Person { Name = "Bob", Title = "Mr.", Description = "Software Engineer" },
                new Person { Name = "Charlie", Title = "Mr.", Description = "Software Engineer" }
            };

            // Check if the request method is POST
            if (_httpContextAccessor.HttpContext.Request.Method == HttpMethod.Post.Method)
            {
                // Create a new PDF renderer
                ChromePdfRenderer renderer = new ChromePdfRenderer();

                // Configure rendering options for better output
                renderer.RenderingOptions.MarginTop = 40;
                renderer.RenderingOptions.MarginBottom = 40;
                renderer.RenderingOptions.PaperOrientation = IronPdf.Rendering.PdfPaperOrientation.Portrait;
                renderer.RenderingOptions.Title = "Persons Report";

                // Render View to PDF document
                PdfDocument pdf = renderer.RenderRazorViewToPdf(_viewRenderService, "Views/Home/Persons.cshtml", persons);

                Response.Headers.Add("Content-Disposition", "inline");

                // Output PDF document
                return File(pdf.BinaryData, "application/pdf", "viewToPdfMVCCore.pdf");
            }

            return View(persons);
        }

        public IActionResult Privacy()
        {
            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}
Imports IronPdf.Extensions.Mvc.Core
Imports Microsoft.AspNetCore.Mvc
Imports System.Diagnostics
Imports ViewToPdfMVCCoreSample.Models

Namespace ViewToPdfMVCCoreSample.Controllers
    Public Class HomeController
        Inherits Controller

        Private ReadOnly _logger As ILogger(Of HomeController)
        Private ReadOnly _viewRenderService As IRazorViewRenderer
        Private ReadOnly _httpContextAccessor As IHttpContextAccessor

        Public Sub New(logger As ILogger(Of HomeController), viewRenderService As IRazorViewRenderer, httpContextAccessor As IHttpContextAccessor)
            _logger = logger
            _viewRenderService = viewRenderService
            _httpContextAccessor = httpContextAccessor
        End Sub

        Public Function Index() As IActionResult
            Return View()
        End Function

        Public Async Function Persons() As Task(Of IActionResult)
            ' Example list of persons
            Dim persons = New List(Of Person) From {
                New Person With {.Name = "Alice", .Title = "Mrs.", .Description = "Software Engineer"},
                New Person With {.Name = "Bob", .Title = "Mr.", .Description = "Software Engineer"},
                New Person With {.Name = "Charlie", .Title = "Mr.", .Description = "Software Engineer"}
            }

            ' Check if the request method is POST
            If _httpContextAccessor.HttpContext.Request.Method = HttpMethod.Post.Method Then
                ' Create a new PDF renderer
                Dim renderer As New ChromePdfRenderer()

                ' Configure rendering options for better output
                renderer.RenderingOptions.MarginTop = 40
                renderer.RenderingOptions.MarginBottom = 40
                renderer.RenderingOptions.PaperOrientation = IronPdf.Rendering.PdfPaperOrientation.Portrait
                renderer.RenderingOptions.Title = "Persons Report"

                ' Render View to PDF document
                Dim pdf As PdfDocument = renderer.RenderRazorViewToPdf(_viewRenderService, "Views/Home/Persons.cshtml", persons)

                Response.Headers.Add("Content-Disposition", "inline")

                ' Output PDF document
                Return File(pdf.BinaryData, "application/pdf", "viewToPdfMVCCore.pdf")
            End If

            Return View(persons)
        End Function

        Public Function Privacy() As IActionResult
            Return View()
        End Function

        <ResponseCache(Duration:=0, Location:=ResponseCacheLocation.None, NoStore:=True)>
        Public Function Error() As IActionResult
            Return View(New ErrorViewModel With {.RequestId = If(Activity.Current?.Id, HttpContext.TraceIdentifier)})
        End Function
    End Class
End Namespace
$vbLabelText   $csharpLabel

Después de usar el método RenderRazorViewToPdf, recibes un objeto PdfDocument que está abierto a mejoras y modificaciones adicionales. Puede convertir el PDF a los formatos PDF/A o PDF/UA, añadir su firma digital al PDF generado o combinar y dividir documentos PDF según sea necesario. Además, la biblioteca te permite rotar páginas, insertar anotaciones o marcadores, e imprimir marcas de agua únicas en tus archivos PDF.

¿Qué es el servicio IRazorViewRenderer?

El IRazorViewRenderer es una interfaz de servicio proporcionada por el paquete IronPdf.Extensions.Mvc.Core que maneja la conversión de vistas de Razor a HTML. Se integra con el motor de vistas de ASP.NET Core para procesar archivos .cshtml con sus modelos asociados, ejecutando toda la sintaxis de Razor y produciendo el HTML final que IronPDF convierte a PDF.

¿Por qué comprobar el método POST antes de renderizar?

La comprobación de POST garantiza que la generación de PDF sólo se produzca cuando se solicite explícitamente a través de un formulario. Esto evita la generación accidental de PDF al cargar la página y permite que la misma acción sirva tanto para la vista HTML (en GET) como para la descarga del PDF (en POST). Este patrón sigue principios RESTful y ofrece una mejor experiencia de usuario.

¿Cómo puedo personalizar la salida PDF?

IronPDF ofrece amplias opciones de personalización a través de la propiedad RenderingOptions. Aquí tienes un ejemplo con una configuración más avanzada:

// Advanced rendering configuration example
var renderer = new ChromePdfRenderer();

// Page setup
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;
renderer.RenderingOptions.MarginLeft = 20;
renderer.RenderingOptions.MarginRight = 20;

// Headers and footers with merge fields
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter()
{
    Height = 25,
    HtmlFragment = "<div style='text-align: center; font-size: 12px;'>Page {page} of {total-pages}</div>"
};

// JavaScript execution delay for dynamic content
renderer.RenderingOptions.WaitFor = new WaitFor()
{
    RenderDelay = 500, // Wait 500ms for JS execution
    NetworkIdle = NetworkIdleTypes.NetworkIdle0 // Wait for network requests
};

// Apply watermark
renderer.RenderingOptions.TextHeader = new TextHeaderFooter()
{
    DrawDividerLine = true,
    CenterText = "CONFIDENTIAL",
    Font = new FontTypes() { FontSize = 16 }
};
// Advanced rendering configuration example
var renderer = new ChromePdfRenderer();

// Page setup
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;
renderer.RenderingOptions.MarginLeft = 20;
renderer.RenderingOptions.MarginRight = 20;

// Headers and footers with merge fields
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter()
{
    Height = 25,
    HtmlFragment = "<div style='text-align: center; font-size: 12px;'>Page {page} of {total-pages}</div>"
};

// JavaScript execution delay for dynamic content
renderer.RenderingOptions.WaitFor = new WaitFor()
{
    RenderDelay = 500, // Wait 500ms for JS execution
    NetworkIdle = NetworkIdleTypes.NetworkIdle0 // Wait for network requests
};

// Apply watermark
renderer.RenderingOptions.TextHeader = new TextHeaderFooter()
{
    DrawDividerLine = true,
    CenterText = "CONFIDENTIAL",
    Font = new FontTypes() { FontSize = 16 }
};
' Advanced rendering configuration example
Dim renderer As New ChromePdfRenderer()

' Page setup
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4
renderer.RenderingOptions.MarginLeft = 20
renderer.RenderingOptions.MarginRight = 20

' Headers and footers with merge fields
renderer.RenderingOptions.HtmlHeader = New HtmlHeaderFooter() With {
    .Height = 25,
    .HtmlFragment = "<div style='text-align: center; font-size: 12px;'>Page {page} of {total-pages}</div>"
}

' JavaScript execution delay for dynamic content
renderer.RenderingOptions.WaitFor = New WaitFor() With {
    .RenderDelay = 500, ' Wait 500ms for JS execution
    .NetworkIdle = NetworkIdleTypes.NetworkIdle0 ' Wait for network requests
}

' Apply watermark
renderer.RenderingOptions.TextHeader = New TextHeaderFooter() With {
    .DrawDividerLine = True,
    .CenterText = "CONFIDENTIAL",
    .Font = New FontTypes() With {.FontSize = 16}
}
$vbLabelText   $csharpLabel

¿Cuáles son los errores más comunes de los controladores?

Entre los errores más comunes se incluyen las excepciones de referencia nula cuando los servicios no se inyectan correctamente, los problemas de ruta al especificar las ubicaciones de las vistas y los problemas de vinculación de modelos. Asegúrate de que todos los servicios requeridos estén registrados en Program.cs y usa rutas relativas desde la raíz del proyecto al especificar ubicaciones de vistas. Para la resolución de problemas, habilite mensajes de error detallados en el modo de desarrollo.

¿Cómo añado una vista?

  • Haz clic derecho en la acción Person recién agregada y selecciona "Agregar vista".

Menú contextual de Visual Studio que muestra la opción 'Agregar vista...' resaltada al hacer clic derecho en el método Persons()

  • Elige "Razor View" para el nuevo elemento Creado por Scaffolding.

Cuadro de diálogo Agregar vista Razor en Visual Studio que muestra la selección de la clase del modelo Persona y la plantilla de Lista con opciones de diseño

  • Selecciona la plantilla "Lista" y la clase modelo Person.

Cuadro de diálogo Agregar vista Razor en Visual Studio que muestra la selección de la plantilla de lista y la clase del modelo Persona con opciones de diseño

Esto crea un archivo .cshtml llamado Persons.

  • Navega a la carpeta "Views" -> carpeta "Home" -> archivo Persons.cshtml.

IronPdf.Extensions.Mvc.Core

Para añadir un botón que invoque la acción Persons, utiliza el siguiente código:

@using (Html.BeginForm("Persons", "Home", FormMethod.Post))
{
    <input type="submit" value="Print Person" />
}
@using (Html.BeginForm("Persons", "Home", FormMethod.Post))
{
    <input type="submit" value="Print Person" />
}
HTML

¿Por qué usar FormMethod.Post para la generación de PDF?

Usar FormMethod.Post para la generación de PDF sigue las mejores prácticas web al hacer la acción explícita y prevenir la generación indeseada de PDF por actualizaciones del navegador o URLs marcadas. Las solicitudes de POST deben ser idempotentes (no cambiar el estado del servidor), mientras que las solicitudes de POST indican una acción que produce un resultado – en este caso, generar un documento PDF.

¿Cómo puedo dar estilo al botón Imprimir PDF?

Estiliza el botón de impresión utilizando clases CSS y mejoralo con JavaScript para una mejor experiencia de usuario. Aquí tienes una versión mejorada:

@using (Html.BeginForm("Persons", "Home", FormMethod.Post, new { @class = "pdf-form" }))
{
    <button type="submit" class="btn btn-primary pdf-download-btn">
        <i class="fas fa-file-pdf"></i> Download as PDF
    </button>
}

<style>
    .pdf-download-btn {
        background-color: #dc3545;
        color: white;
        padding: 10px 20px;
        border: none;
        border-radius: 5px;
        cursor: pointer;
        transition: background-color 0.3s ease;
    }

    .pdf-download-btn:hover {
        background-color: #c82333;
    }

    .pdf-download-btn:active {
        transform: translateY(1px);
    }
</style>

<script>
    // Optional: Show loading indicator during PDF generation
    document.querySelector('.pdf-form').addEventListener('submit', function() {
        const button = this.querySelector('button');
        button.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Generating PDF...';
        button.disabled = true;
    });
</script>
@using (Html.BeginForm("Persons", "Home", FormMethod.Post, new { @class = "pdf-form" }))
{
    <button type="submit" class="btn btn-primary pdf-download-btn">
        <i class="fas fa-file-pdf"></i> Download as PDF
    </button>
}

<style>
    .pdf-download-btn {
        background-color: #dc3545;
        color: white;
        padding: 10px 20px;
        border: none;
        border-radius: 5px;
        cursor: pointer;
        transition: background-color 0.3s ease;
    }

    .pdf-download-btn:hover {
        background-color: #c82333;
    }

    .pdf-download-btn:active {
        transform: translateY(1px);
    }
</style>

<script>
    // Optional: Show loading indicator during PDF generation
    document.querySelector('.pdf-form').addEventListener('submit', function() {
        const button = this.querySelector('button');
        button.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Generating PDF...';
        button.disabled = true;
    });
</script>
HTML

¿Qué plantillas de vista funcionan mejor para PDF?

Los templates List y Details funcionan particularmente bien para la generación de PDF ya que proporcionan estructuras organizadas. Las plantillas personalizadas diseñadas específicamente para PDF suelen dar los mejores resultados. Considere la posibilidad de crear vistas de PDF dedicadas que se optimicen para el diseño de impresión en lugar de la visualización en pantalla, eliminando los elementos de navegación y centrándose en la presentación del contenido.

¿Cómo añado una sección a la barra de navegación superior?

  • En la misma carpeta "Views" navega a la carpeta "Shared" -> _Layout.cshtml. Coloca el elemento de navegación Person después de Home.

Asegúrate de que el valor para el atributo asp-action coincide exactamente con nuestro nombre de archivo, que en este caso es Persons.

<header>
    <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
        <div class="container-fluid">
            <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">ViewToPdfMVCCoreSample</a>
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                    aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                <ul class="navbar-nav flex-grow-1">
                    <li class="nav-item">
                        <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Persons">Person</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                    </li>
                </ul>
            </div>
        </div>
    </nav>
</header>
<header>
    <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
        <div class="container-fluid">
            <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">ViewToPdfMVCCoreSample</a>
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                    aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                <ul class="navbar-nav flex-grow-1">
                    <li class="nav-item">
                        <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Persons">Person</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                    </li>
                </ul>
            </div>
        </div>
    </nav>
</header>
HTML

¿Por qué debe coincidir exactamente la acción asp?

El atributo asp-action usa los tag helpers de ASP.NET Core para generar el URL correcto según tu configuración de rutas. Una coincidencia exacta garantiza que el enlace resuelva la acción correcta del controlador. Los desajustes dan lugar a errores 404 o a acciones no deseadas. El sistema de ayuda de etiquetas distingue entre mayúsculas y minúsculas y debe coincidir con el nombre exacto del método en su controlador.

¿Qué ocurre si los enlaces de navegación no coinciden?

Cuando los enlaces de navegación no coinciden con las acciones del controlador, los usuarios se encuentran con errores 404 o son redirigidos a páginas incorrectas. Durante el desarrollo, la página de excepciones del desarrollador de ASP.NET Core muestra errores de enrutamiento detallados. En producción, los usuarios ven páginas de error genéricas. Compruebe siempre que los enlaces de navegación coincidan exactamente con los nombres de las acciones de los controladores para evitar que se interrumpa la experiencia del usuario.

¿Cómo edito el archivo Program.cs?

Registra la interfaz IHttpContextAccessor y IRazorViewRenderer en el contenedor de inyección de dependencias (DI). Consulte el código siguiente como referencia.

using IronPdf.Extensions.Mvc.Core;
using Microsoft.AspNetCore.Mvc.ViewFeatures;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews();

builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
builder.Services.AddSingleton<ITempDataProvider, CookieTempDataProvider>();

// Register IRazorViewRenderer here
builder.Services.AddSingleton<IRazorViewRenderer, RazorViewRenderer>();

// Optional: Configure IronPDF license if you have one
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY-HERE";

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();
using IronPdf.Extensions.Mvc.Core;
using Microsoft.AspNetCore.Mvc.ViewFeatures;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews();

builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
builder.Services.AddSingleton<ITempDataProvider, CookieTempDataProvider>();

// Register IRazorViewRenderer here
builder.Services.AddSingleton<IRazorViewRenderer, RazorViewRenderer>();

// Optional: Configure IronPDF license if you have one
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY-HERE";

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();
Imports IronPdf.Extensions.Mvc.Core
Imports Microsoft.AspNetCore.Mvc.ViewFeatures

Dim builder = WebApplication.CreateBuilder(args)

' Add services to the container.
builder.Services.AddControllersWithViews()

builder.Services.AddSingleton(Of IHttpContextAccessor, HttpContextAccessor)()
builder.Services.AddSingleton(Of ITempDataProvider, CookieTempDataProvider)()

' Register IRazorViewRenderer here
builder.Services.AddSingleton(Of IRazorViewRenderer, RazorViewRenderer)()

' Optional: Configure IronPDF license if you have one
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY-HERE"

Dim app = builder.Build()

' Configure the HTTP request pipeline.
If Not app.Environment.IsDevelopment() Then
    app.UseExceptionHandler("/Home/Error")
    ' The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts()
End If

app.UseHttpsRedirection()
app.UseStaticFiles()

app.UseRouting()

app.UseAuthorization()

app.MapControllerRoute(
    name:="default",
    pattern:="{controller=Home}/{action=Index}/{id?}")

app.Run()
$vbLabelText   $csharpLabel

¿Por qué registrar servicios como Singleton?

Los servicios singleton se crean una vez y se reutilizan durante toda la vida de la aplicación, lo que los hace eficientes para servicios sin estado como IRazorViewRenderer. Este patrón reduce la sobrecarga de memoria y mejora el rendimiento, ya que el servicio de representación de vistas no mantiene el estado específico de las solicitudes. El IHttpContextAccessor debe ser singleton para ser accesible a través de diferentes ciclos de vida de servicio.

¿Para qué se utiliza ITempDataProvider?

El ITempDataProvider permite el almacenamiento temporal de datos entre solicitudes, comúnmente usado para mostrar mensajes después de redireccionamientos. En el contexto de la generación de PDF, garantiza que el estado de la vista se mantenga correctamente al renderizar vistas a PDF. El CookieTempDataProvider almacena estos datos temporales en cookies encriptadas, proporcionando un mecanismo seguro para la gestión de estado.

¿Puedo utilizar Scoped Services en su lugar?

Aunque podrías usar servicios con ámbito para algunos escenarios, IRazorViewRenderer funciona mejor como un singleton porque no mantiene un estado específico de la solicitud. El uso de scoped services crearía nuevas instancias para cada solicitud, lo que aumentaría el uso de memoria sin ningún beneficio. Sin embargo, si necesita inyectar servicios de ámbito en sus vistas, asegúrese de gestionar correctamente la vida útil del servicio para evitar errores en tiempo de ejecución.

Ejecutar el proyecto

Aquí se muestra cómo ejecutar el proyecto y generar un documento PDF. Cuando ejecutes la aplicación, navega a la página Persons usando el menú de navegación superior, luego haz clic en el botón Print Person para generar y descargar el PDF.

Visual Studio showing HomeController.cs with ASP.NET Core MVC controller code and IntelliSense assistance

¿Dónde puedo descargar el proyecto ASP.NET Core MVC?

Descargue el código completo de esta guía. Viene como un archivo comprimido que puede abrir en Visual Studio como un proyecto ASP.NET Core Web App (Modelo-Vista-Controlador).

Descargar el Proyecto Muestra de ASP.NET Core MVC

¿Qué incluye el proyecto de muestra?

El proyecto de muestra incluye una aplicación ASP.NET Core MVC totalmente configurada con integración IronPDF, que demuestra la conversión de vista a PDF. Contiene el modelo Person, HomeController con la lógica de generación de PDF, Persons vista con sintaxis correcta de Razor y todos los registros de servicios necesarios en Program.cs. El proyecto también incluye ejemplos de configuraciones de estilo y maquetación optimizadas para PDF.

¿Qué versión de Visual Studio debo utilizar?

Se recomienda Visual Studio 2022 (versión 17.0 o posterior) para obtener la mejor experiencia con proyectos .NET 6+. Visual Studio Code con extensiones de C# también funciona bien para el desarrollo multiplataforma. Asegúrese de tener instalada la carga de trabajo ASP.NET y de desarrollo web. El proyecto está orientado a .NET 6.0 por defecto, pero puede actualizarse a versiones más recientes.

¿Cómo solucionar problemas de configuración de proyectos?

Los problemas de configuración más comunes son la falta de paquetes NuGet, versiones incorrectas del SDK de .NET o problemas de configuración. Primero, restaura los paquetes NuGet usando dotnet restore o a través del Administrador de Paquetes de Visual Studio. Verifica que tu versión de SDK de .NET coincida con los requisitos del proyecto usando dotnet --version. Para cuestiones de licencias, consulte la documentación sobre claves de licencia. Si surgen problemas de renderización, consulte la guía de solución de problemas.

¿Listo para ver qué más puedes hacer? Consulta nuestra página de tutoriales aquí: Convertir PDFs

Portales de facturación española con ASP.NET Core MVC y IronPDF

El patrón de convertir vistas MVC a PDF es especialmente valioso para los ISVs y empresas españolas que construyen portales de facturación electrónica. A continuación se describen los casos de uso más relevantes en el contexto normativo español:

  • Portales VeriFactu multi-tenant con vistas Razor: Los ISVs españoles que desarrollan software de facturación VeriFactu para múltiples clientes utilizan ASP.NET Core MVC como arquitectura base. Cada factura generada en la vista Razor puede convertirse simultáneamente a PDF con RenderRazorViewToPdf para su almacenamiento como representación gráfica requerida. Los portales multi-tenant comparten el controlador pero parametrizan la vista con los datos del emisor, eliminando la necesidad de un servicio de generación de PDF independiente.

  • Generación de PDF para la plataforma FACe desde vistas MVC: Las aplicaciones que gestionan el envío de facturas B2G a través de FACe utilizan vistas Razor para el diseño de la factura y convierten estas vistas a PDF como adjunto del XML Facturae. El controlador MVC coordina la generación del XML, la creación del PDF con IronPDF y el envío a la plataforma en una sola acción.

  • Preview de facturas Facturae antes del envío: Los portales de gestión documental presentan al usuario una previsualización de la factura en formato HTML (vista Razor) y, con el mismo modelo de datos, generan el PDF definitivo para firma y envío. IronPDF garantiza que la representación HTML y el PDF resultante son visualmente idénticos, lo que simplifica la validación por parte del usuario.

  • Aplicaciones SaaS de facturación para pymes españolas bajo Crea y Crece: La ley Crea y Crece obligará a las pymes españolas a emitir facturas electrónicas B2B a partir de 2027-2028. Las plataformas SaaS que se anticipan a este requisito adoptan ASP.NET Core MVC como framework y delegan en IronPDF la generación del PDF de representación, cumpliendo así con los requisitos de entrega de factura al receptor en formato legible.

  • Integración con certificados FNMT para firma del PDF generado: Una vez obtenido el PdfDocument tras la conversión de la vista Razor, los portales españoles aplican la firma PAdES con certificados emitidos por la FNMT o validados mediante Cl@ve, garantizando la validez legal del documento bajo el reglamento eIDAS.

Preguntas Frecuentes

¿Cuál es la forma más sencilla de convertir vistas CSHTML a PDF en ASP.NET Core MVC?

La forma más sencilla es utilizar el método RenderRazorViewToPdf de IronPDF, que puede convertir sus archivos .cshtml en documentos PDF con una sola línea de código. Simplemente llame a: new IronPdf.ChromePdfRenderer().RenderRazorViewToPdf(HttpContext, "Views/Home/Report.cshtml", model).SaveAs("report.pdf");

¿Qué paquetes NuGet necesito para convertir vistas en PDF en ASP.NET Core MVC?

Se necesitan dos paquetes: IronPDF (el paquete principal) y IronPdf.Extensions.Mvc.Core (el paquete de extensión). El paquete de extensión proporciona funciones específicas para la integración con el sistema de inyección de dependencias de ASP.NET Core y el canal de renderización de vistas Razor.

¿Puedo aplicar estilos CSS y JavaScript al convertir CSHTML a PDF?

Sí, IronPDF es totalmente compatible con el estilo CSS, la ejecución de JavaScript y las fuentes personalizadas al renderizar Vistas a PDF. Esto garantiza que sus PDF mantengan la misma apariencia y funcionalidad que sus vistas web, incluyendo CSS adaptable y contenido JavaScript dinámico.

¿Cuáles son los pasos principales para implementar la conversión de Vista a PDF en mi proyecto ASP.NET Core MVC?

El flujo de trabajo consta de 5 pasos: 1) Descargar IronPDF y su extensión MVC Core, 2) Añadir una clase modelo para sus datos, 3) Editar su Controlador para utilizar el método RenderRazorViewToPdf, 4) Crear o modificar una Vista (archivo .cshtml) para la renderización de PDF, y 5) Ejecutar su aplicación para generar PDFs.

¿Cómo funciona el patrón MVC con la generación de PDF a partir de vistas?

En ASP.NET Core MVC, el Modelo contiene los datos y la lógica de negocio, la Vista (su archivo .cshtml) presenta la interfaz de usuario y muestra los datos, y el Controlador gestiona las solicitudes y utiliza el método RenderRazorViewToPdf de IronPDF para orquestar la generación de PDF desde la Vista.

¿Por qué ASP.NET Core MVC es el stack preferido para construir portales VeriFactu en España?

ASP.NET Core MVC es el framework más utilizado entre los ISVs españoles que desarrollan software de facturación electrónica VeriFactu. Su integración nativa con el ecosistema Microsoft (Azure, SQL Server, Active Directory), el soporte para eIDAS mediante Azure AD y la facilidad de despliegue en Azure España lo convierten en la opción natural. IronPDF se integra directamente en estos proyectos MVC para generar los PDFs de factura requeridos.

¿Cómo uso IronPDF en ASP.NET Core MVC para generar PDFs de facturas para FACe?

FACe (Punto de acceso general de facturas electrónicas) acepta facturas en formato Facturae (XML) con un PDF de cortesía adjunto. En una aplicación ASP.NET Core MVC, puede usar RenderRazorViewToPdf para generar el PDF de cortesía a partir de una vista Razor que contenga todos los campos obligatorios de Facturae (NIF, CIF, importes, tipos impositivos) y adjuntarlo al XML Facturae para su envío a FACe.

Curtis Chau
Escritor Técnico

Curtis Chau tiene una licenciatura en Ciencias de la Computación (Carleton University) y se especializa en el desarrollo front-end con experiencia en Node.js, TypeScript, JavaScript y React. Apasionado por crear interfaces de usuario intuitivas y estéticamente agradables, disfruta trabajando con frameworks modernos y creando manuales bien ...

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 19,014,616 | Versión: 2026.5 just released
Still Scrolling Icon

¿Aún desplazándote?

¿Quieres una prueba rápida? PM > Install-Package IronPdf
ejecutar una muestra Mira cómo tu HTML se convierte en PDF.