跳至頁尾內容
移民指南

從 Fluid(模板)遷移到 IronPDF

Fluid 是一個 .NET 函式庫,它實作了 Liquid 模板語言,為開發人員提供了一種靈活的方式來渲染動態模板,並將內容與表示邏輯分開。 雖然 Fluid 可以有效地產生動態文字輸出,但它並不直接支援 PDF 生成——開發人員必須整合額外的 PDF 庫才能將 HTML 輸出轉換為 PDF 文件。 這種雙庫方法引入了複雜性,而許多開發團隊都試圖消除這種複雜性。

本指南提供了從 Fluid(範本)和外部 PDF 庫到 IronPDF 的完整遷移路徑,其中包含逐步說明、程式碼比較和實用範例,供正在評估此過渡的專業 .NET 開發人員參考。

為什麼要從 Fluid(模板)遷移到 IronPDF

Fluid 是一個基於 Liquid 的優秀模板引擎,但將其用於 PDF 生成會引入顯著的複雜性:

雙庫依賴: Fluid 只產生 HTML——你需要一個單獨的 PDF 庫(wkhtmltopdf、PuppeteerSharp 等)來建立 PDF,這使得你的依賴項和維護負擔翻倍。

整合複雜性:協調兩個函式庫意味著管理兩套配置、錯誤處理和更新。 當系統故障時,調試就變得更加困難。

Liquid 語法學習曲線:儘管 C# 已經內建了強大的字串處理功能,但開發人員仍然必須學習 Liquid 模板語法( {{ }}{% %} )。

PDF 控制有限:您的 PDF 輸出品質取決於您選擇搭配 Fluid 使用的 PDF 函式庫,而不是專用的渲染引擎。

偵錯挑戰:模板產生或 PDF 生成階段都可能出現錯誤,這使得故障排除比使用單一整合解決方案更加困難。

線程安全問題: TemplateContext不是線程安全的,在並發應用程式中需要謹慎管理。

IronPDF 與 Fluid(模板):功能對比

了解架構差異有助於技術決策者評估遷移投資:

方面Fluid + PDF 函式庫IronPDF
依賴關係2 個以上軟體包(Fluid + PDF 庫)單包裝
範本Liquid 語法( {{ }}C# 字串插值或 Razor
PDF生成需要外部函式庫內建鉻合金引擎
CSS 支援取決於 PDF 庫完全基於 CSS3 的 Flexbox/Grid 佈局
JavaScript取決於 PDF 庫完全支援 JavaScript
螺紋安全TemplateContext 不是線程安全的。ChromePdfRenderer 是線程安全的。
學習曲線Liquid + PDF 庫 APIHTML/CSS(網頁標準)
錯誤處理兩個誤差源單一錯誤來源

快速入門:Fluid 到 IronPDF 的遷移

透過這些基礎步驟,遷移工作可以立即開始。

步驟 1:替換 NuGet 套件

移除 Fluid 和所有外部 PDF 庫:

# Remove Fluid and external PDF library
dotnet remove package Fluid.Core
dotnet remove package WkHtmlToPdf-DotNet  # or whatever PDF library you used
dotnet remove package PuppeteerSharp       # if used
# Remove Fluid and external PDF library
dotnet remove package Fluid.Core
dotnet remove package WkHtmlToPdf-DotNet  # or whatever PDF library you used
dotnet remove package PuppeteerSharp       # if used
SHELL

安裝 IronPDF:

# Install IronPDF (all-in-one solution)
dotnet add package IronPdf
# Install IronPDF (all-in-one solution)
dotnet add package IronPdf
SHELL

步驟 2:更新命名空間

將 Fluid 命名空間替換為 IronPdf:

// Before (Fluid + external PDF library)
using Fluid;
using Fluid.Values;
using SomeExternalPdfLibrary;

// After (IronPDF)
using IronPdf;
using IronPdf.Rendering;  // For RenderingOptions
// Before (Fluid + external PDF library)
using Fluid;
using Fluid.Values;
using SomeExternalPdfLibrary;

// After (IronPDF)
using IronPdf;
using IronPdf.Rendering;  // For RenderingOptions
$vbLabelText   $csharpLabel

步驟 3:初始化許可證

在應用程式啟動時新增許可證初始化:

IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
$vbLabelText   $csharpLabel

程式碼遷移範例

基本 HTML 轉 PDF

最基本的操作揭示了這些方法之間的關鍵差異。

流體方法:

// NuGet: Install-Package Fluid.Core
using Fluid;
using System.IO;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        var parser = new FluidParser();
        var template = parser.Parse("<html><body><h1>Hello {{name}}!</h1></body></html>");
        var context = new TemplateContext();
        context.SetValue("name", "World");
        var html = await template.RenderAsync(context);

        // Fluid only generates HTML - you'd need another library to convert to PDF
        File.WriteAllText("output.html", html);
    }
}
// NuGet: Install-Package Fluid.Core
using Fluid;
using System.IO;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        var parser = new FluidParser();
        var template = parser.Parse("<html><body><h1>Hello {{name}}!</h1></body></html>");
        var context = new TemplateContext();
        context.SetValue("name", "World");
        var html = await template.RenderAsync(context);

        // Fluid only generates HTML - you'd need another library to convert to PDF
        File.WriteAllText("output.html", html);
    }
}
$vbLabelText   $csharpLabel

