Cómo gestionar inicios de sesión y autenticación usando C#

Convertir HTML a PDF con autenticación de inicio de sesión en C#

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

Para convertir HTML a PDF con autenticación de inicio de sesión en C#, utilice ChromeHttpLoginCredentials de IronPDF para la autenticación de red o descargue HTML utilizando System.Net.WebClient/HttpClient antes de la conversión. Este enfoque es eficaz tanto para la autenticación en red como para el inicio de sesión mediante formularios HTML.

Inicio Rápido: Convertir HTML a PDF Detrás de un Inicio de Sesión con IronPDF

Convierta páginas HTML en PDF detrás de formularios de inicio de sesión utilizando la API de IronPDF. Esta guía muestra ChromeHttpLoginCredentials para la autenticación y la recuperación de contenido protegido. Maneja tanto la autenticación de red como los inicios de sesión mediante formularios HTML con ejemplos de código sencillos.

Nuget IconEmpieza a crear PDF con NuGet ahora:

  1. Instalar IronPDF con el gestor de paquetes NuGet

    PM > Install-Package IronPdf

  2. Copie y ejecute este fragmento de código.

    new ChromePdfRenderer { LoginCredentials = new ChromeHttpLoginCredentials("username","password") }
        .RenderUrlAsPdf("https://example.com/protected")
        .SaveAs("secure.pdf");
  3. Despliegue para probar en su entorno real

    Empieza a utilizar IronPDF en tu proyecto hoy mismo con una prueba gratuita
    arrow pointer


¿Cuáles son las mejores prácticas para manejar la autenticación de inicio de sesión?

IronPDF admite la autenticación de red TLS (nombre de usuario y contraseña) a través de la API ChromeHttpLoginCredentials. Para obtener una guía completa sobre varios escenarios de inicio de sesión, consulte el tutorial TLS Website & System Logins.

Se recomienda utilizar System.Net.WebClient o HttpClient para descargar HTML y activos. Este método admite cabeceras, inicios de sesión y otros requisitos. Tras la descarga en memoria o disco, IronPDF convierte el HTML a PDF. Extraiga activos como hojas de estilo e imágenes con HtmlAgilityPack y, a continuación, descárguelos con System.Net.WebClient.

// Download HTML content from a URL with authentication
string html;
using (WebClient client = new WebClient()) 
{
    // Add authentication headers if needed
    client.Headers.Add("Authorization", "Bearer " + accessToken);

    // Download the HTML string
    html = client.DownloadString("http://www.example.com/protected-content");
}

// Load the HTML into an HtmlDocument for parsing
HtmlDocument doc = new HtmlDocument();        
doc.LoadHtml(html);

// Extract all image sources for downloading
foreach(HtmlNode img in doc.DocumentNode.SelectNodes("//img")) 
{
    string imgSrc = img.GetAttributeValue("src", null);
    Console.WriteLine($"Found image: {imgSrc}");

    // Download each image asset
    if (!string.IsNullOrEmpty(imgSrc))
    {
        string fileName = Path.GetFileName(imgSrc);
        client.DownloadFile(imgSrc, fileName);
    }
}

// Convert the downloaded HTML to PDF
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("authenticated-content.pdf");
// Download HTML content from a URL with authentication
string html;
using (WebClient client = new WebClient()) 
{
    // Add authentication headers if needed
    client.Headers.Add("Authorization", "Bearer " + accessToken);

    // Download the HTML string
    html = client.DownloadString("http://www.example.com/protected-content");
}

// Load the HTML into an HtmlDocument for parsing
HtmlDocument doc = new HtmlDocument();        
doc.LoadHtml(html);

// Extract all image sources for downloading
foreach(HtmlNode img in doc.DocumentNode.SelectNodes("//img")) 
{
    string imgSrc = img.GetAttributeValue("src", null);
    Console.WriteLine($"Found image: {imgSrc}");

    // Download each image asset
    if (!string.IsNullOrEmpty(imgSrc))
    {
        string fileName = Path.GetFileName(imgSrc);
        client.DownloadFile(imgSrc, fileName);
    }
}

// Convert the downloaded HTML to PDF
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("authenticated-content.pdf");
$vbLabelText   $csharpLabel

Por favor notaRebase URLs relativas a URLs absolutas usando el constructor sobrecargado System.Uri. Para volver a basar todas las rutas relativas en un documento HTML, añada una etiqueta <base> a la cabecera utilizando HtmlAgilityPack. Ejemplo. Para obtener más información sobre el manejo de URL y activos, consulte la guía Base URLs & Asset Encoding.

