Annotations and Forms

Annotations and Forms

Aspose.PDF FOSS for .NET gives you full read/write access to PDF annotations and interactive AcroForm fields. The primary entry point for annotations is Page.Annotations (an AnnotationCollection), while form fields are accessed through Document.Form. Both subsystems work entirely in-memory and require no license key.


Adding annotations

AnnotationCollection exposes typed helper methods for every standard annotation kind. Each method accepts a Rectangle defining the annotation position on the page plus type-specific parameters.

using var doc = Document.Open(pdfBytes);
var page = doc.Pages[1];

// Text (sticky-note) annotation
page.Annotations.AddTextAnnotation(
    new Rectangle(72, 720, 200, 740),
    contents: "Review this paragraph",
    title: "Editor",
    open: true);

// Highlight annotation
page.Annotations.AddHighlightAnnotation(
    new Rectangle(72, 680, 300, 700),
    quadPoints: null,
    color: new double[] { 1, 1, 0 });

// Free-text annotation (rendered directly on the page)
page.Annotations.AddFreeTextAnnotation(
    new Rectangle(72, 640, 350, 660),
    contents: "Inline note",
    fontName: "Helvetica",
    fontSize: 10,
    color: new double[] { 0, 0, 0 });

using var ms = new MemoryStream();
doc.Save(ms);

Link annotations and actions

Links combine a clickable rectangle with a PdfAction. The library supports URI, GoTo, JavaScript, Named, and Launch actions.

using var doc = Document.Open(pdfBytes);
var page = doc.Pages[1];

// URI link
var uriAction = PdfAction.CreateUri("https://aspose.com");
page.Annotations.AddLinkAnnotation(
    new Rectangle(50, 700, 200, 720), uriAction);

// GoTo link (jump to page 3)
page.Annotations.AddLinkAnnotation(
    new Rectangle(50, 660, 200, 680),
    destinationPage: 3,
    destRect: new Rectangle(0, 0, 612, 792));

// JavaScript link
var jsAction = PdfAction.CreateJavaScript("app.alert('Hello');");
page.Annotations.AddLinkAnnotation(
    new Rectangle(50, 620, 200, 640), jsAction);

doc.Save("links.pdf");

To read a link back after opening a saved PDF, cast the annotation to LinkAnnotation and inspect its Uri property or resolve the action dictionary via PdfAction.Create.


Markup and shape annotations

Markup annotations (highlight, underline, strikeout) mark existing text. Shape annotations (square, circle, line, ink) draw geometry on the page.

var page = doc.Pages[1];

// Underline
page.Annotations.AddUnderlineAnnotation(
    new Rectangle(72, 600, 300, 620),
    quadPoints: null,
    color: new double[] { 1, 0, 0 });

// Square
page.Annotations.AddSquareAnnotation(
    new Rectangle(72, 540, 200, 580),
    borderColor: new double[] { 0, 0, 1 },
    fillColor: null,
    lineWidth: 1.5);

// Line
page.Annotations.AddLineAnnotation(
    new Rectangle(72, 500, 300, 520),
    x1: 72, y1: 510, x2: 300, y2: 510,
    color: new double[] { 0, 0.5, 0 },
    lineWidth: 2);

// Ink (freehand)
page.Annotations.AddInkAnnotation(
    new Rectangle(72, 440, 200, 480),
    inkPaths: new[] { new double[] { 80, 450, 120, 470, 160, 450 } },
    color: new double[] { 0.5, 0, 0.5 },
    lineWidth: 1);

Stamp annotations

Stamp annotations overlay an image or predefined icon on a page.

var stamp = new StampAnnotation(doc);
// Configure stamp properties, then add to page
page.Annotations.Add(stamp);

Flattening annotations

Call Flatten() on any annotation to burn its visual appearance into the page content stream and remove it from the interactive annotation list.

foreach (var annot in doc.Pages[1].Annotations)
{
    annot.Flatten();
}

The visitor pattern with AnnotationSelector

AnnotationSelector implements the visitor pattern so you can filter annotations by type without manual casting.

var selector = new AnnotationSelector();
doc.Pages[1].Accept(selector);

// selector.Selected now contains all annotations on page 1
foreach (var annot in selector.Selected)
{
    // Process each annotation by type
}

Pass a typed annotation instance to the constructor to filter for that type only:

var linkFilter = new AnnotationSelector(new LinkAnnotation(page, Rectangle.Empty));
page.Accept(linkFilter);
// linkFilter.Selected contains only LinkAnnotation instances

