使用 IRONPDF

如何在C#中使用Fluent Validation與IronPDF

已更新 2024年3月17日
分享:

什麼是Fluent Validation?

FluentValidation是一個 .NET 驗證庫,有助於建立強類型的驗證規則。 這是通過提供流暢接口和 lambda 表達式來實現的,使代碼更具可讀性和可維護性。 與其在模型類中使用數據註解或手動驗證,您可以使用Fluent Validation來建立一個單獨的類以實現驗證邏輯。

流暢驗證為驗證環節帶來更多彈性。 Fluent Validation 是 .NET Core 工具包中的強大工具,具有內建驗證器處理常見場景、建構自訂驗證的能力,以及簡單的方式來鏈結驗證規則。

理解流暢驗證

Fluent Validation是一個開放原始碼的.NET庫,可以輕鬆地為您的模型類別建立驗證規則。

  1. 驗證器: 驗證器是封裝驗證邏輯的類別。 它們通常透過繼承 AbstractValidator 來創建基類。

  2. 規則: 規則是屬性必須滿足的驗證條件。 在驗證器類別中,規則是使用 RuleFor 方法定義的。

  3. 驗證失敗: 如果某個規則失敗,Fluent Validation 會創建一個 ValidationFailure 對象,其中包含有關錯誤的詳細資訊,包括屬性名稱和錯誤訊息。

什麼是 IronPDF?

IronPDF - 在 C# 中將 HTML 轉換為 PDF是一個強大的 .NET 函式庫,可以讓您從 HTML 內容生成 PDF 文件。 無論您需要創建發票、報告或任何其他類型的文件,IronPDF都提供了簡便易用的解決方案。 它可無縫整合到您的 ASP.NET Core 應用程式中,只需幾行程式碼即可生成高品質的 PDF 文件。

在 IronPDF 中使用 Fluent Validation

現在我們已經了解Fluent Validation和IronPDF是什麼了,讓我們看看它們如何能一起使用。 本教程將幫助您建立一個發票生成器,其中發票內容將在使用 IronPDF 生成 PDF 之前,使用 ASP.NET Core 中的 FluentValidation 進行驗證。

現在讓我們開始吧!

設置專案

首先,讓我們在 Visual Studio 或您偏好的開發環境中創建一個新的主控台應用程式。

  1. 打開 Visual Studio,前往 檔案 > 新增 > 專案

  2. 選擇「主控台應用程式」(ASP.NET Core)「作為專案範本並為您的專案提供名稱。」

    如何在C#中使用流暢驗證與IronPDF,圖1:創建一個新的控制台應用程序

    建立新的主控台應用程式

  3. 點擊 下一步 按鈕,通過命名並選擇儲存庫位置來配置您的專案。

    如何在 C# 中使用 Fluent Validation 與 IronPDF,圖2:配置新應用程式

    配置新應用程式

  4. 點擊下一步按鈕,然後選擇.NET Framework。 最新的 .NET Framework(7)建議使用。

    如何在C#中使用Fluent Validation與IronPDF,圖3:.NET Framework選擇

    .NET Framework 選擇

  5. 按下建立按鈕來建立專案。

安裝所需套件

一旦專案建立,我們需要添加Fluent Validation和IronPDF所需的NuGet封裝。

  1. 在方案總管中右鍵點擊專案,然後選擇「管理 NuGet 套件」。

  2. 搜尋「FluentValidation」並點擊「Install」以將該套件添加到您的專案中。

    如何在C#中使用Fluent Validation與IronPDF,圖4:在NuGet套件管理器UI中安裝FluentValidation套件

    在NuGet套件管理器UI中安裝FluentValidation套件

  3. 類似地,搜尋「IronPDF - 強大的 .NET PDF 庫並安裝IronPDF套件。

    不過,您也可以使用 NuGet Package Manager Console 並使用以下命令安裝 IronPDF:

Install-Package IronPdf

如何在C#中使用流暢驗證與IronPDF,圖5:在包管理控制台中安裝IronPdf包

在套件管理器控制台中安裝 IronPdf 套件

設定好專案並安裝所需套件後,讓我們繼續定義 PDF 內容類別。

定義 PDF 內容

在這個範例中,將從新的兩個類別 InvoiceContentInvoiceItem 中的 HTML 代碼創建一個簡單的發票 PDF。

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
VB   C#

在上述程式碼中,定義了一個抽象的 PdfContent 類別,並且包含一個名為 RenderHtml 的抽象方法。 InvoiceContent 類別擴展了 PdfContent,代表發票 PDF 的內容。 它具有客戶名稱、地址和發票項目列表等屬性。 InvoiceItem 類別包含兩個屬性「Description」和「Price」。 RenderHtml 方法根據內容生成發票的 HTML 標記。