¿Por qué debo descargar primero el contenido HTML?

Descargar el contenido HTML antes de convertirlo ofrece varias ventajas:

  1. Control total: Modifica HTML, corrige enlaces rotos o inyecta tokens de autenticación antes de la conversión
  2. Gestión de activos: Descarga y almacena en caché recursos externos como imágenes, CSS y archivos JavaScript
  3. Flexibilidad de autenticación: Utiliza cualquier mecanismo de autenticación .NET incluyendo OAuth, tokens JWT o cabeceras personalizadas
  4. Rendimiento: Almacena en caché el contenido al que se accede con frecuencia para reducir la carga del servidor
  5. Debugging: Inspeccionar el HTML exacto que se está convirtiendo para solucionar problemas

Para situaciones complejas de autenticación que impliquen cookies y sesiones, consulte la Guía de cookies, que explica la gestión del estado de autenticación durante la conversión de PDF.

¿Cómo manejo activos como imágenes y hojas de estilo?

Al convertir páginas autenticadas, los activos externos suelen requerir la misma autenticación. He aquí un enfoque exhaustivo utilizando HttpClient:

public async Task<string> DownloadAuthenticatedHtmlWithAssets(string url, string authToken)
{
    using (var client = new HttpClient())
    {
        // Set authentication header
        client.DefaultRequestHeaders.Authorization = 
            new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authToken);

        // Download the main HTML
        string html = await client.GetStringAsync(url);

        // Parse HTML to find assets
        var doc = new HtmlDocument();
        doc.LoadHtml(html);

        // Create a base URI for resolving relative paths
        var baseUri = new Uri(url);

        // Download CSS files
        var cssLinks = doc.DocumentNode.SelectNodes("//link[@rel='stylesheet']");
        if (cssLinks != null)
        {
            foreach (var link in cssLinks)
            {
                string href = link.GetAttributeValue("href", "");
                if (!string.IsNullOrEmpty(href))
                {
                    var cssUri = new Uri(baseUri, href);
                    string cssContent = await client.GetStringAsync(cssUri);

                    // Embed CSS directly in the HTML
                    var styleNode = doc.CreateElement("style");
                    styleNode.InnerHtml = cssContent;
                    doc.DocumentNode.SelectSingleNode("//head").AppendChild(styleNode);

                    // Remove the external link
                    link.Remove();
                }
            }
        }

        // Return the modified HTML with embedded assets
        return doc.DocumentNode.OuterHtml;
    }
}
public async Task<string> DownloadAuthenticatedHtmlWithAssets(string url, string authToken)
{
    using (var client = new HttpClient())
    {
        // Set authentication header
        client.DefaultRequestHeaders.Authorization = 
            new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authToken);

        // Download the main HTML
        string html = await client.GetStringAsync(url);

        // Parse HTML to find assets
        var doc = new HtmlDocument();
        doc.LoadHtml(html);

        // Create a base URI for resolving relative paths
        var baseUri = new Uri(url);

        // Download CSS files
        var cssLinks = doc.DocumentNode.SelectNodes("//link[@rel='stylesheet']");
        if (cssLinks != null)
        {
            foreach (var link in cssLinks)
            {
                string href = link.GetAttributeValue("href", "");
                if (!string.IsNullOrEmpty(href))
                {
                    var cssUri = new Uri(baseUri, href);
                    string cssContent = await client.GetStringAsync(cssUri);

                    // Embed CSS directly in the HTML
                    var styleNode = doc.CreateElement("style");
                    styleNode.InnerHtml = cssContent;
                    doc.DocumentNode.SelectSingleNode("//head").AppendChild(styleNode);

                    // Remove the external link
                    link.Remove();
                }
            }
        }

        // Return the modified HTML with embedded assets
        return doc.DocumentNode.OuterHtml;
    }
}
$vbLabelText   $csharpLabel

¿Qué herramientas ayudan a analizar HTML?

HtmlAgilityPack es la biblioteca de análisis sintáctico de HTML más popular para .NET, pero existen alternativas:

  1. HtmlAgilityPack: Lo mejor para el análisis sintáctico y la manipulación de HTML en general
  2. AngleSharp: Analizador HTML moderno y conforme a los estándares con soporte para selectores CSS
  3. CsQuery: sintaxis similar a jQuery para desarrolladores de C# familiarizados con jQuery
  4. Expresiones regulares: Para tareas de extracción sencillas (no recomendadas para HTML complejo)

