在實際環境中測試
在生產環境中測試無浮水印。
在任何需要的地方都能運作。
FluentValidation是一個 .NET 驗證庫,有助於建立強類型的驗證規則。 這是通過提供流暢接口和 lambda 表達式來實現的,使代碼更具可讀性和可維護性。 與其在模型類中使用數據註解或手動驗證,您可以使用Fluent Validation來建立一個單獨的類以實現驗證邏輯。
流暢驗證為驗證環節帶來更多彈性。 Fluent Validation 是 .NET Core 工具包中的強大工具,具有內建驗證器處理常見場景、建構自訂驗證的能力,以及簡單的方式來鏈結驗證規則。
Fluent Validation是一個開放原始碼的.NET庫,可以輕鬆地為您的模型類別建立驗證規則。
驗證器: 驗證器是封裝驗證邏輯的類別。 它們通常透過繼承 AbstractValidator
來創建
規則: 規則是屬性必須滿足的驗證條件。 在驗證器類別中,規則是使用 RuleFor
方法定義的。
ValidationFailure
對象,其中包含有關錯誤的詳細資訊,包括屬性名稱和錯誤訊息。IronPDF - 在 C# 中將 HTML 轉換為 PDF是一個強大的 .NET 函式庫,可以讓您從 HTML 內容生成 PDF 文件。 無論您需要創建發票、報告或任何其他類型的文件,IronPDF都提供了簡便易用的解決方案。 它可無縫整合到您的 ASP.NET Core 應用程式中,只需幾行程式碼即可生成高品質的 PDF 文件。
現在我們已經了解Fluent Validation和IronPDF是什麼了,讓我們看看它們如何能一起使用。 本教程將幫助您建立一個發票生成器,其中發票內容將在使用 IronPDF 生成 PDF 之前,使用 ASP.NET Core 中的 FluentValidation 進行驗證。
現在讓我們開始吧!
首先,讓我們在 Visual Studio 或您偏好的開發環境中創建一個新的主控台應用程式。
打開 Visual Studio,前往 檔案 > 新增 > 專案。
選擇「主控台應用程式」(ASP.NET Core)「作為專案範本並為您的專案提供名稱。」
建立新的主控台應用程式
點擊 下一步 按鈕,通過命名並選擇儲存庫位置來配置您的專案。
配置新應用程式
點擊下一步按鈕,然後選擇.NET Framework。 最新的 .NET Framework(7)建議使用。
.NET Framework 選擇
一旦專案建立,我們需要添加Fluent Validation和IronPDF所需的NuGet封裝。
在方案總管中右鍵點擊專案,然後選擇「管理 NuGet 套件」。
搜尋「FluentValidation」並點擊「Install」以將該套件添加到您的專案中。
在NuGet套件管理器UI中安裝FluentValidation套件
類似地,搜尋「IronPDF - 強大的 .NET PDF 庫並安裝IronPDF套件。
不過,您也可以使用 NuGet Package Manager Console 並使用以下命令安裝 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(內容 => 內容.客戶名稱)
可以定義一個新規則,客戶名稱不可為空。 Fluent Validation 也可以鏈接使用 NotEmpty
方法來指定此驗證規則。 同樣地,我們為地址和發票項目屬性定義驗證規則。
要驗證發票項目,使用 RuleForEach
方法迭代 InvoiceItems
清單中的每個項目,並應用名為 InvoiceItemValidator
的驗證器。 InvoiceItemValidator
類別被單獨定義,並包含 InvoiceItem
類別的驗證規則。
設置這些驗證規則後,讓我們繼續使用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
在上面的源代碼中,我們定義了一個 PdfService
類,該類提供了一個 GeneratePdf
方法。 此方法將 PdfContent
物件作為輸入,並根據驗證過的內容生成 PDF 文件。
首先,我們通過調用 GetValidatorForContent
方法獲取適合內容的驗證器。 此方法檢查內容類型並返回相應的驗證器。 在我們的案例中,我們僅支持InvoiceContent
並使用InvoiceContentValidator
。
接下來,我們透過呼叫驗證器的 validate 方法來驗證內容。 驗證結果儲存在一個 ValidationResult
物件中。
如果驗證失敗(!validationResult.IsValid),我們會拋出一個
FluentValidation.ValidationException
並包含驗證錯誤。 否則,我們將繼續使用 IronPDF 生成 PDF。
我們創建一個实例ChromePdfRenderer將 HTML 內容渲染為 PDF。 我們稱呼這個將HTML渲染為PDF在 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 生成和驗證規則。
在此程式碼範例中,有三個待測試的情境:
客戶名稱為空:將客戶名稱留空以觸發驗證錯誤。
空的發票項目:提供一個空的發票項目列表以觸發驗證錯誤。
成功產生:提供有效內容以成功生成 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 應用程式中的對象。 它允許您以強類型的方式定義驗證規則,自訂錯誤訊息,並優雅地處理驗證錯誤。
IronPDF 免費試用與授權資訊提供免費試用,許可證起始於每位開發者 $499。