IRONSOFTWAREHOME
USANDO IRONPDF

Generación dinámica de PDF en C# para VeriFactu, TicketBAI y Facturae | IronPDF

Curtis Chau
Curtis Chau
Updated: 12 de julio de 2026

Crear archivos PDF en Xamarin.Forms puede ser complicado. La mayoría de las bibliotecas PDF .NET no admiten directamente aplicaciones móviles, y tratar de generar documentos PDF en un dispositivo a menudo genera errores o falta de funcionalidad. Aquí es donde entra en juego IronPDF .

Si bien IronPDF no se ejecuta de forma nativa dentro de una aplicación Xamarin.Forms, un enfoque de API del lado del servidor cierra esa brecha de manera clara. Su aplicación móvil envía contenido HTML a la API y recibe a cambio archivos PDF terminados, lo que le brinda acceso a la generación profesional de PDF que incluye formularios, encabezados, pies de página, imágenes y diseños personalizados. Este patrón es especialmente adecuado para ISV en España que desarrollan aplicaciones de facturación bajo VeriFactu (Real Decreto 1007/2023): el servidor genera facturas con la leyenda obligatoria VERI*FACTU validable en la AEAT y, al centralizar el procesamiento, facilita el cumplimiento de la LOPDGDD supervisada por la AEPD, ya que los datos personales nunca se procesan en el dispositivo del usuario.

Nota importante: Microsoft finalizó el soporte para Xamarin en mayo de 2024. Para proyectos nuevos, .NET MAUI es el sucesor recomendado y admite IronPDF de manera más directa. Esta guía cubre el patrón del lado del servidor para proyectos heredados de Xamarin aún en mantenimiento y explica la ruta de migración a MAUI para equipos que comienzan desde cero.

¿Por qué funciona un enfoque del lado del servidor para la generación de PDF móviles?

IronPDF se destaca en la conversión de contenido HTML en documentos PDF pulidos con soporte completo para CSS, JavaScript y diseños complejos. Ejecutar IronPDF en un servidor dedicado, en lugar de dentro de una aplicación móvil, evita las restricciones de la plataforma que impiden la representación directa de PDF en dispositivos iOS y Android.

El patrón del lado del servidor ofrece varias ventajas concretas:

  • Salida consistente: las fuentes, imágenes y CSS se resuelven en el lado del servidor, lo que elimina las diferencias de representación entre el hardware de Android e iOS.
  • Acceso a funciones: las funciones de IronPDF como creación de formularios PDF, firmas digitales, marcas de agua y diseños de varias páginas están disponibles en el servidor sin restricciones.
  • Aplicación móvil más liviana: el dispositivo solo envía una solicitud HTTP y almacena los bytes PDF devueltos; no se ejecuta ningún motor PDF pesado en el teléfono.
  • Licencias centralizadas: una única licencia de IronPDF cubre la implementación de su servidor en lugar de licenciar cada dispositivo por separado.

El cliente Xamarin.Forms llama a la API, recibe una matriz de bytes, la escribe en el almacenamiento local y, opcionalmente, abre un visor de PDF. El servidor se encarga de todo lo demás.

¿Cómo se configura una API de generación de PDF de IronPDF ?

Comience creando un proyecto de API web ASP.NET Core . Esta es una API mínima estándar de .NET 10 que puede alojar en cualquier lugar: Azure App Service, AWS, un servidor local o un contenedor Docker.

Instalar IronPDF

Instala IronPDF desde NuGet utilizando cualquiera de estos comandos:

PM > Install-Package IronPdf

Crear el controlador PDF

Con IronPDF instalado, agregue un controlador que acepte HTML y devuelva un PDF:

using IronPdf;
using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.Run();

namespace PdfGenerationApi.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class PdfController : ControllerBase
    {
        [HttpPost("generate")]
        public async Task<IActionResult> GeneratePdf([FromBody] PdfRequest request)
        {
            var renderer = new ChromePdfRenderer();
            renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;
            renderer.RenderingOptions.MarginTop = 25;
            renderer.RenderingOptions.MarginBottom = 25;
            renderer.RenderingOptions.MarginLeft = 20;
            renderer.RenderingOptions.MarginRight = 20;

            var pdf = await renderer.RenderHtmlAsPdfAsync(request.HtmlContent);
            return File(pdf.BinaryData, "application/pdf", "document.pdf");
        }
    }

    public class PdfRequest
    {
        public string HtmlContent { get; set; } = string.Empty;
    }
}