¿Cómo iniciar sesión con autenticación de red?

La mayoría de las aplicaciones ASP.NET admiten autenticación de red, que es más confiable que el envío de formularios HTML. IronPDF proporciona soporte integrado para autenticación básica, digest y NTLM a través de la clase ChromeHttpLoginCredentials. Para obtener más información sobre la personalización de cabeceras, consulte la guía HTTP Request Header guide.

:path=/static-assets/pdf/content-code-examples/how-to/logins-username-password.cs
using IronPdf;
using System;

ChromePdfRenderer renderer = new ChromePdfRenderer
{
    // setting login credentials to bypass basic authentication
    LoginCredentials = new ChromeHttpLoginCredentials()
    {
        NetworkUsername = "testUser",
        NetworkPassword = "testPassword"
    }
};

var uri = new Uri("http://localhost:51169/Invoice");

// Render web URL to PDF
PdfDocument pdf = renderer.RenderUrlAsPdf(uri);

// Export PDF
pdf.SaveAs("UrlToPdfExample.Pdf");
$vbLabelText   $csharpLabel

¿Por qué la autenticación de red es más fiable que la publicación de formularios?

La autenticación en red ofrece varias ventajas sobre la publicación de formularios HTML:

  1. Protocolo estandarizado: Utiliza cabeceras de autenticación HTTP siguiendo los estándares RFC
  2. Integración con el navegador: El motor de renderizado de Chrome gestiona la autenticación sin problemas
  3. Gestión de sesiones: Gestión automática de retos de autenticación y persistencia de sesión
  4. Seguridad: Las credenciales se transmiten de forma segura a través de las cabeceras en lugar de los datos del formulario
  5. Compatibilidad: Funciona con la mayoría de los sistemas de autenticación empresariales (Active Directory, LDAP)

¿Qué credenciales necesito para la autenticación de red?

Los distintos tipos de autenticación requieren credenciales diferentes:

// Basic Authentication (most common)
var basicAuth = new ChromeHttpLoginCredentials
{
    NetworkUsername = "user@domain.com",
    NetworkPassword = "password123",
    AuthenticationType = ChromeHttpLoginCredentials.AuthType.Basic
};

// NTLM/Windows Authentication
var ntlmAuth = new ChromeHttpLoginCredentials
{
    NetworkUsername = "DOMAIN\\username", // Include domain
    NetworkPassword = "password123",
    AuthenticationType = ChromeHttpLoginCredentials.AuthType.Ntlm
};

// Custom authentication headers
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.CustomHttpHeaders.Add("X-API-Key", "your-api-key");
renderer.RenderingOptions.CustomHttpHeaders.Add("Authorization", "Bearer " + jwtToken);
// Basic Authentication (most common)
var basicAuth = new ChromeHttpLoginCredentials
{
    NetworkUsername = "user@domain.com",
    NetworkPassword = "password123",
    AuthenticationType = ChromeHttpLoginCredentials.AuthType.Basic
};

// NTLM/Windows Authentication
var ntlmAuth = new ChromeHttpLoginCredentials
{
    NetworkUsername = "DOMAIN\\username", // Include domain
    NetworkPassword = "password123",
    AuthenticationType = ChromeHttpLoginCredentials.AuthType.Ntlm
};

// Custom authentication headers
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.CustomHttpHeaders.Add("X-API-Key", "your-api-key");
renderer.RenderingOptions.CustomHttpHeaders.Add("Authorization", "Bearer " + jwtToken);
$vbLabelText   $csharpLabel

¿Cómo solucionar problemas de autenticación?

Problemas comunes de autenticación y soluciones:

  1. 401 No autorizado: Comprobar credenciales y tipo de autenticación
  2. 403 Prohibido: Usuario autenticado pero carece de permisos
  3. Timeout Errors: Aumentar RenderDelay para sistemas de autenticación lentos
  4. Errores de certificado: Configure adecuadamente los ajustes TLS/SSL

Permitir la depuración para diagnosticar problemas:

// Enable detailed logging
IronPdf.Logging.Logger.EnableDebugging = true;
IronPdf.Logging.Logger.LogFilePath = "IronPdf.log";
IronPdf.Logging.Logger.LoggingMode = IronPdf.Logging.Logger.LoggingModes.All;

