Guide
How to fill PDF form fields in C#
If the PDF contains an AcroForm, load the file, get the form, and update fields through wrappers such as
TextFormField and ChoiceFormField. If you already know the field names, fetch
them directly instead of iterating through the whole form.
Most of the work is in finding the right field names, handling text and choice fields, and checking what the document supports before you wire it into a service.
Start with direct lookup
If you already know the field names you want, fetch them directly by name and expected type.
using ZingPDF;
using ZingPDF.Elements.Forms.FieldTypes.Choice;
using ZingPDF.Elements.Forms.FieldTypes.Text;
using var pdf = Pdf.Load(File.OpenRead("form.pdf"));
var form = await pdf.GetFormAsync();
if (form is null)
{
return;
}
var nameField = await form.GetFieldAsync("Applicant.Name");
if (nameField is not null)
{
await nameField.SetValueAsync("Taylor Smith");
}
var stateField = await form.GetFieldAsync("Applicant.State");
if (stateField is not null)
{
await stateField.SelectOptionByTextAsync("NSW");
}
await pdf.SaveAsync(File.Create("form-filled.pdf"));
That covers many form-filling cases, especially when the document structure is stable and the field names are already known.
Use direct lookup when the field names are already known
If your mapping already knows that Applicant.Name is a text field and
Applicant.State is a choice field, there is no reason to enumerate every field first.
Use Form.GetFieldAsync(name) for a non-generic lookup, or
Form.GetFieldAsync<TField>(name) when you want the expected field type back directly.
How to discover the fields you actually have
In real PDFs, the hardest part is often not writing values. It is finding the right field names and understanding how the form is structured.
ZingPDF exposes terminal fields through Form.GetFieldsAsync(). Nested names are flattened into
dot-separated paths, so you may see names like Applicant.Address.Suburb rather than simple
single-word identifiers.
var form = await pdf.GetFormAsync();
if (form is null)
{
return;
}
foreach (var field in await form.GetFieldsAsync())
{
Console.WriteLine(field.Name);
}
If you are integrating with a new third-party form, this discovery pass is usually the first thing to do before you build the mapping. Once you know the names, switch over to direct lookup in the real write path.
Text fields and choice fields are the main high-level path
Text fields are the easiest to automate. Once you have a TextFormField, you can read the
current value, set a new one, or clear it.
Choice fields are still simple, but they depend more on the document because you often need to match the available options to values from your own system.
If you already know the option text or export value you want, use
SelectOptionByTextAsync(...) or SelectOptionByValueAsync(...). If you do not,
inspect the option list first and then build your mapping.
Checks before you automate form filling
Before you wire this into a service or import job, it helps to verify a few things against real sample files.
- Confirm the document actually contains an AcroForm.
- Inspect the terminal field names instead of guessing them.
- Check whether your inputs map to text fields, choice fields, or button options.
- Test the output in the PDF viewers your users actually rely on.
- Decide whether you want a normal incremental save or a clean rewrite for downstream distribution.
Those checks save time because form automation problems are often problems with the PDF itself, not with the code that writes values into it.
Flatten the form when you need a non-interactive output
If the file is going out to another system or to end users and it no longer needs to behave like a form, flatten it before you save.
var form = await pdf.GetFormAsync();
if (form is null)
{
return;
}
await form.FlattenAsync();
await pdf.SaveAsync(File.Create("form-flattened.pdf"));
That places the current widget appearances onto the page as normal content and removes the interactive form structure from the saved document.
Current gaps
Two areas still sit outside the current high-level API.
- Push-button action details can be inspected, but action execution is not exposed through the high-level API.
- Signature fields can be inspected, but high-level signing is not implemented.
Test against one of your real forms
Run field discovery against one of your own PDFs, map the fields you care about, and then verify the saved output in the viewers your users use. If the result is meant for distribution rather than further editing, flatten it before you save.