Interactive form fields

Access AcroForm fields through Document.Form. The Form class exposes field-level read/write operations and supports JSON export.

using var doc = Document.Open(pdfBytes);

// Enumerate all fields
foreach (var field in doc.Form.Fields)
{
    Console.WriteLine($"{field.FullName}: {field.Value}");
}

Field subclasses include TextBoxField, CheckboxField, RadioButtonField, ComboBoxField, ListBoxField, ChoiceField, and SignatureField.


Exporting form data to JSON

WidgetAnnotation provides ExportToJson overloads for serializing field data to a stream or file path. An optional ExportFieldsToJsonOptions parameter controls output formatting.

using var doc = Document.Open(pdfBytes);
var widget = (WidgetAnnotation)doc.Pages[1].Annotations[1];

using var jsonStream = new MemoryStream();
widget.ExportToJson(jsonStream);

Tips and Best Practices

  • Always specify explicit Rectangle coordinates in PDF user-space units (1/72 inch).
  • Use AddLinkAnnotation with a PdfAction for maximum flexibility — URI, GoTo, JavaScript, and Named actions are all supported.
  • Call Flatten() before distributing a PDF if you want annotations to appear in non-interactive viewers.
  • Access form fields via Document.Form.Fields rather than iterating page annotations — the form collection handles cross-page field grouping.
  • Save and reopen the document to verify annotation round-trip fidelity, especially for custom actions.

Common Issues

IssueCauseFix
Annotation not visible after saveRectangle has zero area or is outside page boundsVerify coordinates fall within the page MediaBox
LinkAnnotation.Uri returns nullLink uses a GoTo or JavaScript action, not a URI actionResolve the action dictionary via PdfAction.Create and check ActionType
Form field value is empty stringField exists but has no /V entryCheck field.Value is not null before processing
Flatten() throwsAnnotation has no /P (page) referenceEnsure the annotation was added through Page.Annotations

FAQ

How do I add a hyperlink to a PDF page?

Use page.Annotations.AddLinkAnnotation(rect, PdfAction.CreateUri(url)) to create a clickable URI link at the specified rectangle.

Can I read form field values from an existing PDF?

Yes. Open the document with Document.Open, then iterate Document.Form.Fields and read the Value property on each Field.

What annotation types does the library support?

The library supports text, free-text, link, highlight, underline, strikeout, square, circle, line, ink, stamp, caret, file-attachment, sound, polygon, polyline, widget, watermark, and 3D annotations. All types are available through AnnotationCollection helper methods or direct construction.

How do I filter annotations by type?

Use AnnotationSelector with a typed template annotation. Call page.Accept(selector) and inspect selector.Selected for matching annotations.

Can I flatten only specific annotations?

Yes. Call Flatten() on individual Annotation instances rather than iterating the entire collection.


API Reference Summary

Class / MethodDescription
AnnotationCollectionTyped collection on each Page; provides Add* helpers for all annotation types
AnnotationCollection.AddTextAnnotationAdd a sticky-note annotation
AnnotationCollection.AddLinkAnnotationAdd a link with URI, page destination, or custom action
AnnotationCollection.AddHighlightAnnotationAdd a text-highlight annotation
AnnotationCollection.AddInkAnnotationAdd a freehand-drawing annotation
AnnotationCollection.AddSquareAnnotationAdd a rectangle shape annotation
AnnotationCollection.AddCircleAnnotationAdd an ellipse shape annotation
AnnotationCollection.AddLineAnnotationAdd a line annotation
Annotation.FlattenBurn annotation appearance into page content
Annotation.AcceptDispatch to typed AnnotationSelector.Visit overload
AnnotationSelectorVisitor that collects annotations by type
LinkAnnotationAnnotation subclass carrying a URI or action
TextAnnotationSticky-note annotation
InkAnnotationFreehand-drawing annotation with stroke paths
StampAnnotationImage or icon overlay annotation
WidgetAnnotation.ExportToJsonSerialize form-field data to JSON
FormAcroForm facade; enumerates and manipulates fields
FieldBase class for form fields (TextBoxField, CheckboxField, etc.)
CheckboxFieldCheck-box form field
TextBoxFieldSingle/multi-line text input field
ComboBoxFieldDrop-down choice field
RadioButtonFieldRadio-button group field
AnnotationTypeEnumeration of annotation kinds
PdfAction.CreateUriFactory for URI link actions
PdfAction.CreateJavaScriptFactory for JavaScript actions

See Also

 English