// Test authentication
try 
{
    var pdf = renderer.RenderUrlAsPdf("https://secure.example.com");
    pdf.SaveAs("authenticated.pdf");
}
catch (Exception ex)
{
    Console.WriteLine($"Authentication failed: {ex.Message}");
    // Check IronPdf.log for detailed error information
}
// Enable detailed logging
IronPdf.Logging.Logger.EnableDebugging = true;
IronPdf.Logging.Logger.LogFilePath = "IronPdf.log";
IronPdf.Logging.Logger.LoggingMode = IronPdf.Logging.Logger.LoggingModes.All;

// Test authentication
try 
{
    var pdf = renderer.RenderUrlAsPdf("https://secure.example.com");
    pdf.SaveAs("authenticated.pdf");
}
catch (Exception ex)
{
    Console.WriteLine($"Authentication failed: {ex.Message}");
    // Check IronPdf.log for detailed error information
}
$vbLabelText   $csharpLabel

¿Cómo iniciar sesión con un formulario HTML?

Para iniciar sesión enviando datos a un formulario HTML, utilice la clase ChromeHttpLoginCredentials. Vea la API ChromeHttpLoginCredentials de IronPDF

Considere estos puntos:

  • Publique los datos de acceso en la URL especificada en el atributo ACTION del formulario HTML. Establézcalo como el atributo LoginFormUrl de HttpLoginCredentials. Esto puede diferir de la URL que desea representar como PDF.
  • Envíe datos que representen cada entrada y área de texto del formulario HTML. Los atributos name definen el nombre de cada variable (no el id).
  • Algunos sitios web protegen activamente contra el inicio de sesión automático.

He aquí un ejemplo completo de autenticación basada en formularios:

// Configure form-based login
var formLogin = new ChromeHttpLoginCredentials
{
    LoginFormUrl = "https://example.com/login",
    LoginFormData = new Dictionary<string, string>
    {
        {"username", "user@example.com"},
        {"password", "securePassword123"},
        {"rememberMe", "true"},
        {"csrf_token", "abc123"} // Include any hidden fields
    }
};

var renderer = new ChromePdfRenderer
{
    LoginCredentials = formLogin,
    RenderingOptions = new ChromePdfRenderOptions
    {
        RenderDelay = 3000, // Allow time for login redirect
        EnableJavaScript = true
    }
};

// The actual page you want to convert (after login)
var pdf = renderer.RenderUrlAsPdf("https://example.com/dashboard");
pdf.SaveAs("dashboard.pdf");
// Configure form-based login
var formLogin = new ChromeHttpLoginCredentials
{
    LoginFormUrl = "https://example.com/login",
    LoginFormData = new Dictionary<string, string>
    {
        {"username", "user@example.com"},
        {"password", "securePassword123"},
        {"rememberMe", "true"},
        {"csrf_token", "abc123"} // Include any hidden fields
    }
};

var renderer = new ChromePdfRenderer
{
    LoginCredentials = formLogin,
    RenderingOptions = new ChromePdfRenderOptions
    {
        RenderDelay = 3000, // Allow time for login redirect
        EnableJavaScript = true
    }
};

// The actual page you want to convert (after login)
var pdf = renderer.RenderUrlAsPdf("https://example.com/dashboard");
pdf.SaveAs("dashboard.pdf");
$vbLabelText   $csharpLabel

¿Qué datos del formulario necesito capturar?

Para autenticar correctamente mediante formularios HTML, capture todas las entradas del formulario:

