USO DE IRONPDF

Cómo utilizar Fluent Validation con IronPDF en C#

¿Qué es la validación fluente?

FluentValidation es una biblioteca de validación .NET que ayuda a construir reglas de validación fuertemente tipadas. Esto se consigue proporcionando una interfaz fluida y expresiones lambda, lo que hace que el código sea más legible y fácil de mantener. En lugar de utilizar anotaciones de datos o validación manual en sus clases modelo, puede utilizar Fluent Validation para crear una clase independiente para su lógica de validación.

Fluent Validation aporta más flexibilidad al juego de la validación. Con validadores integrados para escenarios comunes, la posibilidad de crear validaciones personalizadas y una forma sencilla de encadenar reglas de validación, Fluent Validation es una potente herramienta del conjunto de herramientas de .NET Core.

Comprender la validación de Fluent

Fluent Validation es una biblioteca de código abierto para .NET que facilita la creación de reglas de validación para sus clases modelo.

  1. Validadores: Los validadores son clases que encapsulan la lógica de validación. Por lo general, se crean heredando de la clase base AbstractValidator<T>.

  2. Reglas: Una regla es una condición de validación que una propiedad debe cumplir. Las reglas se definen usando el método RuleFor en una clase validadora.

  3. Fallos de Validación: Si una regla falla, Fluent Validation crea un objeto ValidationFailure que contiene detalles sobre el error, incluyendo el nombre de la propiedad y el mensaje de error.

¿Qué es IronPDF?

IronPDF - Convertir HTML a PDF en C# es una poderosa biblioteca .NET que te permite generar documentos PDF a partir de contenido HTML. Tanto si necesita crear facturas, informes o cualquier otro tipo de documento, IronPDF le ofrece una solución fácil de usar. Se integra perfectamente con sus aplicaciones ASP.NET Core, lo que le permite generar archivos PDF de alta calidad con sólo unas pocas líneas de código.

Uso de Fluent Validation con IronPDF

Ahora que ya sabemos qué son Fluent Validation y IronPDF, veamos cómo pueden utilizarse juntos. Este tutorial ayudará a construir un generador de facturas, donde el contenido de la factura será validado usando FluentValidation en ASP.NET Core antes de generar el PDF usando IronPDF.

¡Ahora empecemos!

Configuración del proyecto

Para empezar, vamos a crear una nueva aplicación de consola en Visual Studio o en su entorno de desarrollo preferido.

  1. Abra Visual Studio y vaya a Archivo > Nuevo > Proyecto.

  2. Seleccione "Aplicación de consola (ASP.NET Core)" como la plantilla de proyecto y proporcione un nombre para su proyecto.

    Cómo usar Fluent Validation con IronPDF en C#, Figura 1: Crear una nueva aplicación de consola

    Crear una nueva aplicación de consola

  3. Haga clic en el botón Siguiente y configure su proyecto dando el nombre y seleccionando la ubicación del repositorio.

    Cómo usar Fluent Validation con IronPDF en C#, Figura 2: Configurar la nueva aplicación

    Configurar la nueva aplicación

  4. Haz clic en el botón Siguiente y selecciona el .NET Framework. Se recomienda la última versión de .NET Framework (7).

    Cómo usar Fluent Validation con IronPDF en C#, Figura 3: selección de .NET Framework

    Selección de .NET Framework

  5. Haz clic en el Crear botón para crear el proyecto.

Instalar los paquetes necesarios

Una vez creado el proyecto, tenemos que añadir los paquetes NuGet necesarios para Fluent Validation y IronPDF.

  1. Haga clic con el botón derecho en el proyecto en el Explorador de soluciones y seleccione "Administrar paquetes NuGet".

  2. Busque "FluentValidation" y haga clic en "Instalar" para añadir el paquete a su proyecto.

    Cómo usar Fluent Validation con IronPDF en C#, Figura 4: Instalar el paquete FluentValidation en la IU del Administrador de Paquetes NuGet

    Instala el paquete FluentValidation en la interfaz de usuario del Administrador de paquetes NuGet

  3. De manera similar, busca "IronPDF - Powerful .NET PDF Library" e instala el paquete de IronPDF.

    Sin embargo, también puedes instalar IronPDF usando NuGet Package Manager Console con el siguiente comando:

