在實際環境中測試
在生產環境中測試無浮水印。
在任何需要的地方都能運作。
什麼是 Fluent Validation?
FluentValidation 是一個 .NET 驗證庫,有助於建立強類型的驗證規則。這是通過提供流暢的接口和 lambda 表達式來完成的,使代碼更加可讀和易於維護。與其在您的模型類中使用數據註釋或手動驗證,您可以使用 Fluent Validation 來構建一個單獨的類來實現驗證邏輯。
Fluent Validation 為驗證帶來了更多的靈活性。它內建常見場景的驗證器、能夠構建自定義驗證,並且簡單地將驗證規則串聯在一起,Fluent Validation 是 .NET Core 工具包中的一個強大工具。
Fluent Validation 是一個用於 .NET 的開源庫,使為模型類建立驗證規則變得簡單。
驗證器: 驗證器是封裝驗證邏輯的類。它們通常透過繼承 AbstractValidator
來創建。
規則: 規則是一個屬性必須滿足的驗證條件。規則是使用驗證器類中的 RuleFor
方法定義的。
ValidationFailure
對象,其中包含關於錯誤的詳細資訊,包括屬性名稱和錯誤訊息。IronPDF 是一個強大的 .NET 庫,允許您 從 HTML 生成 PDF 文件 無論您需要創建發票、報告還是任何其他類型的文件,IronPDF 都提供一個易於使用的解決方案。它無縫整合到您的 ASP.NET Core 應用程序中,使您只需幾行代碼即可生成高品質的 PDF 文件。
現在我們了解了什麼是 Fluent Validation 和 IronPDF,讓我們看看如何將它們一起使用。本教程將幫助建立一個發票生成器,其中發票內容將在使用 IronPDF 生成 PDF 之前,在 ASP.NET Core 中使用 FluentValidation 進行驗證。
現在讓我們開始吧!
首先,讓我們在 Visual Studio 或您偏好的開發環境中建立一個新的控制台應用程式。
選擇「控制台應用程式」 (ASP.NET Core)「作為專案範本並為您的專案命名。」
建立新的控制台應用程式
點擊下一步按鈕,透過命名並選擇存儲位置配置您的專案。
配置新應用程式
點擊下一步按鈕並選擇.NET Framework。最新的.NET Framework (7) 推薦。
.NET Framework 選擇
專案建立後,我們需要添加 Fluent Validation 和 IronPDF 所需的 NuGet 套件。
搜尋「FluentValidation」並點擊「安裝」以將該套件添加到您的專案中。
安裝 FluentValidation 套件於 NuGet 套件管理器 UI
然而,你也可以使用以下命令透過 NuGet 套件管理器控制台 安裝 IronPDF:
Install-Package IronPdf
在套件管理員控制台中安裝 IronPdf 套件
在設置好專案並安裝所需套件後,讓我們繼續定義 PDF 內容類別。
在此範例中,將從新的兩個類別:InvoiceContent
和 InvoiceItem
中的 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
在上面的代碼中,定義了一個抽象的 PdfContent
類別,其中包含名為 RenderHtml
的抽象方法。InvoiceContent
類別繼承了 PdfContent
,並表示發票 PDF 的內容。它具有客戶名稱、地址和發票項目列表的屬性。InvoiceItem
類別包含兩個屬性「Description」和「Price」。RenderHtml
方法根據內容生成發票的 HTML 標記。
現在 PDF 內容已經定義好了,接下來我們來使用 Fluent Validation 創建驗證規則。
為了為 InvoiceContent
類別建立驗證規則,請建立一個名為 InvoiceContentValidator
的驗證器類別。此類別將繼承自 AbstractValidator
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
在上面的源代碼中,定義了 InvoiceContentValidator
類,它繼承自 AbstractValidator
RuleFor
方法為 InvoiceContent
類別的每個屬性定義驗證規則。
例如,RuleFor(內容 => 內容.客戶名稱)可以定義一個新規則,使客戶姓名不能為空。流暢驗證也可以鏈接
NotEmpty` 方法來指定此驗證規則。同樣的,我們為地址和發票項目的屬性定義驗證規則。
要驗證發票項目,使用 RuleForEach
方法迭代 InvoiceItems
列表中的每個項目並應用名為 InvoiceItemValidator
的驗證器。InvoiceItemValidator
類是單獨定義的,包含 InvoiceItem
類的驗證規則。
設置這些驗證規則後,讓我們開始使用 IronPDF 生成 PDF。
IronPDF 是一個受歡迎的 .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
在上面的源代碼中,我們定義了一個 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
在上面的代碼中,try-catch
塊有助於捕捉任何可能發生的異常。如果捕捉到異常,將使用 Console.WriteLine
向用戶顯示錯誤消息。
現在,讓我們通過不同的情境測試這個應用程式,以驗證 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!
在控制台中的輸出錯誤
輸出 PDF 檔案
如預期所料,前兩個情境顯示了驗證錯誤,第三個情境顯示成功訊息。
本教學探討了 Fluent Validation,並學習如何將其與 IronPDF 一起使用來生成 PDF 文件。從設置控制台應用程式和定義 PDF 內容類開始。然後,使用 Fluent Validation 創建驗證規則,並在不同的場景下測試 PDF 生成。
Fluent Validation 提供了一種靈活且易用的方法來驗證 .NET 應用中的對象。它允許您以強類型的方式定義驗證規則,自訂錯誤訊息,並優雅地處理驗證錯誤。