// Use this helper method to extract form fields
public Dictionary<string, string> ExtractFormFields(string loginPageHtml)
{
    var formData = new Dictionary<string, string>();
    var doc = new HtmlDocument();
    doc.LoadHtml(loginPageHtml);

    // Find all input fields
    var inputs = doc.DocumentNode.SelectNodes("//input");
    if (inputs != null)
    {
        foreach (var input in inputs)
        {
            string name = input.GetAttributeValue("name", "");
            string value = input.GetAttributeValue("value", "");
            string type = input.GetAttributeValue("type", "text");

            if (!string.IsNullOrEmpty(name))
            {
                // Handle different input types
                switch (type.ToLower())
                {
                    case "checkbox":
                        if (input.Attributes["checked"] != null)
                            formData[name] = "on";
                        break;
                    case "radio":
                        if (input.Attributes["checked"] != null)
                            formData[name] = value;
                        break;
                    default:
                        formData[name] = value;
                        break;
                }
            }
        }
    }

    // Don't forget select elements
    var selects = doc.DocumentNode.SelectNodes("//select");
    if (selects != null)
    {
        foreach (var select in selects)
        {
            string name = select.GetAttributeValue("name", "");
            var selected = select.SelectSingleNode(".//option[@selected]");
            if (selected != null && !string.IsNullOrEmpty(name))
            {
                formData[name] = selected.GetAttributeValue("value", "");
            }
        }
    }

    return formData;
}
// Use this helper method to extract form fields
public Dictionary<string, string> ExtractFormFields(string loginPageHtml)
{
    var formData = new Dictionary<string, string>();
    var doc = new HtmlDocument();
    doc.LoadHtml(loginPageHtml);

    // Find all input fields
    var inputs = doc.DocumentNode.SelectNodes("//input");
    if (inputs != null)
    {
        foreach (var input in inputs)
        {
            string name = input.GetAttributeValue("name", "");
            string value = input.GetAttributeValue("value", "");
            string type = input.GetAttributeValue("type", "text");

            if (!string.IsNullOrEmpty(name))
            {
                // Handle different input types
                switch (type.ToLower())
                {
                    case "checkbox":
                        if (input.Attributes["checked"] != null)
                            formData[name] = "on";
                        break;
                    case "radio":
                        if (input.Attributes["checked"] != null)
                            formData[name] = value;
                        break;
                    default:
                        formData[name] = value;
                        break;
                }
            }
        }
    }

    // Don't forget select elements
    var selects = doc.DocumentNode.SelectNodes("//select");
    if (selects != null)
    {
        foreach (var select in selects)
        {
            string name = select.GetAttributeValue("name", "");
            var selected = select.SelectSingleNode(".//option[@selected]");
            if (selected != null && !string.IsNullOrEmpty(name))
            {
                formData[name] = selected.GetAttributeValue("value", "");
            }
        }
    }

    return formData;
}
$vbLabelText   $csharpLabel

¿Cómo encontrar la URL de acción de formulario correcta?

La URL de acción del formulario es fundamental para que la autenticación se realice correctamente:

public string ExtractFormAction(string loginPageUrl, string loginPageHtml)
{
    var doc = new HtmlDocument();
    doc.LoadHtml(loginPageHtml);

    // Find the login form
    var form = doc.DocumentNode.SelectSingleNode("//form[contains(@action, 'login') or contains(@id, 'login') or contains(@class, 'login')]");

    if (form == null)
    {
        // Try finding any form with password field
        form = doc.DocumentNode.SelectSingleNode("//form[.//input[@type='password']]");
    }

    if (form != null)
    {
        string action = form.GetAttributeValue("action", "");

        // Resolve relative URLs
        if (!string.IsNullOrEmpty(action))
        {
            var baseUri = new Uri(loginPageUrl);
            var actionUri = new Uri(baseUri, action);
            return actionUri.ToString();
        }
    }

    // Default to the login page URL if no action found
    return loginPageUrl;
}
public string ExtractFormAction(string loginPageUrl, string loginPageHtml)
{
    var doc = new HtmlDocument();
    doc.LoadHtml(loginPageHtml);

    // Find the login form
    var form = doc.DocumentNode.SelectSingleNode("//form[contains(@action, 'login') or contains(@id, 'login') or contains(@class, 'login')]");

    if (form == null)
    {
        // Try finding any form with password field
        form = doc.DocumentNode.SelectSingleNode("//form[.//input[@type='password']]");
    }

    if (form != null)
    {
        string action = form.GetAttributeValue("action", "");

        // Resolve relative URLs
        if (!string.IsNullOrEmpty(action))
        {
            var baseUri = new Uri(loginPageUrl);
            var actionUri = new Uri(baseUri, action);
            return actionUri.ToString();
        }
    }

    // Default to the login page URL if no action found
    return loginPageUrl;
}
$vbLabelText   $csharpLabel

¿Cuáles son los problemas comunes de la autenticación basada en formularios?

  1. TokenCSRF: Muchos formularios incluyen tokens antifalsificación que caducan
  2. Validación de JavaScript: Algunos formularios requieren la ejecución de JavaScript
  3. Autenticación en varios pasos: Formularios que requieren varias páginas
  4. Protección CAPTCHA: Desafíos de la verificación humana
  5. Tiempos de espera de sesión: Sesiones de inicio de sesión que caducan rápidamente