Install-Package IronPdf

Cómo usar la validación fluida con IronPDF en C#, Figura 5: Instale el paquete IronPdf en la Consola del Administrador de Paquetes

Instala el paquete de IronPdf en la Consola del Administrador de Paquetes

Una vez configurado el proyecto e instalados los paquetes necesarios, pasemos a definir la clase de contenido PDF.

Definir el contenido del PDF

En este ejemplo, se creará un PDF de factura simple a partir del código HTML en las dos nuevas clases: InvoiceContent y InvoiceItem.

public abstract class PdfContent
{
    public abstract string RenderHtml();
}

public class InvoiceContent : PdfContent
{
    public string CustomerName { get; set; }
    public string Address { get; set; }
    public List<InvoiceItem> InvoiceItems { get; set; }

    public override string RenderHtml()
    {
        string invoiceItemsHtml = string.Join("", InvoiceItems.Select(item => $"<li>{item.Description}: {item.Price}</li>"));
        return $"<h1>Invoice for {CustomerName}</h1><p>{Address}</p><ul>{invoiceItemsHtml}</ul>";
    }
}

public class InvoiceItem
{
    public string Description { get; set; }
    public decimal Price { get; set; }
}
public abstract class PdfContent
{
    public abstract string RenderHtml();
}

public class InvoiceContent : PdfContent
{
    public string CustomerName { get; set; }
    public string Address { get; set; }
    public List<InvoiceItem> InvoiceItems { get; set; }

    public override string RenderHtml()
    {
        string invoiceItemsHtml = string.Join("", InvoiceItems.Select(item => $"<li>{item.Description}: {item.Price}</li>"));
        return $"<h1>Invoice for {CustomerName}</h1><p>{Address}</p><ul>{invoiceItemsHtml}</ul>";
    }
}

public class InvoiceItem
{
    public string Description { get; set; }
    public decimal Price { get; set; }
}
Public MustInherit Class PdfContent
	Public MustOverride Function RenderHtml() As String
End Class

Public Class InvoiceContent
	Inherits PdfContent

	Public Property CustomerName() As String
	Public Property Address() As String
	Public Property InvoiceItems() As List(Of InvoiceItem)

	Public Overrides Function RenderHtml() As String
		Dim invoiceItemsHtml As String = String.Join("", InvoiceItems.Select(Function(item) $"<li>{item.Description}: {item.Price}</li>"))
		Return $"<h1>Invoice for {CustomerName}</h1><p>{Address}</p><ul>{invoiceItemsHtml}</ul>"
	End Function
End Class

Public Class InvoiceItem
	Public Property Description() As String
	Public Property Price() As Decimal
End Class
$vbLabelText   $csharpLabel

En el código anterior, se define una clase abstracta PdfContent con un método abstracto llamado RenderHtml. La clase InvoiceContent extiende PdfContent y representa el contenido del PDF de la factura. Tiene propiedades para el nombre del cliente, la dirección y una lista de artículos de la factura. La clase InvoiceItem contiene dos propiedades 'Description' y 'Price'. El método RenderHtml genera el marcado HTML para la factura basado en el contenido.

Ahora que el contenido del PDF está definido, pasemos a crear reglas de validación utilizando Fluent Validation.

Creación de reglas de validación

Para construir reglas de validación para la clase InvoiceContent, cree una clase validadora llamada InvoiceContentValidator. Esta clase heredará de AbstractValidator<InvoiceContent>, que es proporcionada por Fluent Validation.

using FluentValidation;

public class InvoiceContentValidator : AbstractValidator<InvoiceContent>
{
    public InvoiceContentValidator()
    {
        RuleFor(content => content.CustomerName).NotEmpty().WithMessage("Customer name is required.");
        RuleFor(content => content.Address).NotEmpty().WithMessage("Address is required.");
        RuleFor(content => content.InvoiceItems).NotEmpty().WithMessage("At least one invoice item is required.");
        RuleForEach(content => content.InvoiceItems).SetValidator(new InvoiceItemValidator());
    }
}

