ZingPDF logo

Guide

How to create and edit PDFs with the fluent API in C#

Use Pdf.New() to author a new document and pdf.Pages(...) to edit an existing one with the same page-level fluent builders for text, shapes, images, and watermarks.

Which API should you use?

Use Pdf.New() when you are authoring a new document from scratch and want the page content to read top to bottom. Use pdf.Pages(...) when you want the same fluent page operations on a loaded or already-created PDF. Use the standard API when you need to work directly with Pdf.Create(...), GetPageAsync(...), and AddTextAsync(...).

Start with Pdf.New()

Pdf.New() creates a fluent builder. Add one or more pages, configure the page content, then save the result.

await Pdf.New()
    .Page(page => page
        .Size(595, 842)
        .Text(text => text
            .Value("Monthly delivery report")
            .HelveticaBold()
            .FontSize(24)
            .At(48, 780)))
    .SaveToFileAsync("report.pdf");

Edit an existing PDF with pdf.Pages(...)

pdf.Pages(...) applies fluent page mutations to an existing document. You can select a page, insert one, append one, or remove one, then save through the same fluent chain.

Standard API

using var pdf = Pdf.Load(File.OpenRead("input.pdf"));

var firstPage = await pdf.GetPageAsync(1);
var font = await pdf.RegisterStandardFontAsync(StandardPdfFonts.HelveticaBold);

await firstPage.AddTextAsync(
    "Approved",
    Rectangle.FromCoordinates(
        new Coordinate(48, 780),
        new Coordinate(168, 804)),
    font,
    18,
    RGBColour.Black);

await pdf.AppendPageAsync(options =>
{
    options.MediaBox = Rectangle.FromDimensions(595, 842);
});

var summaryPage = await pdf.GetPageAsync(2);
await summaryPage.AddTextAsync(
    "Summary",
    Rectangle.FromCoordinates(
        new Coordinate(48, 780),
        new Coordinate(220, 808)),
    font,
    24,
    RGBColour.Black);

await pdf.SaveAsync(File.Create("edited.pdf"));

Fluent API

using var pdf = Pdf.Load(File.OpenRead("input.pdf"));

await pdf.Pages(pages => pages
        .Page(1, page => page
            .Text(text => text
                .Value("Approved")
                .HelveticaBold()
                .FontSize(18)
                .At(48, 780)))
        .Append(page => page
            .Size(595, 842)
            .Text(text => text
                .Value("Summary")
                .HelveticaBold()
                .FontSize(24)
                .At(48, 780))))
    .SaveAsync(File.Create("edited.pdf"));

Use Remove(...) or Delete(...) when you want to drop existing pages from the document.

Add text, shapes, and layout boxes

The fluent page builder covers the same authored page primitives as the core page API: text, rectangles, lines, paths, images, and watermarks.

Standard API

using var pdf = Pdf.Create();
var page = await pdf.GetPageAsync(1);
var font = await pdf.RegisterStandardFontAsync(StandardPdfFonts.HelveticaBold);

await page.AddPathAsync(new Path(
    new StrokeOptions(RGBColour.PrimaryBlue, 1),
    new FillOptions(new RGBColour(0.9, 0.97, 1)),
    PathType.Linear,
    [
        new Coordinate(48, 700),
        new Coordinate(268, 700),
        new Coordinate(268, 752),
        new Coordinate(48, 752),
        new Coordinate(48, 700)
    ]));

await page.AddTextAsync(
    "Northwind ERP Modernisation",
    Rectangle.FromCoordinates(
        new Coordinate(48, 780),
        new Coordinate(288, 804)),
    font,
    24,
    RGBColour.Black);

Fluent API

await Pdf.New()
    .Page(page => page
        .Size(595, 842)
        .Rectangle(box => box
            .At(48, 700)
            .Size(220, 52)
            .Stroke(RGBColour.PrimaryBlue, 1)
            .Fill(new RGBColour(0.9, 0.97, 1)))
        .Text(text => text
            .Value("Northwind ERP Modernisation")
            .HelveticaBold()
            .FontSize(24)
            .At(48, 780))
        .Text(text => text
            .Value("Generated with Pdf.New()")
            .Helvetica()
            .FontSize(11)
            .InBox(60, 714, 196, 20)
            .AlignStart()
            .AlignMiddle()
            .Padding(0)))
    .SaveToFileAsync("report.pdf");

Wrap text inside a bounded box

Use InBox(...) when text should stay inside a rectangle. Add Wrap() for multiline content, or ShrinkToFit(...) when it should remain a single line and reduce size as needed.

Standard API

var font = await pdf.RegisterStandardFontAsync(StandardPdfFonts.Helvetica);

await page.AddTextAsync(
    "Run the warehouse pilot readiness review and confirm rollout communications with business leads.",
    Rectangle.FromCoordinates(
        new Coordinate(378, 500),
        new Coordinate(519, 528)),
    font,
    10,
    RGBColour.Black,
    new TextLayoutOptions
    {
        Wrap = true,
        Overflow = TextOverflowMode.Clip,
        HorizontalAlignment = TextHorizontalAlignment.Start,
        VerticalAlignment = TextVerticalAlignment.Top,
        Padding = TextPadding.None
    });

Fluent API

page.Text(text => text
    .Value("Run the warehouse pilot readiness review and confirm rollout communications with business leads.")
    .Helvetica()
    .FontSize(10)
    .InBox(378, 500, 141, 28)
    .AlignStart()
    .AlignTop()
    .Padding(0)
    .Wrap()
    .ClipOverflow());

Choose fonts

You can use the built-in standard font helpers, register a TrueType font, or plug in ZingPDF.GoogleFonts through the same text builder.

Standard API

var headingFont = await pdf.RegisterStandardFontAsync(StandardPdfFonts.TimesBold);
var brandFont = await pdf.RegisterTrueTypeFontAsync("MyFont-Regular.ttf", fontName: "MyFont-Regular");

await page.AddTextAsync(
    "Executive summary",
    Rectangle.FromCoordinates(
        new Coordinate(48, 320),
        new Coordinate(248, 340)),
    headingFont,
    14,
    RGBColour.Black);

await page.AddTextAsync(
    "Brand heading",
    Rectangle.FromCoordinates(
        new Coordinate(48, 280),
        new Coordinate(248, 304)),
    brandFont,
    20,
    RGBColour.Black);

Fluent API

page.Text(text => text
    .Value("Executive summary")
    .TimesBold()
    .FontSize(14)
    .At(48, 320));

page.Text(text => text
    .Value("Brand heading")
    .WithTrueTypeFont("MyFont-Regular.ttf", fontName: "MyFont-Regular")
    .FontSize(20)
    .At(48, 280));

Build multi-page output

Add more pages by calling Page(...) again. Each callback receives a fresh page builder.

Standard API

using var pdf = Pdf.Create(options =>
{
    options.MediaBox = Rectangle.FromDimensions(595, 842);
});

var firstPage = await pdf.GetPageAsync(1);
var secondPage = await pdf.AppendPageAsync(options =>
{
    options.MediaBox = Rectangle.FromDimensions(595, 842);
});

Fluent API

await Pdf.New()
    .Page(page => page
        .Size(595, 842)
        .Text(text => text.Value("Page 1").HelveticaBold().FontSize(18).At(48, 780)))
    .Page(page => page
        .Size(595, 842)
        .Text(text => text.Value("Page 2").HelveticaBold().FontSize(18).At(48, 780)))
    .SaveToFileAsync("two-pages.pdf");

Runnable examples

The examples folder includes a minimal starter, an existing-PDF editing example, and a larger report layout built with the fluent API.