¿Cómo manejo la protección anti-bot?

Los sitios web modernos están protegidos contra los inicios de sesión automáticos:

// Strategies for handling anti-bot measures
var renderer = new ChromePdfRenderer
{
    RenderingOptions = new ChromePdfRenderOptions
    {
        // Mimic real browser behavior
        ViewPortWidth = 1920,
        ViewPortHeight = 1080,
        EnableJavaScript = true,
        RenderDelay = 5000, // Wait for JavaScript

        // Set a real user agent
        CustomHttpHeaders = new Dictionary<string, string>
        {
            {"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}
        }
    }
};

 // For sites with rate limiting, add delays between requests
 System.Threading.Thread.Sleep(2000);
// Strategies for handling anti-bot measures
var renderer = new ChromePdfRenderer
{
    RenderingOptions = new ChromePdfRenderOptions
    {
        // Mimic real browser behavior
        ViewPortWidth = 1920,
        ViewPortHeight = 1080,
        EnableJavaScript = true,
        RenderDelay = 5000, // Wait for JavaScript

        // Set a real user agent
        CustomHttpHeaders = new Dictionary<string, string>
        {
            {"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}
        }
    }
};

 // For sites with rate limiting, add delays between requests
 System.Threading.Thread.Sleep(2000);
$vbLabelText   $csharpLabel

Para obtener información completa sobre la conversión de HTML a PDF, incluidas situaciones complejas de autenticación, visite el Tutorial de HTML a PDF.

¿Cómo manejo la autenticación MVC?

La siguiente solución convierte una vista MVC de .NET en una cadena mediante programación, lo que evita el inicio de sesión en MVC y reproduce las vistas fielmente. Este enfoque funciona bien al convertir CSHTML a PDF en MVC Core o MVC Framework.

// Converts an MVC partial view to a string
public static string RenderPartialViewToString(this Controller controller, string viewPath, object model = null)
{
    try
    {
        // Set the model
        var context = controller.ControllerContext;
        controller.ViewData.Model = model;

        using (var sw = new StringWriter())
        {
            // Find the partial view
            var viewResult = ViewEngines.Engines.FindPartialView(context, viewPath);

            if (viewResult.View == null)
            {
                throw new Exception($"Partial view {viewPath} could not be found.");
            }

            // Create a view context
            var viewContext = new ViewContext(context, viewResult.View, context.Controller.ViewData, context.Controller.TempData, sw);

            // Render the view
            viewResult.View.Render(viewContext, sw);
            viewResult.ViewEngine.ReleaseView(context, viewResult.View);

            return sw.GetStringBuilder().ToString();
        }
    }
    catch (Exception ex)
    {
        // Return error message if there is an exception
        return ex.Message;
    }
}

// Usage in an MVC Controller
public ActionResult GeneratePdf()
{
    // Render authenticated view to string
    var model = new InvoiceViewModel { /* populate model */ };
    string html = this.RenderPartialViewToString("~/Views/Invoice/Details.cshtml", model);

    // Convert to PDF
    var renderer = new ChromePdfRenderer();
    var pdf = renderer.RenderHtmlAsPdf(html);

    // Return PDF file
    return File(pdf.BinaryData, "application/pdf", "invoice.pdf");
}
// Converts an MVC partial view to a string
public static string RenderPartialViewToString(this Controller controller, string viewPath, object model = null)
{
    try
    {
        // Set the model
        var context = controller.ControllerContext;
        controller.ViewData.Model = model;

        using (var sw = new StringWriter())
        {
            // Find the partial view
            var viewResult = ViewEngines.Engines.FindPartialView(context, viewPath);

            if (viewResult.View == null)
            {
                throw new Exception($"Partial view {viewPath} could not be found.");
            }

            // Create a view context
            var viewContext = new ViewContext(context, viewResult.View, context.Controller.ViewData, context.Controller.TempData, sw);

            // Render the view
            viewResult.View.Render(viewContext, sw);
            viewResult.ViewEngine.ReleaseView(context, viewResult.View);

            return sw.GetStringBuilder().ToString();
        }
    }
    catch (Exception ex)
    {
        // Return error message if there is an exception
        return ex.Message;
    }
}

// Usage in an MVC Controller
public ActionResult GeneratePdf()
{
    // Render authenticated view to string
    var model = new InvoiceViewModel { /* populate model */ };
    string html = this.RenderPartialViewToString("~/Views/Invoice/Details.cshtml", model);

    // Convert to PDF
    var renderer = new ChromePdfRenderer();
    var pdf = renderer.RenderHtmlAsPdf(html);

    // Return PDF file
    return File(pdf.BinaryData, "application/pdf", "invoice.pdf");
}
$vbLabelText   $csharpLabel

¿Por qué renderizar vistas a cadenas en lugar de conversión directa?

La conversión de vistas MVC a cadenas de texto ofrece varias ventajas clave:

  1. Contexto de autenticación: Las vistas se renderizan dentro del contexto del usuario autenticado
  2. Full MVC Pipeline: Todas las características MVC funcionan incluyendo ViewBag, TempData, y Html helpers
  3. Soporte de diseño: Las páginas maestras y los diseños se renderizan correctamente
  4. Model Binding: Los modelos de vista complejos funcionan a la perfección
  5. Filtros de acción: los filtros de seguridad y registro se ejecutan con normalidad

¿Cuáles son las ventajas de esta solución MVC?

El enfoque de representación de cadenas MVC ofrece:

  • Seguridad: No es necesario exponer URL internas ni saltarse la autenticación
  • Rendimiento: Evitar peticiones HTTP adicionales
  • Consistencia: Salida idéntica a la que los usuarios ven en los navegadores
  • Flexibilidad: Modificar HTML antes de la conversión a PDF
  • Pruebas: Generación de HTML para pruebas unitarias de forma sencilla

¿Cómo paso modelos a la vista renderizada?

He aquí un ejemplo completo con un modelo complejo:

public class InvoiceController : Controller
{
    private readonly IInvoiceService _invoiceService;

    public async Task<ActionResult> DownloadInvoicePdf(int invoiceId)
    {
        // Load data within authenticated context
        var invoice = await _invoiceService.GetInvoiceAsync(invoiceId);

        if (invoice == null || invoice.UserId != User.Identity.GetUserId())
        {
            return HttpNotFound();
        }

        // Create view model
        var viewModel = new InvoiceDetailsViewModel
        {
            Invoice = invoice,
            Company = await _invoiceService.GetCompanyDetailsAsync(),
            LineItems = await _invoiceService.GetLineItemsAsync(invoiceId),
            TaxDetails = await _invoiceService.GetTaxDetailsAsync(invoiceId)
        };

        // Render to HTML string
        string html = this.RenderPartialViewToString("~/Views/Invoice/DetailsPdf.cshtml", viewModel);

        // Add custom styling for PDF
        html = $@"
            <html>
            <head>
                <style>
                    body {{ font-family: Arial, sans-serif; }}
                    .invoice-header {{ background-color: #f0f0f0; padding: 20px; }}
                    .line-items {{ width: 100%; border-collapse: collapse; }}
                    .line-items th, .line-items td {{ border: 1px solid #ddd; padding: 8px; }}
                </style>
            </head>
            <body>
                {html}
            </body>
            </html>";

        // Convert to PDF with options
        var renderer = new ChromePdfRenderer
        {
            RenderingOptions = new ChromePdfRenderOptions
            {
                MarginTop = 20,
                MarginBottom = 20,
                MarginLeft = 10,
                MarginRight = 10,
                PrintHtmlBackgrounds = true
            }
        };

        var pdf = renderer.RenderHtmlAsPdf(html);

        // Add metadata
        pdf.MetaData.Author = "Invoice System";
        pdf.MetaData.Title = $"Invoice #{invoice.Number}";
        pdf.MetaData.CreationDate = DateTime.Now;

        return File(pdf.BinaryData, "application/pdf", $"Invoice-{invoice.Number}.pdf");
    }
}
public class InvoiceController : Controller
{
    private readonly IInvoiceService _invoiceService;

    public async Task<ActionResult> DownloadInvoicePdf(int invoiceId)
    {
        // Load data within authenticated context
        var invoice = await _invoiceService.GetInvoiceAsync(invoiceId);

        if (invoice == null || invoice.UserId != User.Identity.GetUserId())
        {
            return HttpNotFound();
        }

        // Create view model
        var viewModel = new InvoiceDetailsViewModel
        {
            Invoice = invoice,
            Company = await _invoiceService.GetCompanyDetailsAsync(),
            LineItems = await _invoiceService.GetLineItemsAsync(invoiceId),
            TaxDetails = await _invoiceService.GetTaxDetailsAsync(invoiceId)
        };

        // Render to HTML string
        string html = this.RenderPartialViewToString("~/Views/Invoice/DetailsPdf.cshtml", viewModel);

        // Add custom styling for PDF
        html = $@"
            <html>
            <head>
                <style>
                    body {{ font-family: Arial, sans-serif; }}
                    .invoice-header {{ background-color: #f0f0f0; padding: 20px; }}
                    .line-items {{ width: 100%; border-collapse: collapse; }}
                    .line-items th, .line-items td {{ border: 1px solid #ddd; padding: 8px; }}
                </style>
            </head>
            <body>
                {html}
            </body>
            </html>";

        // Convert to PDF with options
        var renderer = new ChromePdfRenderer
        {
            RenderingOptions = new ChromePdfRenderOptions
            {
                MarginTop = 20,
                MarginBottom = 20,
                MarginLeft = 10,
                MarginRight = 10,
                PrintHtmlBackgrounds = true
            }
        };

        var pdf = renderer.RenderHtmlAsPdf(html);

        // Add metadata
        pdf.MetaData.Author = "Invoice System";
        pdf.MetaData.Title = $"Invoice #{invoice.Number}";
        pdf.MetaData.CreationDate = DateTime.Now;

        return File(pdf.BinaryData, "application/pdf", $"Invoice-{invoice.Number}.pdf");
    }
}
$vbLabelText   $csharpLabel

Antes de implementar cualquier solución de autenticación, asegúrese de haber instalado IronPDF correctamente y de haber configurado sus claves de licencia.

¿Listo para ver qué más puedes hacer? Visite nuestra página de tutoriales: Convertir PDF.

Preguntas Frecuentes

¿Cómo puedo convertir HTML a PDF cuando el contenido está detrás de un formulario de acceso?

IronPDF proporciona múltiples enfoques para convertir HTML a PDF tras la autenticación de inicio de sesión. Puede utilizar la API ChromeHttpLoginCredentials para la autenticación de red TLS, o descargar el contenido HTML utilizando System.Net.WebClient o HttpClient con las cabeceras de autenticación adecuadas antes de convertirlo a PDF con IronPDF.

¿Qué es ChromeHttpLoginCredentials y cómo se utiliza?

ChromeHttpLoginCredentials es la API de IronPDF para manejar la autenticación de red. Puede utilizarla estableciendo la propiedad LoginCredentials en ChromePdfRenderer con su nombre de usuario y contraseña, permitiendo a IronPDF autenticarse automáticamente al renderizar URL protegidas por contraseña a PDF.

¿Puedo gestionar inicios de sesión basados en formularios HTML para la conversión de PDF?

Sí, IronPDF admite inicios de sesión basados en formularios HTML. Se recomienda utilizar System.Net.WebClient o HttpClient para gestionar el proceso de inicio de sesión, descargar el contenido HTML autenticado y, a continuación, utilizar el método RenderHtmlAsPdf de IronPDF para convertir el HTML descargado en PDF.

¿Cómo descargo activos HTML como imágenes y hojas de estilo de páginas autenticadas?

Puede utilizar HtmlAgilityPack para analizar el HTML descargado y extraer las URL de activos como imágenes y hojas de estilo. A continuación, utilice System.Net.WebClient para descargar cada activo con las mismas cabeceras de autenticación antes de convertir el paquete HTML completo a PDF con IronPDF.

¿Cuál es la mejor práctica para manejar tokens o cabeceras de autenticación?

Cuando utilice IronPDF con tokens de autenticación, descargue el HTML utilizando HttpClient o WebClient con sus cabeceras de autenticación (como los tokens Bearer). Una vez que tenga el contenido HTML autenticado en la memoria o guardado en el disco, utilice ChromePdfRenderer de IronPDF para convertirlo a PDF.

¿Existe alguna solución para la autenticación de inicio de sesión MVC?

Sí, IronPDF proporciona soluciones para los escenarios de autenticación de inicio de sesión MVC. El enfoque recomendado es autenticar y descargar primero el contenido HTML utilizando clientes HTTP .NET estándar y, a continuación, pasar el HTML autenticado directamente al motor de renderizado de IronPDF en lugar de que IronPDF se encargue de la autenticación.

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
¿Listo para empezar?
Nuget Descargas 17,012,929 | Versión: 2025.12 recién lanzado