IronPDF 方法:

// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var html = "<html><body><h1>Hello World!</h1></body></html>";
        var pdf = renderer.RenderHtmlAsPdf(html);
        pdf.SaveAs("output.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var html = "<html><body><h1>Hello World!</h1></body></html>";
        var pdf = renderer.RenderHtmlAsPdf(html);
        pdf.SaveAs("output.pdf");
    }
}
$vbLabelText   $csharpLabel

Fluid 需要建立一個FluidParser ,解析模板字串,建立一個TemplateContext ,對每個變數呼叫SetValue() ,非同步渲染以取得 HTML,然後寫入檔案-但這仍然不是 PDF。 程式碼中的註解明確指出"Fluid 只產生 HTML - 你需要另一個函式庫才能轉換為 PDF"。

IronPDF 消除了這種複雜性:建立一個渲染器,呼叫RenderHtmlAsPdf() ,然後直接儲存為 PDF。 無需中間 HTML 文件,也無需其他庫。

如需更進階的 HTML 轉 PDF 場景,請參閱HTML 轉 PDF 轉換指南

帶有動態資料的發票模板

包含多個變數的文件範本清楚地展示了模板模式的差異。

流體方法:

// NuGet: Install-Package Fluid.Core
using Fluid;
using System;
using System.IO;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        var parser = new FluidParser();
        var template = parser.Parse(@"
            <html><body>
                <h1>Invoice #{{invoiceNumber}}</h1>
                <p>Date: {{date}}</p>
                <p>Customer: {{customer}}</p>
                <p>Total: ${{total}}</p>
            </body></html>");

        var context = new TemplateContext();
        context.SetValue("invoiceNumber", "12345");
        context.SetValue("date", DateTime.Now.ToShortDateString());
        context.SetValue("customer", "John Doe");
        context.SetValue("total", 599.99);

        var html = await template.RenderAsync(context);
        // Fluid outputs HTML - requires additional PDF library
        File.WriteAllText("invoice.html", html);
    }
}
// NuGet: Install-Package Fluid.Core
using Fluid;
using System;
using System.IO;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        var parser = new FluidParser();
        var template = parser.Parse(@"
            <html><body>
                <h1>Invoice #{{invoiceNumber}}</h1>
                <p>Date: {{date}}</p>
                <p>Customer: {{customer}}</p>
                <p>Total: ${{total}}</p>
            </body></html>");

        var context = new TemplateContext();
        context.SetValue("invoiceNumber", "12345");
        context.SetValue("date", DateTime.Now.ToShortDateString());
        context.SetValue("customer", "John Doe");
        context.SetValue("total", 599.99);

        var html = await template.RenderAsync(context);
        // Fluid outputs HTML - requires additional PDF library
        File.WriteAllText("invoice.html", html);
    }
}
$vbLabelText   $csharpLabel