ChromePdfRenderer utiliza un motor basado en Chromium para renderizar HTML exactamente como lo haría un navegador moderno. La conversión de HTML a PDF respeta animaciones CSS, fuentes incrustadas, gráficos SVG y contenido generado por JavaScript. El tamaño del papel y la configuración de los márgenes se traducen directamente en el diseño final del documento.

Añadir encabezados y pies de página

Para documentos profesionales, agregue encabezados y pies de página antes de llamar al renderizador:

renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='text-align:right; font-size:12px; color:#555;'>Confidential -- Page {page} of {total-pages}</div>",
    DrawDividerLine = true
};
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='text-align:center; font-size:11px;'>Generated by MyCompany App</div>"
};

Los tokens de número de página como {page} y {total-pages} se resuelven automáticamente en el momento de la renderización.

¿Cómo se implementa el cliente Xamarin para enviar facturas Facturae y datos VeriFactu?

En la aplicación Xamarin.Forms, cree una clase de servicio que llame a la API. Mantenga el servicio simple: su único trabajo es serializar la carga HTML, enviarla y devolver los bytes del PDF sin procesar al llamador. Para aplicaciones de facturación bajo VeriFactu y la Ley Crea y Crece, el cliente Xamarin envía los datos de la factura (NIF/CIF del emisor con formato B-12345678, NIF/CIF del receptor, importe en EUR, número de Modelo tributario, y los datos del encadenamiento de huella exigido por la AEAT) al servidor, que genera el PDF con la leyenda obligatoria VERI*FACTU y el QR verificable en la sede electrónica. Los documentos con datos personales bajo la LOPDGDD se gestionan en el servidor bajo supervisión de la AEPD, garantizando que no se procesen datos sensibles en el dispositivo móvil.

using System.Net.Http;
using System.Text;
using System.Text.Json;

namespace XamarinPdfApp.Services
{
    public class PdfService
    {
        private readonly HttpClient _httpClient;
        private const string ApiUrl = "https://your-api.example.com/api/pdf/generate";

        public PdfService()
        {
            _httpClient = new HttpClient
            {
                Timeout = TimeSpan.FromSeconds(60)
            };
        }

        public async Task<byte[]> GeneratePdfAsync(string htmlContent)
        {
            var payload = new { HtmlContent = htmlContent };
            var json = JsonSerializer.Serialize(payload);
            var content = new StringContent(json, Encoding.UTF8, "application/json");

            var response = await _httpClient.PostAsync(ApiUrl, content);

            if (response.IsSuccessStatusCode)
                return await response.Content.ReadAsByteArrayAsync();

            var error = await response.Content.ReadAsStringAsync();
            throw new InvalidOperationException($"PDF generation failed ({(int)response.StatusCode}): {error}");
        }
    }
}

Un tiempo de espera de 60 segundos permite documentos HTML complejos con muchas imágenes o recursos CSS. Para archivos muy grandes, considere devolver una URL de descarga pre-firmada desde la API en lugar de transmitir el binario directamente: esto mantiene predecible el uso de la memoria móvil.

¿Cómo guardar y abrir archivos PDF en el dispositivo?

Una vez que el servicio devuelve la matriz de bytes, escríbala en el almacenamiento del dispositivo y ábrala en el visor de PDF de la plataforma. Xamarin.Forms utiliza el patrón DependencyService para llamar a implementaciones específicas de la plataforma.

Define la interfaz en código compartido:

using System.Threading.Tasks;

namespace XamarinPdfApp.Interfaces
{
    public interface ISaveFile
    {
        Task<string> SavePdfAsync(string filename, byte[] pdfData);
    }
}

Registre la implementación de iOS utilizando DependencyService:

using Foundation;
using QuickLook;
using UIKit;
using XamarinPdfApp.Interfaces;
using Xamarin.Forms;

[assembly: Dependency(typeof(XamarinPdfApp.iOS.SaveFileIOS))]
namespace XamarinPdfApp.iOS
{
    public class SaveFileIOS : ISaveFile
    {
        public async Task<string> SavePdfAsync(string filename, byte[] pdfData)
        {
            var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            var filePath = System.IO.Path.Combine(documents, filename);
            await System.IO.File.WriteAllBytesAsync(filePath, pdfData);
            return filePath;
        }
    }
}