現在 PDF 內容已經定義,我們接著使用 Fluent Validation 創建驗證規則。

建立驗證規則

為了為 InvoiceContent 類建立驗證規則,創建一個名為 InvoiceContentValidator 的驗證器類別。 該類別將繼承自 AbstractValidator`, 由 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
VB   C#

在上面的源代碼中,定義了 InvoiceContentValidator 類,它繼承自 AbstractValidator. 在驗證器類別的構造函數內,RuleFor方法為InvoiceContent` 類別的每個屬性定義驗證規則。

例如,RuleFor(內容 => 內容.客戶名稱)可以定義一個新規則,客戶名稱不可為空。 Fluent Validation 也可以鏈接使用 NotEmpty 方法來指定此驗證規則。 同樣地,我們為地址和發票項目屬性定義驗證規則。

要驗證發票項目,使用 RuleForEach 方法迭代 InvoiceItems 清單中的每個項目,並應用名為 InvoiceItemValidator 的驗證器。 InvoiceItemValidator 類別被單獨定義,並包含 InvoiceItem 類別的驗證規則。

設置這些驗證規則後,讓我們繼續使用IronPDF生成PDF。

使用 IronPDF 生成 PDF

IronPDF - 生成和編輯 PDF 文檔是一個受歡迎的 .NET 函式庫,用於創建和操作 PDF 文件。 IronPDF 將基於已驗證的發票內容生成 PDF。

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
VB   C#

在上面的源代碼中,我們定義了一個 PdfService 類,該類提供了一個 GeneratePdf 方法。 此方法將 PdfContent 物件作為輸入,並根據驗證過的內容生成 PDF 文件。

首先,我們通過調用 GetValidatorForContent 方法獲取適合內容的驗證器。 此方法檢查內容類型並返回相應的驗證器。 在我們的案例中,我們僅支持InvoiceContent並使用InvoiceContentValidator

接下來,我們透過呼叫驗證器的 validate 方法來驗證內容。 驗證結果儲存在一個 ValidationResult 物件中。

如果驗證失敗(!validationResult.IsValid),我們會拋出一個 FluentValidation.ValidationException 並包含驗證錯誤。 否則,我們將繼續使用 IronPDF 生成 PDF。

我們創建一個实例ChromePdfRenderer將 HTML 內容渲染為 PDF。 我們稱呼這個將HTML渲染為PDFhtmlToPdf 物件上使用方法,並傳入由 content.RenderHtml 方法生成的 HTML。 這將生成 PDF 文件。

現在我們已經定義了 PDF 生成邏輯,接下來處理可能發生的驗證錯誤。

處理驗證錯誤

當發生驗證錯誤時,我們希望顯示錯誤訊息並妥善處理。 讓我們修改 Program 類別的 Main 方法,以處理任何例外並向使用者顯示有意義的訊息。

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
VB   C#

在上述代碼中,try-catch 區塊有助於捕獲可能發生的任何異常。 如果捕捉到例外,將使用 Console.WriteLine 向使用者顯示錯誤訊息。

現在,讓我們用不同的場景來測試此應用程式,以驗證 PDF 生成和驗證規則。

測試應用程式

在此程式碼範例中,有三個待測試的情境:

  1. 客戶名稱為空:將客戶名稱留空以觸發驗證錯誤。

  2. 空的發票項目:提供一個空的發票項目列表以觸發驗證錯誤。

  3. 成功產生:提供有效內容以成功生成 PDF。

    運行應用程式並觀察控制台中的輸出。

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# 中使用 Fluent Validation 與 IronPDF,圖 6:在控制台中的輸出錯誤

控制台中的輸出錯誤

如何在C#中使用流暢驗證與IronPDF,圖7:輸出PDF文件

輸出 PDF 檔案

如預期,前兩個情境顯示驗證錯誤,第三個情境顯示成功訊息。

結論

本教程探討了Fluent Validation並學習如何與IronPDF一起使用以生成PDF文件。 首先,設置一個控制台應用程式並定義 PDF 內容類別。 然後,使用 Fluent Validation 建立驗證規則,並在不同情況下測試 PDF 生成。

Fluent Validation 提供了一種靈活且易於使用的方法,用於驗證 .NET 應用程式中的對象。 它允許您以強類型的方式定義驗證規則,自訂錯誤訊息,並優雅地處理驗證錯誤。

IronPDF 免費試用與授權資訊提供免費試用,許可證起始於每位開發者 $499。

< 上一頁
PDF與PDFA(開發人員的運作方式)
下一個 >
如何使用 ChatGPT 與 IronPDF 給 C# 開發者

準備開始了嗎? 版本: 2024.12 剛剛發布

免費 NuGet 下載 總下載次數: 11,622,374 查看許可證 >