Preflighting PDF/UA Documents with TX Text Control in .NET C#
Accessibility is an important aspect of document creation. In this article, we will explore how to preflight PDF/UA documents using TX Text Control in .NET C# applications. We will discuss the necessary steps to ensure your documents meet accessibility standards and are usable by everyone, including individuals with disabilities.

Creating a valid PDF/UA document requires more than selecting the correct save option. To ensure accessibility compliance, semantic metadata must be complete before exporting the document. TX Text Control will export a completely valid PDF/UA document with a single line of code when all these requirements are met.
When working with TX Text Control, it is important to ensure that:
- all Form
Fields define meaningful DescriptiveText - all Tables have appropriate DescriptiveText set
- all Images have meaningful DescriptiveText
- the document itself defines a Document
Settings. Document Title
Failing to include any of these will result in a PDF that is technically readable but not PDF/UA-compliant. To ensure a robust, reusable process, we recommend adding a PDF/UA preflight step before saving the document.
Why a PDF/UA preflight matters
In many business applications, documents are no longer created as static files. Instead, they are assembled dynamically from templates, user input, conditional logic, and data from various systems. Form fields can be inserted at runtime, tables can be generated from data sources, and images or frames can be added based on the workflow. In this kind of environment, accessibility metadata is easy to overlook, even when the visual result appears complete.
PDF/UA compliance requires this semantic information to be present and consistent when the document is exported. If required metadata, such as descriptive text or a document title, is missing, the resulting PDF may open correctly and appear fine to sighted users. However, it will fail accessibility validation and cause problems for assistive technologies.
A preflight step makes these requirements explicit and enforceable. Rather than discovering accessibility issues after the PDF has been generated or rejected by a downstream system, validation occurs at a well-defined point in the document lifecycle. This enables applications to prevent invalid exports, direct users to provide missing information, and guarantee that all generated PDFs adhere to the same accessibility standard. In practice, a preflight check transforms PDF/UA compliance from an implicit assumption into a reliable, repeatable process.
TX Text Control provides the ability to verify the validity of a PDF after it has been generated. This can be useful for auditing existing documents or validating third-party PDFs. However, the most effective way to ensure consistent accessibility compliance is to integrate preflight checks directly into the document generation workflow.
Learn More
The new TXTextControl.PDF.Validation NuGet package enables you to validate PDF/UA documents and verify digital signatures directly in your code without relying on third-party tools or external services.
Validate PDF/UA Documents and Verify Electronic Signatures in C# .NET
A unified preflight design
The recommended approach combines two validation styles:
- Report-based validation
Returns a structured list of issues and allows a final "pass or fail" decision. - Event-based validation
Streams issues as they are found, enabling UI feedback, logging, or early aborts.
Both styles are powered by a single validation engine, which ensures consistency and prevents duplicate rules. The report-based approach is ideal for batch processing, automated testing, and scenarios requiring a comprehensive overview of all issues. The event-based approach is better suited to interactive applications, real-time feedback, and situations requiring immediate action upon detecting an issue.
The PDF/UA preflight API
The PDF/UA preflight API is designed to be straightforward and easy to integrate into existing document generation workflows. The implementation consists of:
- PdfUaPreflightRunner
Performs the validation and raises events. - PdfUaPreflightResult
Collects issues and exposesIsValid/ThrowIfInvalid(). - PdfUaIssueFound event
Fired whenever a compliance issue is detected.
Here is the complete implementation:
namespace TXTextControl.PDF
{
public enum PdfUaIssueType
{
MissingDocumentTitle,
MissingDescriptiveText
}
public sealed record PdfUaIssue(
PdfUaIssueType Type,
string ObjectType,
string Message,
object? SourceObject = null
);
public sealed class PdfUaPreflightResult
{
private readonly List<PdfUaIssue> _issues = new();
public IReadOnlyList<PdfUaIssue> Issues => _issues;
public bool IsValid => _issues.Count == 0;
internal void Add(PdfUaIssue issue) => _issues.Add(issue);
public void ThrowIfInvalid()
{
if (IsValid) return;
var text = "PDF/UA preflight failed:" + Environment.NewLine;
foreach (var i in _issues)
text += $"• [{i.ObjectType}] {i.Message}{Environment.NewLine}";
throw new InvalidOperationException(text);
}
}
public sealed class PdfUaIssueFoundEventArgs : EventArgs
{
public PdfUaIssue Issue { get; }
public bool Cancel { get; set; } // handler can abort preflight early
public PdfUaIssueFoundEventArgs(PdfUaIssue issue) => Issue = issue;
}
public sealed class PdfUaPreflightOptions
{
public bool StopOnFirstIssue { get; set; } = false;
public bool CollectIssues { get; set; } = true; // if false, event-only streaming
}
public sealed class PdfUaPreflightRunner
{
public event EventHandler<PdfUaIssueFoundEventArgs>? IssueFound;
public PdfUaPreflightResult Run(ServerTextControl textControl, PdfUaPreflightOptions? options = null)
{
if (textControl == null) throw new ArgumentNullException(nameof(textControl));
options ??= new PdfUaPreflightOptions();
var result = new PdfUaPreflightResult();
static bool Missing(string? s) => string.IsNullOrWhiteSpace(s);
bool Report(PdfUaIssue issue)
{
// 1) Raise event
var args = new PdfUaIssueFoundEventArgs(issue);
IssueFound?.Invoke(this, args);
// 2) Collect into result (optional)
if (options.CollectIssues)
result.Add(issue);
// 3) Stop rules (either by option or handler cancel)
return args.Cancel || options.StopOnFirstIssue;
}
// Document title
if (Missing(textControl.DocumentSettings?.DocumentTitle))
{
if (Report(new PdfUaIssue(
PdfUaIssueType.MissingDocumentTitle,
"Document",
"DocumentTitle is not set.")))
return result;
}
// FormFields
foreach (FormField field in textControl.FormFields)
{
if (Missing(field.DescriptiveText))
{
if (Report(new PdfUaIssue(
PdfUaIssueType.MissingDescriptiveText,
"FormField",
$"DescriptiveText missing (Name: '{field.Name ?? "unnamed"}').",
field)))
return result;
}
}
// Tables
foreach (Table table in textControl.Tables)
{
if (Missing(table.DescriptiveText))
{
if (Report(new PdfUaIssue(
PdfUaIssueType.MissingDescriptiveText,
"Table",
"DescriptiveText missing.",
table)))
return result;
}
}
// Frames
foreach (FrameBase frame in textControl.Frames)
{
if (Missing(frame.DescriptiveText))
{
if (Report(new PdfUaIssue(
PdfUaIssueType.MissingDescriptiveText,
"Frame",
$"DescriptiveText missing (Type: {frame.GetType().Name}).",
frame)))
return result;
}
}
return result;
}
}
public static class PdfUaPreflight
{
// Convenience wrapper for the common "report-only" use case
public static PdfUaPreflightResult Validate(ServerTextControl textControl)
=> new PdfUaPreflightRunner().Run(textControl, new PdfUaPreflightOptions { CollectIssues = true });
}
}
The preflight code explicitly traverses all document elements relevant to PDF/UA accessibility, checking their required metadata before saving the document.
It begins at the document level, verifying that a DocumentTitle is defined. This is mandatory for accessible PDFs and is used by screen readers to identify the document. Then, the code iterates through all interactive elements, such as form field objects, ensuring that each field provides descriptive text so that its purpose can be understood without visual context.
Next, the preflight code loops through all table objects in the document. Tables must expose descriptive text that explains their content or structure, enabling assistive technologies to announce them correctly. The same approach is applied to all frame base objects, including images, shapes, and other embedded content. For these elements, DescriptiveText serves as the equivalent of alternative text.
Each time a required property is missing, the preflight reports an issue through the central reporting mechanism. By systematically walking through the document object model and validating every relevant element, the code ensures that no accessibility-critical component is accidentally skipped when exporting a PDF/UA-compliant document.
Running a simple preflight before saving
For most applications, one validation call is enough. Here is an example of performing a preflight check before exporting a PDF/UA document:
using TXTextControl;
using TXTextControl.PDF;
using (var tc = new ServerTextControl())
{
tc.Create();
tc.Load("sample_valid.tx", StreamType.InternalUnicodeFormat);
PdfUaPreflight.Validate(tc).ThrowIfInvalid();
tc.Save("output.pdf", StreamType.AdobePDF);
}
Saving is blocked with a clear exception message if any required PDF/UA metadata is missing. This ensures that only valid, accessible PDFs are generated.
Streaming issues via events
For interactive applications, providing real-time feedback as issues are detected may be desirable. This can be achieved by subscribing to the IssueFound event.
using TXTextControl;
using TXTextControl.PDF;
using (var tc = new ServerTextControl())
{
tc.Create();
tc.Load("sample_invalid.tx", StreamType.InternalUnicodeFormat);
var runner = new PdfUaPreflightRunner();
runner.IssueFound += (_, e) =>
{
Console.WriteLine(e.Issue.Message);
};
var result = runner.Run(tc);
tc.Save("output.pdf", StreamType.AdobePDF);
}
Each issue is reported immediately along with a reference to the underlying object, such as a form field, table, or frame. This enables applications to highlight problematic UI elements, log issues for auditing purposes, and abort the export process as soon as a critical issue is identified.
DocumentTitle is not set.
DescriptiveText missing (Name: 'test').
DescriptiveText missing (Name: 'check').
DescriptiveText missing.
DescriptiveText missing (Type: Image).
DescriptiveText missing (Type: BarcodeFrame).
Failing fast when needed
In some scenarios, it may be necessary to abort the validation process as soon as the first issue is detected.
using TXTextControl;
using TXTextControl.PDF;
using (var tc = new ServerTextControl())
{
tc.Create();
tc.Load("sample_invalid.tx", StreamType.InternalUnicodeFormat);
var runner = new PdfUaPreflightRunner();
runner.IssueFound += (_, e) =>
{
e.Cancel = true;
};
runner.Run(tc, new PdfUaPreflightOptions
{
StopOnFirstIssue = true
});
tc.Save("output.pdf", StreamType.AdobePDF);
}
This approach minimizes processing time and resource consumption when the presence of issues is all that matters, rather than a complete report. It is useful for automated workflows and scenarios where immediate feedback is critical.
Conclusion
Integrating a PDF/UA preflight step into your document generation workflow is essential for ensuring accessibility compliance. Leveraging TX Text Control's validation capabilities allows developers to create robust applications that consistently produce valid, accessible PDFs. The PDF/UA preflight API provides the tools needed to meet accessibility standards effectively, whether using report-based validation for comprehensive audits or event-based validation for real-time feedback.
ASP.NET
Integrate document processing into your applications to create documents such as PDFs and MS Word documents, including client-side document editing, viewing, and electronic signatures.
- Angular
- Blazor
- React
- JavaScript
- ASP.NET MVC, ASP.NET Core, and WebForms
Related Posts
Text Control Sponsors & Exhibits at NDC London 2026
We are pleased to announce that Text Control will be sponsoring and exhibiting at NDC London 2026, one of Europe's leading conferences for professional software developers, once again. Join us…
Procurement Comparison: TX Text Control .NET Server vs Aspose (Words + PDF)
A detailed cost comparison between TX Text Control .NET Server and Aspose.Words + Aspose.PDF for document generation and processing in .NET applications. Discover the advantages of using TX Text…
The State of Electronic and Digital Signatures (E-Signatures) in Business…
Electronic signatures are no longer just a "nice-to-have" workflow upgrade. By 2025, they had become infrastructure. A critical component of modern business applications. This article explores the…
Looking Ahead: Our Conference Journey in 2026
We just wrapped up our last conference of 2025 in Cologne. While the year has come to a close, we're already looking ahead to what's next. At Text Control, we start planning for the upcoming…
How to Extend the Default Style Mapping when Converting DOCX to Markdown in…
Learn how to customize the default style mapping when converting DOCX documents to Markdown format using Text Control's .NET C# libraries. This article provides step-by-step instructions and code…