Para Android, escriba en el directorio de archivos externos de la aplicación y registre un FileProvider en el manifiesto para poder entregar el URI a un intento de visor de PDF. La llamada DependencyService.Get<ISaveFile>() en código compartido recupera cualquier implementación que esté registrada para la plataforma actual en tiempo de ejecución.

Conectándolo todo junto

En su página o ViewModel de Xamarin.Forms, combine el servicio y el protector de plataforma:

var htmlContent = BuildInvoiceHtml(invoice);
var pdfBytes = await _pdfService.GeneratePdfAsync(htmlContent);
var saver = DependencyService.Get<ISaveFile>();
var filePath = await saver.SavePdfAsync("invoice.pdf", pdfBytes);
await Launcher.OpenAsync(new OpenFileRequest
{
    File = new ReadOnlyFile(filePath, "application/pdf")
});

Esto abre el PDF guardado en cualquier visor que el usuario tenga instalado, que normalmente es una aplicación PDF nativa tanto en iOS como en Android.

¿Cómo generar facturas e informes profesionales en formato PDF?

La calidad de un PDF depende casi por completo de la calidad de la plantilla HTML pasada al renderizador. Utilice la interpolación de cadenas de C# o una biblioteca de plantillas como Scriban para crear HTML basado en datos:

public string BuildInvoiceHtml(Invoice invoice)
{
    var rows = string.Join(
        "\n",
        invoice.Elementos.Select(i =>
            $"<tr><td>{i.Name}</td><td>{i.Quantity}</td><td>${i.UnitPrice:F2}</td><td>${i.Total:F2}</td></tr>"
        )
    );

    return $@"<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<style>
  body {{ font-family: Arial, sans-serif; color: #333; margin: 0; padding: 30px; }}
  h1 {{ color: #1a73e8; }}
  table {{ width: 100%; border-collapse: collapse; margin-top: 20px; }}
  th {{ background: #1a73e8; color: #fff; padding: 10px; text-align: left; }}
  td {{ padding: 10px; border-bottom: 1px solid #e0e0e0; }}
  .total {{ font-weight: bold; font-size: 1.1em; text-align: right; margin-top: 15px; }}
</style>
</head>
<body>
  <h1>Invoice #{invoice.Number}</h1>
  <p>Date: {invoice.Date:yyyy-MM-dd} &nbsp;|&nbsp; Due: {invoice.DueDate:yyyy-MM-dd}</p>
  <p>Bill to: <strong>{invoice.ClientName}</strong></p>
  <table>
    <thead><tr><th>Elemento</th><th>Qty</th><th>Unit Price</th><th>Total</th></tr></thead>
    <tbody>{rows}</tbody>
  </table>
  <p class='total'>Grand Total: ${invoice.GrandTotal:F2}</p>
</body>
</html>";
}

El ChromePdfRenderer renderiza esta plantilla exactamente como lo haría un navegador. Puede agregar marcas de agua utilizando la API de marcas de agua de IronPDF o aplicar diseños de marcas de agua personalizados para borradores confidenciales. Para los documentos que requieren un campo de firma, el soporte de firma de IronPDF le permite incorporar firmas PAdES conformes al reglamento eIDAS de la UE mediante certificados cualificados de la FNMT (Fábrica Nacional de Moneda y Timbre) y el sistema de identidad electrónica Cl@ve, siendo esto un requisito habitual para documentos Facturae presentados a través de FACe y para el sistema TicketBAI en los territorios forales de Bizkaia, Gipuzkoa y Araba.

¿Cómo manejar formularios PDF en una aplicación Xamarin?

Los formularios PDF son un requisito común para las aplicaciones comerciales móviles: contratos, cuestionarios de incorporación y listas de verificación de inspección se benefician de campos editables precargados. La API del servidor puede aceptar datos de campo junto con la plantilla HTML e incrustar valores de formulario antes de devolver el PDF:

[HttpPost("form")]
public async Task<IActionResult> GenerateForm([FromBody] FormRequest request)
{
    var renderer = new ChromePdfRenderer();
    // Render an HTML form template to create an interactive PDF form
    var pdf = await renderer.RenderHtmlAsPdfAsync(request.HtmlTemplate);

    // Fill known values before returning
    var form = pdf.Form;
    foreach (var field in request.FieldValues)
    {
        var pdfField = form.Fields.FirstOrDefault(f => f.Name == field.Key);
        if (pdfField is IronPdf.Forms.PdfFormTextFieldField textField)
            textField.Value = field.Value;
    }

    return File(pdf.BinaryData, "application/pdf", "form.pdf");
}

El cliente móvil envía un diccionario de nombres de campos y valores. El servidor los completa y devuelve un formulario que el usuario puede revisar, completar los campos restantes en un visor de PDF y enviarlo.

¿Cómo extraer texto y fusionar archivos PDF desde una aplicación Xamarin?

Más allá de la generación, IronPDF admite una amplia gama de operaciones de documentos que puedes exponer como puntos finales de API:

  • Extraer texto de PDF : analice el contenido de PDF para indexar documentos o completar previamente formularios de ingreso de datos.
  • Fusionar o dividir archivos PDF : combine varios informes en un solo PDF o divida un documento grande en archivos por sección.
  • Convertir PDF a imagen : renderiza páginas PDF como miniaturas PNG o JPEG para obtener una vista previa en la interfaz de usuario móvil.

Cada uno de estos se convierte en un punto final de API independiente. El cliente Xamarin los llama como cualquier otro recurso REST, manteniendo el código móvil libre de lógica PDF y al servidor como procesador de documentos autorizado.

¿Cuáles son los problemas más comunes y cómo solucionarlos?

La arquitectura servidor-cliente es sencilla, pero hay varias cuestiones de producción que merecen atención:

Problemas comunes y soluciones recomendadas para la integración de la API de Xamarin con IronPDF
EdiciónCausaSolución recomendada
Tiempo de espera de solicitudEl HTML complejo con muchos activos remotos tarda tiempo en renderizarseAumente HttpClient.Timeout y configure el tiempo de espera de renderizado del lado del servidor en las opciones de renderizado
Gran pico de memoria PDFTransmisión de un PDF de 20 MB a través del cuerpo de la respuestaSubir al almacenamiento de blobs y devolver una URL de descarga de corta duración en su lugar
Generación fuera de líneaEl dispositivo no tiene conectividad cuando el usuario solicita un PDFPoner en cola las solicitudes localmente y volver a intentarlo cuando se restablezca la conectividad
Acceso no autorizado a la APIEl punto final está abierto a InternetProteja con JWT o clave API; aplique HTTPS en todas las rutas
Fuente no incrustadaEl sistema operativo del servidor no tiene la fuente instaladaIncruste la fuente en el HTML como un URI de datos base64 o como una regla CSS @font-face
Permiso de almacenamiento de iOSLa aplicación está diseñada para iOS 14+ con un entorno sandbox más estrictoEscriba en Environment.SpecialFolder.MyDocuments dentro del entorno de pruebas de la aplicación

Para limitar la velocidad, agregue middleware en el lado de ASP.NET Core usando una biblioteca como AspNetCoreRateLimit . Registre cada solicitud de generación con datos de tiempo para poder detectar plantillas lentas antes de que afecten a los usuarios.

¿Debería migrar de Xamarin a .NET MAUI para aplicaciones de facturación española?

Si va a iniciar un nuevo proyecto móvil en 2026, .NET MAUI es la opción ideal. Microsoft finalizó el soporte para Xamarin en mayo de 2024, lo que significa que no habrá más parches de seguridad ni correcciones de errores. .NET MAUI es el sucesor directo y se ejecuta en .NET 10, coincidiendo con el entorno de ejecución IronPDF actual.

Para equipos españoles que desarrollan aplicaciones móviles de gestión de facturas o ERPs bajo VeriFactu y la Ley Crea y Crece (Ley 18/2022), la migración de Xamarin a MAUI es especialmente relevante: MAUI permite la inyección de dependencia nativa, facilitando la integración con servicios de firma PAdES conforme a eIDAS, módulos de sellado de tiempo de la FNMT y el sistema Cl@ve. La arquitectura servidor-cliente descrita en esta guía persiste en MAUI, manteniendo la generación de facturas Facturae con la leyenda VERI*FACTU y el QR verificable ante la AEAT en el servidor, mientras la aplicación MAUI actúa como cliente ligero que recibe y visualiza el PDF resultante. Para aplicaciones que deben funcionar bajo la normativa TicketBAI en los territorios forales de Bizkaia, Gipuzkoa y Araba, la migración a MAUI facilita la integración con SDKs de firma XAdES actualizados por las respectivas diputaciones forales sin los problemas de compatibilidad de Xamarin con plataformas más nuevas. El cumplimiento de la LOPDGDD supervisado por la AEPD también mejora con la arquitectura servidor-cliente en MAUI, ya que los datos personales de los documentos (NIF/CIF de clientes, IBAN, importes en EUR) permanecen procesados y firmados en el servidor y nunca se almacenan en el dispositivo del usuario sin cifrado.

La arquitectura del lado del servidor descrita en esta guía funciona de manera idéntica para las aplicaciones .NET MAUI : el código HTTP del cliente es esencialmente el mismo; sólo el DependencyService se sustituye por la inyección de dependencia incorporada de MAUI. Los equipos que mantienen aplicaciones Xamarin existentes deben planificar una migración a MAUI; La guía oficial de migración de .NET MAUI de Microsoft documenta los pasos en detalle.

¿Cómo implementar y licenciar IronPDF para producción?

La implementación es sencilla: contenga la API de ASP.NET Core con Docker y envíela a Azure App Service, AWS ECS o cualquier clúster de Kubernetes. La clave de licencia de IronPDF se establece como una variable de entorno en el servidor:

IronPdf.License.LicenseKey = Environment.GetEnvironmentVariable("IRONPDF_LICENSE_KEY")
    ?? throw new InvalidOperationException("IronPDF license key not set.");

Para ISV en España bajo la normativa VeriFactu y la Ley Crea y Crece, la elección de la licencia es una decisión crítica de cumplimiento: iText usa licencia AGPL, que puede obligar a los ISV a publicar el código fuente de sus aplicaciones propietarias, con sanciones de hasta €150.000/año por parte de la AEAT para ISV no conformes. IronPDF ofrece licencia comercial sin restricciones AGPL y es compatible con la generación de PDFs para Facturae y la leyenda VERI*FACTU.

Revise la página de licencias de IronPDF para seleccionar el nivel correcto para su implementación. Una licencia de prueba gratuita le permite probar el conjunto completo de funciones antes de comprometerse. Para implementaciones en contenedores o sin servidor, verifique que el nivel de licencia cubra la cantidad de instancias de servidor que se ejecutan simultáneamente.

Después de obtener la licencia, explore la documentación de IronPDF para conocer opciones de configuración avanzadas, incluidas configuraciones de representación segura para subprocesos, conformidad con PDF/A y etiquetado de accesibilidad.

Lista de verificación de implementación de producción

Lista de verificación de implementación para una API de generación de PDF basada en IronPDF
ElementoRecomendación
Clave de licenciaAlmacenar en variables de entorno o en un administrador secreto, nunca en el código fuente
HTTPSAplicar TLS en todos los puntos finales de API; nunca enviar cargas HTML a través de HTTP simple
AutenticaciónUtilice tokens portadores JWT o claves API; revoque en caso de incumplimiento
CachéAlmacenar en caché cargas HTML idénticas durante un TTL corto para reducir representaciones redundantes
EscaladoIronPDF es seguro para subprocesos; ejecuta múltiples réplicas de API detrás de un balanceador de carga
MonitoreoSeguimiento de la latencia de renderizado y tasas de error; alerta sobre picos por encima de la línea base

El patrón del lado del servidor se escala horizontalmente sin ningún cambio en el cliente Xamarin o MAUI. Agregue réplicas a medida que crece el volumen de generación de PDF y confíe en el equilibrador de carga para distribuir las solicitudes de manera uniforme.

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 estructurados y visualmente atractivos.

...
Leer más

Artículos Relacionados

Key in blue circle

Obtenga su clave de prueba gratuita de 30 días al instante.

Your trial license will be sent to your email address

Sin limitaciones. 100 % desbloqueado. Sin tarjeta de crédito.

bullet_checkedNo se requiere tarjeta de crédito ni creación de cuentaSin limitaciones. 100 % desbloqueado. Sin tarjeta de crédito.
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
Reserve su Demostración en Vivo gratuita
Booking Badge

Confiado por millones de ingenieros en todo el mundo

Logos de clientes de Iron Software
Obtén tu Consulta Sin Compromiso
Completa el formulario a continuación o envía un correo a sales@ironsoftware.com
Tus detalles siempre serán mantenidos confidenciales.
Confiado por millones de ingenieros en todo el mundo
Logos de clientes de Iron Software
Obtenga su Clave de Prueba de 30 días gratis al instante.
No se requiere tarjeta de crédito ni creación de cuenta