public class InvoiceItemValidator : AbstractValidator<InvoiceItem>
{
    public InvoiceItemValidator()
    {
        RuleFor(item => item.Description).NotEmpty().WithMessage("Description is required.");
        RuleFor(item => item.Price).GreaterThanOrEqualTo(0).WithMessage("Price must be greater than or equal to 0.");
    }
}
using FluentValidation;

public class InvoiceContentValidator : AbstractValidator<InvoiceContent>
{
    public InvoiceContentValidator()
    {
        RuleFor(content => content.CustomerName).NotEmpty().WithMessage("Customer name is required.");
        RuleFor(content => content.Address).NotEmpty().WithMessage("Address is required.");
        RuleFor(content => content.InvoiceItems).NotEmpty().WithMessage("At least one invoice item is required.");
        RuleForEach(content => content.InvoiceItems).SetValidator(new InvoiceItemValidator());
    }
}

public class InvoiceItemValidator : AbstractValidator<InvoiceItem>
{
    public InvoiceItemValidator()
    {
        RuleFor(item => item.Description).NotEmpty().WithMessage("Description is required.");
        RuleFor(item => item.Price).GreaterThanOrEqualTo(0).WithMessage("Price must be greater than or equal to 0.");
    }
}
Imports FluentValidation

Public Class InvoiceContentValidator
	Inherits AbstractValidator(Of InvoiceContent)

	Public Sub New()
		RuleFor(Function(content) content.CustomerName).NotEmpty().WithMessage("Customer name is required.")
		RuleFor(Function(content) content.Address).NotEmpty().WithMessage("Address is required.")
		RuleFor(Function(content) content.InvoiceItems).NotEmpty().WithMessage("At least one invoice item is required.")
		RuleForEach(Function(content) content.InvoiceItems).SetValidator(New InvoiceItemValidator())
	End Sub
End Class

Public Class InvoiceItemValidator
	Inherits AbstractValidator(Of InvoiceItem)

	Public Sub New()
		RuleFor(Function(item) item.Description).NotEmpty().WithMessage("Description is required.")
		RuleFor(Function(item) item.Price).GreaterThanOrEqualTo(0).WithMessage("Price must be greater than or equal to 0.")
	End Sub
End Class
$vbLabelText   $csharpLabel

En el código fuente anterior, se define la clase InvoiceContentValidator, que hereda de AbstractValidator<InvoiceContent>. Dentro del constructor de la clase validadora, el método RuleFor define reglas de validación para cada propiedad de la clase InvoiceContent.

Por ejemplo, RuleFor(content => content.CustomerName) puede definir una nueva regla que el nombre del cliente no debe estar vacío. La validación fluida también puede encadenar el método NotEmpty para especificar esta regla de validación. Del mismo modo, definimos reglas de validación para las propiedades de dirección y elementos de factura.

Para validar los elementos de la factura, el método RuleForEach se utiliza para iterar sobre cada elemento en la lista InvoiceItems y aplicar un validador llamado InvoiceItemValidator. La clase InvoiceItemValidator se define por separado y contiene reglas de validación para la clase InvoiceItem.

Una vez establecidas estas reglas de validación, pasemos a generar el PDF con IronPDF.

Generación de PDF con IronPDF

IronPDF: Genere y Edite Documentos PDF es una biblioteca popular de .NET para crear y manipular documentos PDF. Se utilizará IronPDF para generar el PDF basándose en el contenido validado de la factura.

using IronPdf;
using FluentValidation;

public class PdfService
{
    public PdfDocument GeneratePdf<T>(T content) where T : PdfContent
    {
        var validator = GetValidatorForContent(content);
        FluentValidation.Results.ValidationResult validationResult = validator.Validate(content);

        if (!validationResult.IsValid)
        {
            throw new FluentValidation.ValidationException(validationResult.Errors);
        }

        var renderer = new ChromePdfRenderer();
        return renderer.RenderHtmlAsPdf(content.RenderHtml());
    }

    private IValidator<T> GetValidatorForContent<T>(T content) where T : PdfContent
    {
        if (content is InvoiceContent)
        {
            return (IValidator<T>)new InvoiceContentValidator();
        }
        else
        {
            throw new NotSupportedException("Unsupported content type.");
        }
    }
}
using IronPdf;
using FluentValidation;

