使用 IRONPDF

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

什麼是Fluent Validation?

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

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

理解流暢驗證

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

  1. 驗證器:驗證器是包裝了驗證邏輯的類別。 它們通常是通過繼承AbstractValidator<T>基類來創建的。

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

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

什麼是 IronPDF?

IronPDF - 將 HTML 轉換為 C# 中的 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 一起使用 Fluent 驗證,圖1:創建一個新的控制台應用程序

    建立新的主控台應用程式

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

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

    配置新應用程式

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

    如何在 C# 中使用流暢驗證與 IronPDF,圖 3:.NET Framework 選擇

    .NET Framework 選擇

  5. 按一下建立按鈕以建立專案。

安裝所需套件

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

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

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

    如何在 C# 中將 Fluent Validation 與 IronPDF 結合使用,圖 4:在 NuGet Package Manager UI 安裝 FluentValidation 套件

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

  3. 同樣,搜尋 "IronPDF - 強大的 .NET PDF 庫" 並安裝 IronPDF 套件。

    不過,您也可以使用NuGet 套件管理器主控台通過以下命令安裝 IronPDF:

Install-Package IronPdf

如何在 C# 中使用 Fluent Validation 與 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
$vbLabelText   $csharpLabel

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

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

建立驗證規則

為了建立InvoiceContent類的驗證規則,請建立一個名為InvoiceContentValidator的驗證器類別。 此類將繼承自AbstractValidator<InvoiceContent>,這是由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

在上述源代碼中,已定義InvoiceContentValidator類別,它繼承自AbstractValidator<InvoiceContent>。 在驗證器類別的建構子中,RuleFor 方法為 InvoiceContent 類別的每個屬性定義了驗證規則。

例如,RuleFor(content => content.CustomerName) 可以定義一個新規則,表示客戶名稱不應為空。 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
$vbLabelText   $csharpLabel

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

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

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

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

我們創建一個 ChromePdfRenderer 實例,以將 HTML 內容渲染為 PDF。 我們調用 RenderHtmlAsPdf 方法在 htmlToPdf 對象上,並傳遞由 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
$vbLabelText   $csharpLabel

在上述程式碼中,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# 中使用 Fluent Validation 與 IronPDF,圖 7:輸出 PDF 檔案

輸出 PDF 檔案

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

結論

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

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

IronPDF 免費試用和授權資訊 提供免費試用,授權價格從每位開發人員 $499 起。

Chipego
奇佩戈·卡林达
軟體工程師
Chipego 擁有天生的傾聽技能,這幫助他理解客戶問題,並提供智能解決方案。他在獲得信息技術理學學士學位後,于 2023 年加入 Iron Software 團隊。IronPDF 和 IronOCR 是 Chipego 專注的兩個產品,但隨著他每天找到新的方法來支持客戶,他對所有產品的了解也在不斷增長。他喜歡在 Iron Software 的協作生活,公司內的團隊成員從各自不同的經歷中共同努力,創造出有效的創新解決方案。當 Chipego 離開辦公桌時,他常常享受讀好書或踢足球的樂趣。
< 上一頁
PDF與PDFA(開發人員的運作方式)
下一個 >
如何使用 ChatGPT 與 IronPDF 給 C# 開發者