IronPDF 方法:

// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var invoiceNumber = "12345";
        var date = DateTime.Now.ToShortDateString();
        var customer = "John Doe";
        var total = 599.99;

        var html = $@"
            <html><body>
                <h1>Invoice #{invoiceNumber}</h1>
                <p>Date: {date}</p>
                <p>Customer: {customer}</p>
                <p>Total: ${total}</p>
            </body></html>";

        var pdf = renderer.RenderHtmlAsPdf(html);
        pdf.SaveAs("invoice.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var invoiceNumber = "12345";
        var date = DateTime.Now.ToShortDateString();
        var customer = "John Doe";
        var total = 599.99;

        var html = $@"
            <html><body>
                <h1>Invoice #{invoiceNumber}</h1>
                <p>Date: {date}</p>
                <p>Customer: {customer}</p>
                <p>Total: ${total}</p>
            </body></html>";

        var pdf = renderer.RenderHtmlAsPdf(html);
        pdf.SaveAs("invoice.pdf");
    }
}
$vbLabelText   $csharpLabel

Fluid 使用 Liquid 的{{variable}}語法,並為每個變數使用context.SetValue() 。 該註釋明確指出"Fluid 輸出 HTML,需要額外的 PDF 庫"。 IronPDF 使用標準的 C# 字串插值( $&quot;{variable}&quot; ),這是語法開發人員熟知的,並直接輸出為 PDF。

瀏覽IronPDF 教學課程,以了解更多文件產生模式。

帶循環的動態數據

包含集合和循環的範本展示了控制流的差異。

流體方法:

// NuGet: Install-Package Fluid.Core
using Fluid;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        var parser = new FluidParser();
        var template = parser.Parse(@"
            <html><body>
                <h1>{{title}}</h1>
                <ul>
                {% for item in items %}
                    <li>{{item}}</li>
                {% endfor %}
                </ul>
            </body></html>");

        var context = new TemplateContext();
        context.SetValue("title", "My List");
        context.SetValue("items", new[] { "Item 1", "Item 2", "Item 3" });

        var html = await template.RenderAsync(context);
        // Fluid generates HTML only - separate PDF conversion needed
        File.WriteAllText("template-output.html", html);
    }
}
// NuGet: Install-Package Fluid.Core
using Fluid;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        var parser = new FluidParser();
        var template = parser.Parse(@"
            <html><body>
                <h1>{{title}}</h1>
                <ul>
                {% for item in items %}
                    <li>{{item}}</li>
                {% endfor %}
                </ul>
            </body></html>");

        var context = new TemplateContext();
        context.SetValue("title", "My List");
        context.SetValue("items", new[] { "Item 1", "Item 2", "Item 3" });

        var html = await template.RenderAsync(context);
        // Fluid generates HTML only - separate PDF conversion needed
        File.WriteAllText("template-output.html", html);
    }
}
$vbLabelText   $csharpLabel

IronPDF 方法:

// NuGet: Install-Package IronPdf
using IronPdf;
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var title = "My List";
        var items = new[] { "Item 1", "Item 2", "Item 3" };

        var html = $@"
            <html><body>
                <h1>{title}</h1>
                <ul>";

        foreach (var item in items)
        {
            html += $"<li>{item}</li>";
        }

        html += "</ul></body></html>";

        var pdf = renderer.RenderHtmlAsPdf(html);
        pdf.SaveAs("template-output.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var title = "My List";
        var items = new[] { "Item 1", "Item 2", "Item 3" };

        var html = $@"
            <html><body>
                <h1>{title}</h1>
                <ul>";

        foreach (var item in items)
        {
            html += $"<li>{item}</li>";
        }

        html += "</ul></body></html>";

        var pdf = renderer.RenderHtmlAsPdf(html);
        pdf.SaveAs("template-output.pdf");
    }
}
$vbLabelText   $csharpLabel

