跳過到頁腳內容
使用IRONPDF

如何使用IronPDF創建.NET PDF API

當您使用現代應用程序時,如您這樣的 .NET 開發人員可能需要構建一個集中化的 PDF 生成服務。無論您是在生成發票、報告、證書或合同,擁有專用的 .NET PDF API 對於高效管理 PDF 文件都非常有利。 那麼這如何改善您的 PDF 生成任務呢? 它通過在您的桌面和網頁應用程序中提供一致性、可維護性和可擴展性來實現這一點。 以前從未如此簡單地管理文檔內容、PDF 頁面和 PDF 表單字段。

在本教程中,您將學習如何使用 ASP.NET Core 和 IronPDF 構建一個可投入生產的 PDF API,這是一個功能強大的 .NET PDF 庫。 我們將創建 RESTful 端點,可以從 HTML 生成 PDF,合併文檔,添加水印,並在您的 Web API 中處理各種實際的 PDF 生成場景。

為什麽要構建專用的 PDF API?

在深入研究代碼之前,讓我們了解為什麼創建專用的 PDF API 有意義:

  • 集中邏輯:所有 PDF 生成邏輯都集中在一個地方,使維護和更新更容易
  • 微服務架構:適合需要 PDF 功能的服務導向架構的不同應用程序
  • 性能優化:專用服務易於對大型 PDF 文件、多頁面和動態數據進行擴展和優化。
  • 語言無關:任何客戶端應用程序都可以不受編程語言的約束使用該 API
  • 一致的輸出:確保您組織內的所有 PDF 文檔保持一致的文檔佈局、段落格式和 PDF 內容。

準備好開始構建了嗎? 下載IronPDF 的免費試用版,並按照本教程編程創建您的 .NET Framework 項目中的 PDF 文件。

IronPDF:完整的 .NET PDF 庫

IronPDF 脫穎而出,成為 .NET 開發人員的首選 PDF 庫,提供了一整套功能,使 Web API 項目中的 PDF 生成變得簡單直接且可靠。 它建立在 Chrome 渲染引擎之上,可確保精確的HTML 到 PDF 轉換,通常只需幾行代碼即可完成。 它在執行所有設計樣式、JavaScript 執行和響應式佈局的同時完成所有這些操作。

使 IronPDF 成為 .NET PDF API 開發理想選擇的關鍵能力:

  • 基於 Chrome 的渲染:利用 Google Chrome 的渲染引擎,準確地從 HTML 內容轉換 PDF 文檔,全面支持內嵌圖像和其他網頁資產
  • Rich Feature Set: Supports the editing of new and existing documents with digital signatures, PDF forms, annotations, encryption, compression, and more
  • 創建安全的 PDF 文檔:使用加密、數字簽名和文檔保護來管理敏感的 PDF 內容。
  • Multiple Input Formats: Use HTML, URLs, images, and Office documents to create PDF documents
  • 高級操作:合併 PDF 頁面、拆分文檔、應用水印、創建交互式 PDF 表單並以程序方式操縱 PDF 文件。
  • Cross-Platform Support: Works on Windows, Linux, macOS, Docker, and cloud platforms
  • 性能優化異步操作,高效的內存管理和快速渲染

如何設置您的 PDF 文檔 API 項目?

我們從創建一個新的 ASP.NET Core Web API 項目並安裝必要的包開始吧。

先決條件

  • .NET 6.0 SDK 或更新版本
  • Visual Studio 2022 或 Visual Studio Code
  • Postman 或類似的 API 測試工具來測試您的 PDF REST API

創建項目

首先,讓我們創建項目,並在其中構建我們的 PDF 生成工具。

dotnet new webapi -n PdfApiService
cd PdfApiService

安裝 IronPDF

下一步是通過 NuGet 將 IronPDF 添加到您的項目中:

dotnet add package IronPdf

或者,在 Visual Studio 中使用 NuGet 套件管理器控制台:

Install-Package IronPdf

項目結構

C# 開發的一個重要方面是保持清晰且結構良好的項目文件夾。 例如:

如何創建您的第一個 PDF 端點?

讓我們構建一個將 HTML 轉換為 PDF 格式的簡單端點。 首先,創建服務接口和實現:

創建 PDF 服務

首先,我們將以下內容添加到 IPdfService.cs 文件中:

public interface IPdfService
{
    byte[] GeneratePdfFromHtml(string htmlContent);
    byte[] GeneratePdfFromUrl(string url);
}
public interface IPdfService
{
    byte[] GeneratePdfFromHtml(string htmlContent);
    byte[] GeneratePdfFromUrl(string url);
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

在 PdfService.cs 文件中,我們將添加以下內容:

using IronPdf;
public class PdfService : IPdfService
{
    private readonly ChromePdfRenderer _renderer;
    public PdfService()
    {
        _renderer = new ChromePdfRenderer();
        // Configure rendering options for optimal PDF generation in .NET
        _renderer.RenderingOptions.MarginTop = 20;
        _renderer.RenderingOptions.MarginBottom = 20;
        _renderer.RenderingOptions.PrintHtmlBackgrounds = true;
    }
    public byte[] GeneratePdfFromHtml(string htmlContent)
    {
        // Generate PDF from HTML using the .NET PDF API
        var pdf = _renderer.RenderHtmlAsPdf(htmlContent);
        return pdf.BinaryData;
    }
    public byte[] GeneratePdfFromUrl(string url)
    {
        // Convert URL to PDF in the REST API
        var pdf = _renderer.RenderUrlAsPdf(url);
        return pdf.BinaryData;
    }
}
using IronPdf;
public class PdfService : IPdfService
{
    private readonly ChromePdfRenderer _renderer;
    public PdfService()
    {
        _renderer = new ChromePdfRenderer();
        // Configure rendering options for optimal PDF generation in .NET
        _renderer.RenderingOptions.MarginTop = 20;
        _renderer.RenderingOptions.MarginBottom = 20;
        _renderer.RenderingOptions.PrintHtmlBackgrounds = true;
    }
    public byte[] GeneratePdfFromHtml(string htmlContent)
    {
        // Generate PDF from HTML using the .NET PDF API
        var pdf = _renderer.RenderHtmlAsPdf(htmlContent);
        return pdf.BinaryData;
    }
    public byte[] GeneratePdfFromUrl(string url)
    {
        // Convert URL to PDF in the REST API
        var pdf = _renderer.RenderUrlAsPdf(url);
        return pdf.BinaryData;
    }
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

PdfService 負責將 HTML 轉換為 PDF 的核心過程。 利用 IronPDF 的 ChromePdfRenderer,此類設置了合理的默認值,例如頁邊距和背景渲染以產生優雅的最終文檔。

當控制器傳入原始 HTML 時,該服務使用 IronPDF 將其渲染為專業質量的 PDF,並將結果返回為字節數據,準備好下載。 此外,它還可以通過直接將 URL 轉換為 PDF 來處理整個網頁。

創建控制器

現在是時候為我們的 API 創建控制器了。 這將提供一個 API 端點,能夠從 HTML 生成 PDF 文件。 然後它能夠將 PDF 文檔下載並保存到您的系統中以供進一步使用或共享。

// Controllers/PdfController.cs
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class PdfController : ControllerBase
{
    private readonly IPdfService _pdfService;
    public PdfController(IPdfService pdfService)
    {
        _pdfService = pdfService;
    }
    [HttpPost("html-to-pdf")]
    public IActionResult ConvertHtmlToPdf([FromBody] HtmlRequest request)
    {
        try
        {
            var pdfBytes = _pdfService.GeneratePdfFromHtml(request.HtmlContent);
            // Return as downloadable file
            return File(pdfBytes, "application/pdf", "document.pdf");
        }
        catch (Exception ex)
        {
            return BadRequest($"Error generating PDF: {ex.Message}");
        }
    }
}
// Controllers/PdfController.cs
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class PdfController : ControllerBase
{
    private readonly IPdfService _pdfService;
    public PdfController(IPdfService pdfService)
    {
        _pdfService = pdfService;
    }
    [HttpPost("html-to-pdf")]
    public IActionResult ConvertHtmlToPdf([FromBody] HtmlRequest request)
    {
        try
        {
            var pdfBytes = _pdfService.GeneratePdfFromHtml(request.HtmlContent);
            // Return as downloadable file
            return File(pdfBytes, "application/pdf", "document.pdf");
        }
        catch (Exception ex)
        {
            return BadRequest($"Error generating PDF: {ex.Message}");
        }
    }
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

然後,在 HtmlRequest.cs 文件中,我們將添加這個:

// Models/HtmlRequest.cs
public class HtmlRequest
{
    public string HtmlContent { get; set; }
    public string FileName { get; set; } = "document.pdf";
}
// Models/HtmlRequest.cs
public class HtmlRequest
{
    public string HtmlContent { get; set; }
    public string FileName { get; set; } = "document.pdf";
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

在第一個文件中,我們設置了一個簡單的 API 端點,將 HTML 轉換為可下載的 PDF。 當有人向 api/pdf/html-to-pdf 路徑發送簡單的 POST 請求時,PdfController 將處理將其轉換為 PDF 的工作分配給專用服務。

創建 PDF 後,控制器將其作為準備下載的文件返回給用戶。請求本身是使用 HtmlRequest 模型構建的,它攜帶原始 HTML 和最終文檔的可選文件名。 簡而言之,此設置使客戶端能夠輕鬆發送 HTML 並立即收到優雅的 PDF 回應。

註冊服務

更新您的 Program.cs 以註冊 PDF 服務:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Register PDF service
builder.Services.AddSingleton<IPdfService, PdfService>();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.MapControllers();
app.Run();
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Register PDF service
builder.Services.AddSingleton<IPdfService, PdfService>();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.MapControllers();
app.Run();
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

如何處理不同的響應類型?

您的 API 應支持根據客戶端需求返回 PDF 的不同方式:

[HttpPost("generate")]
 public IActionResult GeneratePdf([FromBody] PdfRequest request)
 {
     var pdfBytes = _pdfService.GeneratePdfFromHtml(request.HtmlContent);
     switch (request.ResponseType?.ToLower())
     {
         case "base64":
             return Ok(new
             {
                 data = Convert.ToBase64String(pdfBytes),
                 filename = request.FileName
             });
         case "inline":
             return File(pdfBytes, "application/pdf");
         default: // download
             return File(pdfBytes, "application/pdf", request.FileName);
     }
 }
[HttpPost("generate")]
 public IActionResult GeneratePdf([FromBody] PdfRequest request)
 {
     var pdfBytes = _pdfService.GeneratePdfFromHtml(request.HtmlContent);
     switch (request.ResponseType?.ToLower())
     {
         case "base64":
             return Ok(new
             {
                 data = Convert.ToBase64String(pdfBytes),
                 filename = request.FileName
             });
         case "inline":
             return File(pdfBytes, "application/pdf");
         default: // download
             return File(pdfBytes, "application/pdf", request.FileName);
     }
 }
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

在此處,我們向控制器添加了一個更靈活的 PDF 生成端點。 通過不斷強制文件下載,GeneratePdf 方法允許客戶端選擇希望以何種方式返回結果。 此選項提供靈活性,允許以多種格式顯示 PDF:作為可下載文件,直接在瀏覽器中或作為 Base64 字串編碼以便於在 API 中使用。

請求由 PdfRequest 模型定義,該模型基於先前的 HtmlRequest 並添加了 ResponseType 選項。 簡而言之,這給用戶提供了更多控制如何接收他們的 PDF,使 API 更加多功能且用戶友好。

現在,當我們運行程序時,我們將在 Swagger 上看到這個輸出。

如何使用 IronPDF 創建 .NET PDF API:圖 4 - Swagger UI

如何實施常見的 PDF 操作?

我們來擴展我們的服務以處理各種 PDF 生成場景:

URL 轉 PDF 轉換

[HttpPost("url-to-pdf")]
public async Task<IActionResult> ConvertUrlToPdf([FromBody] UrlRequest request)
{
    try
    {
        var pdfBytes = await Task.Run(() => 
            _pdfService.GeneratePdfFromUrl(request.Url));
        return File(pdfBytes, "application/pdf", 
            $"{request.FileName ?? "website"}.pdf");
    }
    catch (Exception ex)
    {
        return BadRequest($"Failed to convert URL: {ex.Message}");
    }
}
public class UrlRequest
{
    public string Url { get; set; }
    public string FileName { get; set; }
}
[HttpPost("url-to-pdf")]
public async Task<IActionResult> ConvertUrlToPdf([FromBody] UrlRequest request)
{
    try
    {
        var pdfBytes = await Task.Run(() => 
            _pdfService.GeneratePdfFromUrl(request.Url));
        return File(pdfBytes, "application/pdf", 
            $"{request.FileName ?? "website"}.pdf");
    }
    catch (Exception ex)
    {
        return BadRequest($"Failed to convert URL: {ex.Message}");
    }
}
public class UrlRequest
{
    public string Url { get; set; }
    public string FileName { get; set; }
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

此端點允許客戶端發送 URL 並獲取該網頁的可下載 PDF。 當 POST /api/pdf/url-to-pdf 請求到來時,控制器使用 _pdfService 在後台將給定的 URL 轉換為 PDF 字節,然後將其作為文件下載返回。 如果在轉換過程中發生問題,它會以清晰的錯誤信息優雅地回應。

我們來試試使用 URL "https://www.apple.com/nz",並測試 POST 請求。以下是我們獲得的輸出。

輸出

如何使用 IronPDF 創建 .NET PDF API:圖 5 - 網址 PDF 輸出

添加自定義水印

public byte[] AddWatermarkFromFile(string filePath, string watermarkText)
{
    // Load PDF directly from file
    var pdf = PdfDocument.FromFile(filePath);
    pdf.ApplyWatermark(
        $"<h1 style='color:red;font-size:72px;'>{watermarkText}</h1>",
        75,
        IronPdf.Editing.VerticalAlignment.Middle,
        IronPdf.Editing.HorizontalAlignment.Center
    );
    return pdf.BinaryData;
}
public byte[] AddWatermarkFromFile(string filePath, string watermarkText)
{
    // Load PDF directly from file
    var pdf = PdfDocument.FromFile(filePath);
    pdf.ApplyWatermark(
        $"<h1 style='color:red;font-size:72px;'>{watermarkText}</h1>",
        75,
        IronPdf.Editing.VerticalAlignment.Middle,
        IronPdf.Editing.HorizontalAlignment.Center
    );
    return pdf.BinaryData;
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

在這裡,我們只是手動加載本地文件以進行測試。 但是,您可以做調整,使您的 PDF API 生成 PDF 文檔,然後輕鬆對其應用自定義水印。

水印輸出

如何使用 IronPDF 創建 .NET PDF API:圖 6 - 來自上面代碼示例的水印輸出

如何添加具有模板的動態數據

對於真實世界的應用程序,您通常需要從具有動態數據的模板生成 PDF:

[HttpPost("from-template")]
public IActionResult GenerateFromTemplate([FromBody] TemplateRequest request)
{
    // Simple template replacement
    var html = request.Template;
    foreach (var item in request.Data)
    {
        html = html.Replace($"{{{{{item.Key}}}}}", item.Value);
    }
    var pdfBytes = _pdfService.GeneratePdfFromHtml(html);
    return File(pdfBytes, "application/pdf", request.FileName);
}
public class TemplateRequest
{
    public string Template { get; set; }
    public Dictionary<string, string> Data { get; set; }
    public string FileName { get; set; } = "document.pdf";
}
[HttpPost("from-template")]
public IActionResult GenerateFromTemplate([FromBody] TemplateRequest request)
{
    // Simple template replacement
    var html = request.Template;
    foreach (var item in request.Data)
    {
        html = html.Replace($"{{{{{item.Key}}}}}", item.Value);
    }
    var pdfBytes = _pdfService.GeneratePdfFromHtml(html);
    return File(pdfBytes, "application/pdf", request.FileName);
}
public class TemplateRequest
{
    public string Template { get; set; }
    public Dictionary<string, string> Data { get; set; }
    public string FileName { get; set; } = "document.pdf";
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

想了解更高級的模板場景,包括 Razor、Handlebars 或其他引擎,請查看 IronPDF 的 HTML 到 PDF 文檔。 You can also explore CSHTML to PDF conversion for MVC applications and Razor to PDF for Blazor applications.

如何優化性能?

在構建生產 PDF API 時,性能至關重要。 以下是關鍵的優化策略:

異步操作

在構建涉及 I/O 操作的項目時,明智的做法是使用異步編碼。 如果您的 PDF 內容來自外部資源,如:

  • 下載 HTML 頁面(RenderUrlAsPdf)
  • 通過 HTTP 獲取圖像、CSS 或字體
  • 讀取/寫入磁盤或雲存儲中的文件

這些操作然後可以阻止一個線程,但使用異步防止您的 API 線程閒置等待。

示例:

public async Task<byte[]> GeneratePdfFromHtmlAsync(string htmlContent)
{
    return await Task.Run(() => 
    {
        var pdf = _renderer.RenderHtmlAsPdf(htmlContent);
        return pdf.BinaryData;
    });
}
public async Task<byte[]> GeneratePdfFromHtmlAsync(string htmlContent)
{
    return await Task.Run(() => 
    {
        var pdf = _renderer.RenderHtmlAsPdf(htmlContent);
        return pdf.BinaryData;
    });
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

渲染選項

配置 IronPDF 以實現最佳性能:

_renderer.RenderingOptions.EnableJavaScript = false; // If JS not needed
_renderer.RenderingOptions.CssMediaType = PdfCssMediaType.Print;
_renderer.RenderingOptions.RenderDelay = 0; // Remove if no JS
_renderer.RenderingOptions.Timeout = 30; // Set reasonable timeout
_renderer.RenderingOptions.EnableJavaScript = false; // If JS not needed
_renderer.RenderingOptions.CssMediaType = PdfCssMediaType.Print;
_renderer.RenderingOptions.RenderDelay = 0; // Remove if no JS
_renderer.RenderingOptions.Timeout = 30; // Set reasonable timeout
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

如何保護您的 PDF API?

安全對於任何生產 API 都很重要。 這裡是簡單的 API 鑰匙身份驗證方法:

// Middleware/ApiKeyMiddleware.cs
public class ApiKeyMiddleware
{
    private readonly RequestDelegate _next;
    private const string ApiKeyHeader = "X-API-Key";
    public ApiKeyMiddleware(RequestDelegate next)
    {
        _next = next;
    }
    public async Task InvokeAsync(HttpContext context)
    {
        if (!context.Request.Headers.TryGetValue(ApiKeyHeader, out var apiKey))
        {
            context.Response.StatusCode = 401;
            await context.Response.WriteAsync("API Key required");
            return;
        }
        // Validate API key (in production, check against database)
        var validApiKey = context.RequestServices
            .GetRequiredService<IConfiguration>()["ApiKey"];
        if (apiKey != validApiKey)
        {
            context.Response.StatusCode = 403;
            await context.Response.WriteAsync("Invalid API Key");
            return;
        }
        await _next(context);
    }
}
// In Program.cs
app.UseMiddleware<ApiKeyMiddleware>();
// Middleware/ApiKeyMiddleware.cs
public class ApiKeyMiddleware
{
    private readonly RequestDelegate _next;
    private const string ApiKeyHeader = "X-API-Key";
    public ApiKeyMiddleware(RequestDelegate next)
    {
        _next = next;
    }
    public async Task InvokeAsync(HttpContext context)
    {
        if (!context.Request.Headers.TryGetValue(ApiKeyHeader, out var apiKey))
        {
            context.Response.StatusCode = 401;
            await context.Response.WriteAsync("API Key required");
            return;
        }
        // Validate API key (in production, check against database)
        var validApiKey = context.RequestServices
            .GetRequiredService<IConfiguration>()["ApiKey"];
        if (apiKey != validApiKey)
        {
            context.Response.StatusCode = 403;
            await context.Response.WriteAsync("Invalid API Key");
            return;
        }
        await _next(context);
    }
}
// In Program.cs
app.UseMiddleware<ApiKeyMiddleware>();
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

對於更高級的身份驗證場景,考慮:

Real-World 示例: Invoice Generation API

讓我們構建一個實用的發票生成端點,展示完整的實施。 此示例顯示了一個生產 .NET PDF API 如何生成具有動態數據的專業發票。

立即開始使用 IronPDF。
green arrow pointer

首先,我們將在 Models 文件夾中創建一個新文件。 在這裡,我將其命名為 Invoice.cs。 然後將以下代碼添加到新文件中。

public class Invoice
{
    public string InvoiceNumber { get; set; }
    public DateTime Date { get; set; }
    public string CustomerName { get; set; }
    public string CustomerAddress { get; set; }
    public List<InvoiceItem> Items { get; set; }
    public decimal Tax { get; set; }
}
public class InvoiceItem
{
    public string Description { get; set; }
    public int Quantity { get; set; }
    public decimal UnitPrice { get; set; }
    public decimal Total => Quantity * UnitPrice;
}
public class Invoice
{
    public string InvoiceNumber { get; set; }
    public DateTime Date { get; set; }
    public string CustomerName { get; set; }
    public string CustomerAddress { get; set; }
    public List<InvoiceItem> Items { get; set; }
    public decimal Tax { get; set; }
}
public class InvoiceItem
{
    public string Description { get; set; }
    public int Quantity { get; set; }
    public decimal UnitPrice { get; set; }
    public decimal Total => Quantity * UnitPrice;
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

然後,我們需要為發票生成器創建一個新的服務文件。 在您的 Services 文件夾中添加以下代碼。 對於我來說,我創建了一個名為 InvoiceService.cs 的新文件。 此代碼將處理我們的發票 PDF 文件的樣式和佈局。

public class InvoiceService
{
    private readonly ChromePdfRenderer _renderer;
    public InvoiceService()
    {
        _renderer = new ChromePdfRenderer();
        _renderer.RenderingOptions.MarginTop = 10;
        _renderer.RenderingOptions.MarginBottom = 10;
        _renderer.RenderingOptions.PrintHtmlBackgrounds = true;
    }
    public byte[] GenerateInvoice(Invoice invoice)
{
    var html = BuildInvoiceHtml(invoice);
    // Add footer with page numbers
    _renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
    {
        MaxHeight = 15,
        HtmlFragment = "<center><i>{page} of {total-pages}</i></center>",
        DrawDividerLine = true
    };
    var pdf = _renderer.RenderHtmlAsPdf(html);
    return pdf.BinaryData;
}
    private string BuildInvoiceHtml(Invoice invoice)
    {
        var subtotal = invoice.Items.Sum(i => i.Total);
        var taxAmount = subtotal * (invoice.Tax / 100);
        var total = subtotal + taxAmount;
        var itemsHtml = string.Join("", invoice.Items.Select(item => 
            $@"<tr>
                <td>{item.Description}</td>
                <td class='text-center'>{item.Quantity}</td>
                <td class='text-right'>${item.UnitPrice:F2}</td>
                <td class='text-right'>${item.Total:F2}</td>
            </tr>"));
        return $@"
        <!DOCTYPE html>
        <html>
        <head>
            <style>
                body {{ font-family: Arial, sans-serif; }}
                .invoice-header {{ 
                    background-color: #f8f9fa; 
                    padding: 20px; 
                    margin-bottom: 20px; 
                }}
                table {{ 
                    width: 100%; 
                    border-collapse: collapse; 
                }}
                th, td {{ 
                    padding: 10px; 
                    border-bottom: 1px solid #ddd; 
                }}
                th {{ 
                    background-color: #007bff; 
                    color: white; 
                }}
                .text-right {{ text-align: right; }}
                .text-center {{ text-align: center; }}
                .total-section {{ 
                    margin-top: 20px; 
                    text-align: right; 
                }}
            </style>
        </head>
        <body>
            <div class='invoice-header'>
                <h1>Invoice #{invoice.InvoiceNumber}</h1>
                <p>Date: {invoice.Date:yyyy-MM-dd}</p>
            </div>   
            <div>
                <h3>Bill To:</h3>
                <p>{invoice.CustomerName}<br/>{invoice.CustomerAddress}</p>
            </div>    
            <table>
                <thead>
                    <tr>
                        <th>Description</th>
                        <th>Quantity</th>
                        <th>Unit Price</th>
                        <th>Total</th>
                    </tr>
                </thead>
                <tbody>
                    {itemsHtml}
                </tbody>
            </table>
            <div class='total-section'>
                <p>Subtotal: ${subtotal:F2}</p>
                <p>Tax ({invoice.Tax}%): ${taxAmount:F2}</p>
                <h3>Total: ${total:F2}</h3>
            </div>
        </body>
        </html>";
    }
}
public class InvoiceService
{
    private readonly ChromePdfRenderer _renderer;
    public InvoiceService()
    {
        _renderer = new ChromePdfRenderer();
        _renderer.RenderingOptions.MarginTop = 10;
        _renderer.RenderingOptions.MarginBottom = 10;
        _renderer.RenderingOptions.PrintHtmlBackgrounds = true;
    }
    public byte[] GenerateInvoice(Invoice invoice)
{
    var html = BuildInvoiceHtml(invoice);
    // Add footer with page numbers
    _renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
    {
        MaxHeight = 15,
        HtmlFragment = "<center><i>{page} of {total-pages}</i></center>",
        DrawDividerLine = true
    };
    var pdf = _renderer.RenderHtmlAsPdf(html);
    return pdf.BinaryData;
}
    private string BuildInvoiceHtml(Invoice invoice)
    {
        var subtotal = invoice.Items.Sum(i => i.Total);
        var taxAmount = subtotal * (invoice.Tax / 100);
        var total = subtotal + taxAmount;
        var itemsHtml = string.Join("", invoice.Items.Select(item => 
            $@"<tr>
                <td>{item.Description}</td>
                <td class='text-center'>{item.Quantity}</td>
                <td class='text-right'>${item.UnitPrice:F2}</td>
                <td class='text-right'>${item.Total:F2}</td>
            </tr>"));
        return $@"
        <!DOCTYPE html>
        <html>
        <head>
            <style>
                body {{ font-family: Arial, sans-serif; }}
                .invoice-header {{ 
                    background-color: #f8f9fa; 
                    padding: 20px; 
                    margin-bottom: 20px; 
                }}
                table {{ 
                    width: 100%; 
                    border-collapse: collapse; 
                }}
                th, td {{ 
                    padding: 10px; 
                    border-bottom: 1px solid #ddd; 
                }}
                th {{ 
                    background-color: #007bff; 
                    color: white; 
                }}
                .text-right {{ text-align: right; }}
                .text-center {{ text-align: center; }}
                .total-section {{ 
                    margin-top: 20px; 
                    text-align: right; 
                }}
            </style>
        </head>
        <body>
            <div class='invoice-header'>
                <h1>Invoice #{invoice.InvoiceNumber}</h1>
                <p>Date: {invoice.Date:yyyy-MM-dd}</p>
            </div>   
            <div>
                <h3>Bill To:</h3>
                <p>{invoice.CustomerName}<br/>{invoice.CustomerAddress}</p>
            </div>    
            <table>
                <thead>
                    <tr>
                        <th>Description</th>
                        <th>Quantity</th>
                        <th>Unit Price</th>
                        <th>Total</th>
                    </tr>
                </thead>
                <tbody>
                    {itemsHtml}
                </tbody>
            </table>
            <div class='total-section'>
                <p>Subtotal: ${subtotal:F2}</p>
                <p>Tax ({invoice.Tax}%): ${taxAmount:F2}</p>
                <h3>Total: ${total:F2}</h3>
            </div>
        </body>
        </html>";
    }
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

最後,您需要創建一個新的控制器,以便通過 API 訪問和創建新的發票。

[ApiController]
[Route("api/[controller]")]
public class InvoiceController : ControllerBase
{
    private readonly InvoiceService _invoiceService;
    public InvoiceController(InvoiceService invoiceService)
    {
        _invoiceService = invoiceService;
    }
    [HttpPost("generate")]
    public IActionResult GenerateInvoice([FromBody] Invoice invoice)
    {
        try
        {
            var pdfBytes = _invoiceService.GenerateInvoice(invoice);
            var fileName = $"Invoice_{invoice.InvoiceNumber}.pdf";
            return File(pdfBytes, "application/pdf", fileName);
        }
        catch (Exception ex)
        {
            return StatusCode(500, $"Error generating invoice: {ex.Message}");
        }
    }
}
[ApiController]
[Route("api/[controller]")]
public class InvoiceController : ControllerBase
{
    private readonly InvoiceService _invoiceService;
    public InvoiceController(InvoiceService invoiceService)
    {
        _invoiceService = invoiceService;
    }
    [HttpPost("generate")]
    public IActionResult GenerateInvoice([FromBody] Invoice invoice)
    {
        try
        {
            var pdfBytes = _invoiceService.GenerateInvoice(invoice);
            var fileName = $"Invoice_{invoice.InvoiceNumber}.pdf";
            return File(pdfBytes, "application/pdf", fileName);
        }
        catch (Exception ex)
        {
            return StatusCode(500, $"Error generating invoice: {ex.Message}");
        }
    }
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

發票輸出

如何使用 IronPDF 創建 .NET PDF API:圖 7 - PDF 發票輸出

容器部署注意事項

雖然本教程側重於本地開發,但這裡對您的 PDF API 進行容器化的概述:

基本 Dockerfile

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["PdfApiService.csproj", "."]
RUN dotnet restore
COPY . .
RUN dotnet build -c Release -o /app/build
FROM build AS publish
RUN dotnet publish -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
# IronPDF requires additional dependencies on Linux
RUN apt-get update && apt-get install -y \
    libgdiplus \
    libc6-dev \
    libx11-dev \
    && rm -rf /var/lib/apt/lists/*     
ENTRYPOINT ["dotnet", "PdfApiService.dll"]
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["PdfApiService.csproj", "."]
RUN dotnet restore
COPY . .
RUN dotnet build -c Release -o /app/build
FROM build AS publish
RUN dotnet publish -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
# IronPDF requires additional dependencies on Linux
RUN apt-get update && apt-get install -y \
    libgdiplus \
    libc6-dev \
    libx11-dev \
    && rm -rf /var/lib/apt/lists/*     
ENTRYPOINT ["dotnet", "PdfApiService.dll"]
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

欲了解您的 .NET PDF API 的詳細部署指南,請參考:

錯誤處理最佳實踐

為了構建一個更容錯的程序,最佳的做法是實施全局錯誤處理器以獲得一致的錯誤響應,例如:

// Middleware/ErrorHandlingMiddleware.cs
public class ErrorHandlingMiddleware
{
    private readonly RequestDelegate _next;
    public ErrorHandlingMiddleware(RequestDelegate next)
    {
        _next = next;
    }
    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync(context, ex);
        }
    }
    private static async Task HandleExceptionAsync(HttpContext context, Exception ex)
    {
        context.Response.ContentType = "application/json";
        context.Response.StatusCode = 500;
        var response = new
        {
            error = "An error occurred processing your request",
            message = ex.Message
        };
        await context.Response.WriteAsync(JsonSerializer.Serialize(response));
    }
}
// Middleware/ErrorHandlingMiddleware.cs
public class ErrorHandlingMiddleware
{
    private readonly RequestDelegate _next;
    public ErrorHandlingMiddleware(RequestDelegate next)
    {
        _next = next;
    }
    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync(context, ex);
        }
    }
    private static async Task HandleExceptionAsync(HttpContext context, Exception ex)
    {
        context.Response.ContentType = "application/json";
        context.Response.StatusCode = 500;
        var response = new
        {
            error = "An error occurred processing your request",
            message = ex.Message
        };
        await context.Response.WriteAsync(JsonSerializer.Serialize(response));
    }
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

針對特定的 IronPDF 故障排除場景,請參閱 IronPDF 故障排除指南

結論

您現在已使用 ASP.NET Core 和 IronPDF 構建了健壯的 .NET PDF API,可以處理各種文檔生成場景。 這個 REST API 為您的應用程序提供了一個集中化的 PDF 操作的堅實基礎。

關鍵要點:

  • IronPDF 使用其基於 Chrome 的渲染,使 Web API 項目中 PDF 合成變得簡單
  • 您可以輕鬆調整您的 Web API 以使用 IronPDF 的高級編輯工具編輯現有的 PDF 文件
  • RESTful 設計原則確保您的 PDF API 直觀和可維護
  • 適當的錯誤處理和安全措施對於生產環境至關重要
  • 通過異步操作和緩存進行性能優化可提高擴展性
  • 您將擁有桌面和網頁應用程序的支持,提供可擴展的文檔解決方案

IronPDF 允許開發人員創建 PDF 文件、保存 PDF 文件並高效地將 HTML 轉換,使其成為現代 .NET Framework 應用程序必不可少的 PDF 文檔 API。

後續步驟

準備好在您的生產 .NET PDF API 中實施 IronPDF 了嗎? 以下是您的下一步操作:

  1. 開始免費試用 - 在您的開發環境中測試 IronPDF 的完整功能
  2. Explore advanced features - Check out digital signatures, PDF forms, and other advanced PDF features
  3. 自信地擴展 - 查看生產 API 需求的 許可選項

今天就建立您的 .NET PDF API,並通過 IronPDF 在整個應用程序生態系統中簡化文檔生成!

常見問題解答

什麼是 .NET PDF API?

.NET PDF API 是一個函式庫,允許開發人員在 .NET 應用程式中建立、編輯和提取 PDF 內容。它簡化了複雜的 PDF 任務,並確保高效管理 PDF 文件。

.NET PDF API 如何使我的應用程式受益?

.NET PDF API 可以透過提供管理 PDF 文件的一致性、可維護性和可擴展性來增強您的應用程序,例如生成發票、報告、證書或合約。

.NET PDF API 的常見用例有哪些?

.NET PDF API 的常見用例包括產生發票、建立報表、產生憑證以及在桌面和 Web 應用程式中管理合約。

IronPDF 如何簡化 PDF 生成任務?

IronPDF 透過提供強大的庫簡化了 PDF 生成任務,該庫可以輕鬆管理文件內容、PDF 頁面和表單字段,從而更容易維護和擴展應用程式。

IronPDF 能否處理 PDF 表單欄位?

是的,IronPDF 可以有效地管理 PDF 表單字段,允許開發人員在 PDF 文件中建立、填寫表單和提取表單資料。

IronPDF 同時適用於桌面和 Web 應用程式?

當然,IronPDF 的設計宗旨就是在桌面和 Web 應用程式之間無縫協作,為 PDF 管理提供一致且可擴展的解決方案。

為什麼 IronPDF 是 .NET 開發人員的可靠選擇?

IronPDF 易於使用,功能全面,能夠簡化 PDF 任務,從而提高生產力和應用程式效能,因此是 .NET 開發人員的可靠選擇。

IronPDF是否支援PDF擷取功能?

是的,IronPDF 支援 PDF 提取功能,可讓您有效率地從 PDF 文件中提取文字、圖像和其他資料。

IronPDF 如何提升 PDF 管理的擴充性?

IronPDF 透過提供集中式 PDF 生成服務來提高可擴展性,該服務可以處理不斷增長的需求而不會犧牲效能,使其成為不斷增長的應用程式的理想選擇。

IronPDF 為 .NET 應用程式提供哪些支援?

IronPDF 為 .NET 應用程式提供廣泛的支持,包括詳細的文件、範例程式碼和快速回應的支援團隊,以協助開發人員整合 PDF 功能。

IronPDF 是否完全相容於 .NET 10?

是的-IronPDF 與 .NET 10 完全相容。它支援 .NET 10 引入的所有效能、語言和執行時間增強功能,並且可以像在 .NET 6、7、8 和 9 等先前的版本中一樣,在 .NET 10 專案中開箱即用。

Curtis Chau
技術作家

Curtis Chau 擁有卡爾頓大學計算機科學學士學位,專注於前端開發,擅長於 Node.js、TypeScript、JavaScript 和 React。Curtis 熱衷於創建直觀且美觀的用戶界面,喜歡使用現代框架並打造結構良好、視覺吸引人的手冊。

除了開發之外,Curtis 對物聯網 (IoT) 有著濃厚的興趣,探索將硬體和軟體結合的創新方式。在閒暇時間,他喜愛遊戲並構建 Discord 機器人,結合科技與創意的樂趣。