public class PdfService
{
    public PdfDocument GeneratePdf<T>(T content) where T : PdfContent
    {
        var validator = GetValidatorForContent(content);
        FluentValidation.Results.ValidationResult validationResult = validator.Validate(content);

        if (!validationResult.IsValid)
        {
            throw new FluentValidation.ValidationException(validationResult.Errors);
        }

        var renderer = new ChromePdfRenderer();
        return renderer.RenderHtmlAsPdf(content.RenderHtml());
    }

    private IValidator<T> GetValidatorForContent<T>(T content) where T : PdfContent
    {
        if (content is InvoiceContent)
        {
            return (IValidator<T>)new InvoiceContentValidator();
        }
        else
        {
            throw new NotSupportedException("Unsupported content type.");
        }
    }
}
Imports IronPdf
Imports FluentValidation

Public Class PdfService
	Public Function GeneratePdf(Of T As PdfContent)(ByVal content As T) As PdfDocument
		Dim validator = GetValidatorForContent(content)
		Dim validationResult As FluentValidation.Results.ValidationResult = validator.Validate(content)

		If Not validationResult.IsValid Then
			Throw New FluentValidation.ValidationException(validationResult.Errors)
		End If

		Dim renderer = New ChromePdfRenderer()
		Return renderer.RenderHtmlAsPdf(content.RenderHtml())
	End Function

	Private Function GetValidatorForContent(Of T As PdfContent)(ByVal content As T) As IValidator(Of T)
		If TypeOf content Is InvoiceContent Then
			Return DirectCast(New InvoiceContentValidator(), IValidator(Of T))
		Else
			Throw New NotSupportedException("Unsupported content type.")
		End If
	End Function
End Class
$vbLabelText   $csharpLabel

En el código fuente anterior, definimos una clase PdfService que proporciona un método GeneratePdf. Este método toma un objeto PdfContent como entrada y genera el documento PDF basado en el contenido validado.

Primero, obtenemos el validador adecuado para el contenido llamando al método GetValidatorForContent. Este método comprueba el tipo de contenido y devuelve el validador correspondiente. En nuestro caso, solo admitimos InvoiceContent y utilizamos el InvoiceContentValidator.

A continuación, validamos el contenido utilizando el validador llamando a su método validate. El resultado de la validación se almacena en un objeto ValidationResult.

Si la validación falla (!validationResult.IsValid), lanzamos una FluentValidation.ValidationException con los errores de validación. En caso contrario, procedemos a generar el PDF utilizando IronPDF.

Creamos una instancia de ChromePdfRenderer para renderizar el contenido HTML como un PDF. Llamamos al método RenderHtmlAsPdf en el objeto htmlToPdf y pasamos el HTML generado por el método content.RenderHtml. Esto genera el documento PDF.

Ahora que hemos definido la lógica de generación de PDF, vamos a gestionar los errores de validación que puedan producirse.

Tratamiento de errores de validación

Cuando se produce un error de validación, queremos mostrar un mensaje de error y manejarlo con elegancia. Modifiquemos el método Main de la clase Program para manejar cualquier excepción y mostrar mensajes significativos al usuario.