Fluid 使用 Liquid 的{% for item in items %}...{% endfor %}語法-這是一種開發人員必須學習的範本語言。 評論指出"Fluid 僅產生 HTML 文件,需要單獨轉換為 PDF 文件。" IronPDF 使用標準的 C# foreach循環(無需學習新語法),並直接輸出為 PDF 文件。

Fluid API 到 IronPDF 映射參考

此映射透過顯示直接的 API 等效項來加速遷移:

核心類別映射

流體類IronPDF當量筆記
FluidParser不適用無需使用—請使用 C# 字串。
FluidTemplate不適用不需要
TemplateContextC# 物件/字串直接傳遞數據
TemplateOptionsRenderingOptionsPDF 輸出配置
FluidValue原生 C# 類型無需轉換
外部 PDF 類ChromePdfRenderer主渲染類

方法映射

流體法IronPDF當量筆記
new FluidParser()new ChromePdfRenderer()建立渲染器
parser.Parse(source)不適用不需要——HTML 是一個字串。
template.RenderAsync(context)renderer.RenderHtmlAsPdf(html)直接 PDF 渲染
context.SetValue("key", value)var key = value;使用 C# 變數

Liquid 語法到 C# 的映射

液態文法C# 等效項筆記
{{ variable }}$"{variable}"字串插值
{% for item in items %}foreach (var item in items)C# 循環
{% if condition %}if (condition)C# 條件語句
{{ x \| 大寫 }}x.ToUpper()C# 方法
{{ x \| 日期:&#39;%Y-%m-%d&#39; }}x.ToString("yyyy-MM-dd")C# 格式化
{{ x \| number_with_precision: 2 }}x.ToString("F2")C# 數字格式化

常見遷移問題及解決方案

問題 1:Liquid 語法轉換

Fluid:使用{{ variable }}{% control %}語法。

解決方案:使用 C# 字串插值和控制流進行替換:

// Liquid: {{ name | upcase }}
// C#: $"{name.ToUpper()}"

// Liquid: {% for item in items %}{{item}}{% endfor %}
// C#: foreach (var item in items) { html += $"{item}"; }
// Liquid: {{ name | upcase }}
// C#: $"{name.ToUpper()}"

// Liquid: {% for item in items %}{{item}}{% endfor %}
// C#: foreach (var item in items) { html += $"{item}"; }
$vbLabelText   $csharpLabel

問題 2:模板上下文變數

Fluid:使用context.SetValue(&quot;key&quot;, value)傳遞資料。

解決方案:使用標準的 C# 變數:

// Before (Fluid)
var context = new TemplateContext();
context.SetValue("customer", customerName);

// After (IronPDF)
var customer = customerName;
var html = $"<p>Customer: {customer}</p>";
// Before (Fluid)
var context = new TemplateContext();
context.SetValue("customer", customerName);

// After (IronPDF)
var customer = customerName;
var html = $"<p>Customer: {customer}</p>";
$vbLabelText   $csharpLabel

第三期:螺紋安全

Fluid: TemplateContext不是線程安全的,需要在並發應用程式中謹慎管理。

解決方案: ChromePdfRenderer是線程安全的,可以在線程間共享:

// Thread-safe usage
private static readonly ChromePdfRenderer _renderer = new ChromePdfRenderer();

public byte[] GeneratePdf(string html)
{
    var pdf = _renderer.RenderHtmlAsPdf(html);
    return pdf.BinaryData;
}
// Thread-safe usage
private static readonly ChromePdfRenderer _renderer = new ChromePdfRenderer();

public byte[] GeneratePdf(string html)
{
    var pdf = _renderer.RenderHtmlAsPdf(html);
    return pdf.BinaryData;
}
$vbLabelText   $csharpLabel

問題 4:兩階段錯誤處理

Fluid:模板製作階段或 PDF 產生階段都可能出現錯誤。

解決方案: IronPDF 只有一個錯誤來源:

try
{
    var pdf = renderer.RenderHtmlAsPdf(html);
    pdf.SaveAs("output.pdf");
}
catch (Exception ex)
{
    // Single point of failure—easier debugging
    Console.WriteLine($"PDF generation failed: {ex.Message}");
}
try
{
    var pdf = renderer.RenderHtmlAsPdf(html);
    pdf.SaveAs("output.pdf");
}
catch (Exception ex)
{
    // Single point of failure—easier debugging
    Console.WriteLine($"PDF generation failed: {ex.Message}");
}
$vbLabelText   $csharpLabel

流體遷移檢查清單

遷移前任務

審核您的程式碼庫,找出所有 Fluid 的使用情況:

# Find all Fluid references
grep -r "FluidParser\|FluidTemplate\|TemplateContext\|using Fluid" --include="*.cs" --include="*.csproj" .

# Find Liquid template files
find . -name "*.liquid" -o -name "*.html" | xargs grep -l "{{"
# Find all Fluid references
grep -r "FluidParser\|FluidTemplate\|TemplateContext\|using Fluid" --include="*.cs" --include="*.csproj" .

# Find Liquid template files
find . -name "*.liquid" -o -name "*.html" | xargs grep -l "{{"
SHELL

記錄所有範本:文件位置、使用的變數、迴圈和條件語句以及外部 PDF 庫配置。

程式碼更新任務

  1. 刪除 Fluid.Core NuGet 套件
  2. 刪除外部 PDF 庫包
  3. 安裝 IronPdf NuGet 套件
  4. 將命名空間導入從Fluid更新為IronPdf
  5. {{ variable }}轉換為$&quot;{variable}&quot;
  6. {% for item in collection %}轉換為 C# foreach
  7. {% if condition %}轉換為 C# if語句
  8. 將 Liquid 過濾器轉換為 C# 方法(例如,| upcase.ToUpper())
  9. FluidParser替換為ChromePdfRenderer
  10. TemplateContext.SetValue()替換為直接的 C# 變數
  11. 移除外部 PDF 函式庫調用
  12. 新增 IronPDF 啟動時許可證初始化功能

遷移後測試

遷移完成後,請確認以下幾個面向:

  • 驗證 PDF 輸出是否符合預期
  • 測試所有模板變體是否都能正確渲染
  • 檢查影像和樣式顯示是否正確
  • 驗證分頁符號是否正確出現
  • 使用不同資料量進行測試
  • 效能測試比較 Fluid + 外部函式庫
  • 測試並發場景下的線程安全性

清理任務

  • 刪除.liquid模板檔案(如果不再需要)
  • 移除與 Fluid 相關的輔助代碼
  • 更新文檔
  • 清理未使用的依賴項

遷移到 IronPDF 的主要優勢

從使用外部 PDF 庫的 Fluid(模板)遷移到 IronPDF 可以帶來幾個關鍵優勢:

單包解決方案:消除對兩個庫的依賴。 IronPDF 在一個軟體包中同時處理範本(透過 HTML/CSS)和 PDF 產生。

無需學習新語法:使用標準的 C# 字串插值和控制流,而不是學習 Liquid 模板語法。

線程安全渲染: ChromePdfRenderer是線程安全的,與TemplateContext不同,簡化了並發 PDF 生成。

Chromium 渲染引擎:業界標準渲染確保完全支援 CSS3,包括 Flexbox 和 Grid,以及完整的 JavaScript 執行。

單一錯誤來源:只需對一個函式庫進行故障排除,而無需在範本和 PDF 產生階段之間進行協調,從而簡化了偵錯過程。

積極開發:隨著 .NET 10 和 C# 14 的普及,IronPDF 將持續更新,確保與目前和未來的 .NET 版本相容。

柯蒂斯·週
技術撰稿人

Curtis Chau擁有卡爾頓大學電腦科學學士學位,專長於前端開發,精通Node.js、TypeScript、JavaScript和React。他熱衷於打造直覺美觀的使用者介面,喜歡使用現代框架,並擅長撰寫結構清晰、視覺效果出色的使用者手冊。

除了開發工作之外,柯蒂斯對物聯網 (IoT) 也抱有濃厚的興趣,致力於探索硬體和軟體整合的創新方法。閒暇時,他喜歡玩遊戲和製作 Discord 機器人,將他對科技的熱愛與創造力結合。