public class Program
{
    static void Main(string [] args)
    {
        var pdfService = new PdfService();

        // Test 1: Empty Customer Name
        try
        {
            var invoiceContent = new InvoiceContent
            {
                CustomerName = "",
                Address = "123 Main St, Anytown, USA",
                InvoiceItems = new List<InvoiceItem> {
                    new InvoiceItem { Description = "Item 1", Price = 19.99M },
                    new InvoiceItem { Description = "Item 2", Price = 29.99M }
                }
            };

            var pdfDocument = pdfService.GeneratePdf(invoiceContent);
            pdfDocument.SaveAs("C:\\TestInvoice.pdf");
            Console.WriteLine("PDF generated successfully!");
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error generating PDF: " + ex.Message);
        }

        // Test 2: Empty InvoiceItems
        try
        {
            var invoiceContent = new InvoiceContent
            {
                CustomerName = "John Doe",
                Address = "123 Main St, Anytown, USA",
                InvoiceItems = new List<InvoiceItem>()  // Empty list
            };

            var pdfDocument = pdfService.GeneratePdf(invoiceContent);
            pdfDocument.SaveAs("C:\\TestInvoice.pdf");
            Console.WriteLine("PDF generated successfully!");
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error generating PDF: " + ex.Message);
        }

        //Successful
        try
        {
            var invoiceContent = new InvoiceContent
            {
                CustomerName = "John Doe",
                Address = "123 Main St, Anytown, USA",
                InvoiceItems = new List<InvoiceItem> {
                new InvoiceItem { Description = "Item 1", Price = 19.99M },
                new InvoiceItem { Description = "Item 2", Price = 29.99M }
            }
            };
            var pdfDocument = pdfService.GeneratePdf(invoiceContent);
            pdfDocument.SaveAs("C:\\TestInvoice.pdf");
            Console.WriteLine("PDF generated successfully!");
        }
        catch(Exception ex)
        {
            Console.WriteLine("Error generating PDF: " + ex.Message);
        }
    }
}
public class Program
{
    static void Main(string [] args)
    {
        var pdfService = new PdfService();

        // Test 1: Empty Customer Name
        try
        {
            var invoiceContent = new InvoiceContent
            {
                CustomerName = "",
                Address = "123 Main St, Anytown, USA",
                InvoiceItems = new List<InvoiceItem> {
                    new InvoiceItem { Description = "Item 1", Price = 19.99M },
                    new InvoiceItem { Description = "Item 2", Price = 29.99M }
                }
            };

            var pdfDocument = pdfService.GeneratePdf(invoiceContent);
            pdfDocument.SaveAs("C:\\TestInvoice.pdf");
            Console.WriteLine("PDF generated successfully!");
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error generating PDF: " + ex.Message);
        }

        // Test 2: Empty InvoiceItems
        try
        {
            var invoiceContent = new InvoiceContent
            {
                CustomerName = "John Doe",
                Address = "123 Main St, Anytown, USA",
                InvoiceItems = new List<InvoiceItem>()  // Empty list
            };

            var pdfDocument = pdfService.GeneratePdf(invoiceContent);
            pdfDocument.SaveAs("C:\\TestInvoice.pdf");
            Console.WriteLine("PDF generated successfully!");
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error generating PDF: " + ex.Message);
        }

        //Successful
        try
        {
            var invoiceContent = new InvoiceContent
            {
                CustomerName = "John Doe",
                Address = "123 Main St, Anytown, USA",
                InvoiceItems = new List<InvoiceItem> {
                new InvoiceItem { Description = "Item 1", Price = 19.99M },
                new InvoiceItem { Description = "Item 2", Price = 29.99M }
            }
            };
            var pdfDocument = pdfService.GeneratePdf(invoiceContent);
            pdfDocument.SaveAs("C:\\TestInvoice.pdf");
            Console.WriteLine("PDF generated successfully!");
        }
        catch(Exception ex)
        {
            Console.WriteLine("Error generating PDF: " + ex.Message);
        }
    }
}
Public Class Program
	Shared Sub Main(ByVal args() As String)
		Dim pdfService As New PdfService()

		' Test 1: Empty Customer Name
		Try
			Dim invoiceContent As New InvoiceContent With {
				.CustomerName = "",
				.Address = "123 Main St, Anytown, USA",
				.InvoiceItems = New List(Of InvoiceItem) From {
					New InvoiceItem With {
						.Description = "Item 1",
						.Price = 19.99D
					},
					New InvoiceItem With {
						.Description = "Item 2",
						.Price = 29.99D
					}
				}
			}

			Dim pdfDocument = pdfService.GeneratePdf(invoiceContent)
			pdfDocument.SaveAs("C:\TestInvoice.pdf")
			Console.WriteLine("PDF generated successfully!")
		Catch ex As Exception
			Console.WriteLine("Error generating PDF: " & ex.Message)
		End Try

		' Test 2: Empty InvoiceItems
		Try
			Dim invoiceContent As New InvoiceContent With {
				.CustomerName = "John Doe",
				.Address = "123 Main St, Anytown, USA",
				.InvoiceItems = New List(Of InvoiceItem)()
			}

			Dim pdfDocument = pdfService.GeneratePdf(invoiceContent)
			pdfDocument.SaveAs("C:\TestInvoice.pdf")
			Console.WriteLine("PDF generated successfully!")
		Catch ex As Exception
			Console.WriteLine("Error generating PDF: " & ex.Message)
		End Try

		'Successful
		Try
			Dim invoiceContent As New InvoiceContent With {
				.CustomerName = "John Doe",
				.Address = "123 Main St, Anytown, USA",
				.InvoiceItems = New List(Of InvoiceItem) From {
					New InvoiceItem With {
						.Description = "Item 1",
						.Price = 19.99D
					},
					New InvoiceItem With {
						.Description = "Item 2",
						.Price = 29.99D
					}
				}
			}
			Dim pdfDocument = pdfService.GeneratePdf(invoiceContent)
			pdfDocument.SaveAs("C:\TestInvoice.pdf")
			Console.WriteLine("PDF generated successfully!")
		Catch ex As Exception
			Console.WriteLine("Error generating PDF: " & ex.Message)
		End Try
	End Sub
End Class
$vbLabelText   $csharpLabel

En el código anterior, un bloque try-catch ayuda a captar cualquier excepción que pueda ocurrir. Si se captura una excepción, se mostrará un mensaje de error al usuario utilizando Console.WriteLine.

Ahora, vamos a probar esta aplicación con diferentes escenarios para validar la generación de PDF y las reglas de validación.

Probar la aplicación

En el ejemplo de código, hay tres escenarios para probar:

  1. Nombre de cliente vacío: Deje el nombre de cliente vacío para activar un error de validación.

  2. Elementos de factura vacíos: Se proporciona una lista vacía de partidas de factura para provocar un error de validación.

  3. Generación correcta: Proporcione contenido válido para generar el PDF correctamente.

    Ejecute la aplicación y observe la salida en la consola.

Error generating PDF: Validation failed:
    -- CustomerName: Customer name is required. Severity: Error
Error generating PDF: Validation failed:
    -- InvoiceItems: At least one invoice item is required. Severity: Error
PDF generated successfully!

Cómo usar Fluent Validation con IronPDF en C#, Figura 6: El error de salida en la Consola

El error de salida en la Consola

Cómo usar la validación fluida con IronPDF en C#, Figura 7: El archivo PDF de salida

El archivo PDF de salida

Como era de esperar, se muestran errores de validación para los dos primeros escenarios y un mensaje de éxito para el tercer escenario.

Conclusión

Este tutorial explora Fluent Validation y aprende a utilizarlo con IronPDF para generar documentos PDF. Empezando por configurar una aplicación de consola y definir la clase de contenido PDF. A continuación, creamos reglas de validación con Fluent Validation y probamos la generación de PDF con distintos escenarios.

Fluent Validation proporciona un enfoque flexible y fácil de usar para validar objetos en aplicaciones .NET. Le permite definir reglas de validación de una manera fuertemente tipada, personalizar los mensajes de error y manejar los errores de validación con gracia.

IronPDF Free Trial & Licensing Information ofrece una prueba gratuita y la licencia comienza desde $499 por desarrollador.

Chipego
Ingeniero de software
Chipego tiene una habilidad natural para escuchar que le ayuda a comprender los problemas de los clientes y a ofrecer soluciones inteligentes. Se unió al equipo de Iron Software en 2023, después de estudiar una licenciatura en Tecnología de la Información. IronPDF e IronOCR son los dos productos en los que Chipego se ha centrado, pero su conocimiento de todos los productos crece día a día, a medida que encuentra nuevas formas de ayudar a los clientes. Disfruta de lo colaborativa que es la vida en Iron Software, con miembros del equipo de toda la empresa que aportan su variada experiencia para contribuir a soluciones eficaces e innovadoras. Cuando Chipego está lejos de su escritorio, a menudo se le puede encontrar disfrutando de un buen libro o jugando al fútbol.
< ANTERIOR
PDF frente a PDFA (cómo funciona para los desarrolladores)
SIGUIENTE >
Cómo utilizar ChatGPT con IronPDF para desarrolladores C#