Skip to content

PdfAPI.Core architecture

PdfAPI.Core is the shared contracts-and-primitives layer of the IT.CoreServices.PDFAPI repository: it defines the request, result, document, page-range, and tracking types used by the PdfAPI Web API service, the PdfAPI.SyncFusionCore processor library, and the PdfAPI.Client package, and it ships a small, stateless set of iTextSharp-backed PDF utilities. It sits at depth 1 of the repository's reference graph — depended on by every other project in the repository, while depending on no in-repo project itself.

Responsibilities

  • Define the shared request/result/options/tracking DTOs and enums (PdfRequest, ConvertRequest, MergeRequest, ExtractPagesRequest, PdfOptions, PdfResult, PdfTrackingInfo, PdfTrackingMetadata, DocumentTypes, PdfConversionType, PdfFormat, PdfProcessorType, PdfStatus) that form the wire and in-process vocabulary shared by the API service, the processor library, and the client package.
  • Provide the Document, DocumentRange, DocumentRangeFactory, and PageRange/IPageRange types that model an in-memory-or-on-disk file and the page selections made against it, including page-expression parsing ("1-5,7,9-*,*").
  • Provide PdfClientService, the only behaviour-bearing type in the library: a static, stateless facade over iTextSharp 5.5.11 offering PDF inspection (BR-01, BR-08, BR-09, BR-10), transformation (Flatten, ExtractPages/ExtractPageRanges), and guard operations (ValidatePdf), all executing entirely in the caller's process with no network or database access.
  • Define cache request/result contracts (PdfAPI.Core.Cache.CacheType, PdfCacheRequest, PdfCacheCreationRequest, PdfCacheResult) that describe a cache lookup/write outcome without implementing any cache store.
  • Carry dormant, non-compiled source (PdfAPI.Core.v1.* legacy contracts and PdfAPI.Services.PdfSettings) that ships as source inside consumer NuGet packages but is excluded from the built assembly and unusable by binary consumers.

Component boundaries

  • Contract layer vs. utility layer. Request/result/options/tracking DTOs are near-anemic (properties, constructors, ToString(), and a handful of computed flags); PdfClientService is the sole component that performs behaviour, and it binds only to iTextSharp.
  • No processor engine coupling. PdfProcessorType names Syncfusion, ActivePDF, and iTextSharp as a seam, but PdfAPI.Core itself only implements the iTextSharp path; the Syncfusion and ActivePDF implementations live in PdfAPI.SyncFusionCore and PdfAPI\Services\ActivePdf\, outside this library.
  • No persistence boundary crossed. CacheType.DbTracking, PdfResult.TrackingId, and PdfTrackingInfo describe persistence concepts only; PdfAPI.Core performs no database access — those concepts are honoured by consumers.
  • File-system boundary is crossed directly. Document reads, writes, and deletes files on the local/UNC file system with no abstraction or injection point; Document.Dispose() deletes the backing file, so a using block over a Document is destructive (BR-24).
  • Static-facade boundary. PdfClientService is entirely static, so consumers cannot substitute or mock it; the PdfAPI service wraps it in instance methods with a useClient flag to allow switching to alternative implementations.
  • Compiled vs. dormant source boundary. Six .cs files (Services\PdfSettings.cs and the five v1\*.cs files) are excluded from the <Compile> list in PdfAPI.Core.csproj but are still globbed as source into both shipped NuGet packages; they are unusable by consumers of the compiled PdfAPI.Core.dll.

Interaction model

  • Consumers (PdfAPI service, PdfAPI.Client, PdfAPI.SyncFusionCore) construct a PdfRequest-derived request, optionally build a DocumentRange/PageRange selection over a Document, and call into PdfClientService for inspection, flattening, or extraction.
  • PdfClientService operations guard their input through IsPdf/ValidatePdf before delegating to iTextSharp (PdfReader, PdfStamper, PdfCopy) and return a PdfResult describing the outcome.
  • Document mediates all file-system interaction (Load, Save, Delete) on behalf of both the contract layer and PdfClientService; disposal of a Document, DocumentRange, or PdfResult cascades into file deletion.
  • PdfAPI (PdfAPI\Services\PdfService.cs) delegates HasFormFields, Flatten, IsPdf, Version, GetPageCount, and both ValidatePdf overloads directly to PdfClientService; PdfTrackingService.cs and ActivePdfService.cs construct PdfTrackingMetadata and call PdfClientService.ExtractPageRanges.
  • PdfAPI.Client (PdfAPI.Client\PdfClient.cs) re-exposes PdfClientService.Version, GetPageCount, IsPdf, HasFormFields, Flatten, and ExtractPages as instance methods for remote callers of the packaged client.
  • PdfAPI.SyncFusionCore holds a project reference to PdfAPI.Core (per the repository reference graph) and consumes its contract types independently of PdfClientService.

Architecture diagram

The following diagram shows high-level component interactions, reproduced from the Stage 1 analysis findings.

flowchart LR
  caller["Consumer: PdfAPI service /<br>PdfAPI.Client / PdfAPI.SyncFusionCore"]
  req["PdfRequest / ConvertRequest /<br>MergeRequest / ExtractPagesRequest"]
  dr["DocumentRange + PageRange"]
  doc[Document]
  svc[PdfClientService]
  its[iTextSharp 5.5.11]
  res[PdfResult]
  fs["Local / UNC file system"]

  caller --> req
  req --> dr
  dr --> doc
  doc <--> fs
  caller --> svc
  dr --> svc
  svc --> its
  svc --> res
  res --> caller

Sequence diagram

The following diagram shows the page-extraction sequence (OP-08), the most representative behaviour-bearing operation in the library.

sequenceDiagram
    participant Caller as Consumer (PdfAPI / PdfAPI.Client)
    participant Svc as PdfClientService
    participant Doc as Document
    participant iText as iTextSharp (PdfReader/PdfCopy)
    Caller->>Svc: ExtractPages(DocumentRange)
    Svc->>Svc: IsPdf(documentRange.Document.File)
    Svc->>iText: new PdfReader(sourceBytes)
    Svc->>iText: PdfCopy over MemoryStream, AddDocument per PageRange
    iText-->>Svc: output bytes
    Svc->>Doc: Document.Load(outputBytes, "pdf")
    Doc-->>Svc: new Document (new Guid)
    Svc-->>Caller: PdfResult (Status = Succeeded, PdfProcessorType = iTextSharp)

Design constraints

  • No external network or database calls are made by this library; all behaviour executes in-process against caller-supplied bytes or the local/UNC file system.
  • PdfClientService is a static facade with no dependency-injection seam, constraining consumers that need to mock or substitute PDF processing behaviour.
  • File-system paths passed to Document.Load, Document.Save, and Document.Delete are used without canonicalisation, allow-listing, or traversal checks — path validation is the consumer's responsibility.
  • Disposal semantics are destructive: disposing a Document, DocumentRange, or PdfResult deletes the backing file (BR-24), so ownership and lifetime of the underlying file must be tracked carefully by callers.
  • The compiled assembly excludes the PdfAPI.Core.v1 namespace and PdfAPI.Services.PdfSettings, even though both are shipped as source in the packaged NuGet packages; binary consumers cannot use these types, and the v1\DocumentRangeFactory.cs source file would not currently compile if re-added (it calls a Document.Load overload that no longer exists).
  • The library binds to iTextSharp 5.5.11 only; Syncfusion and ActivePDF processing are implemented by separate projects (PdfAPI.SyncFusionCore, PdfAPI\Services\ActivePdf\) outside this library's boundary.
  • PdfTrackingMetadata.Parse reads capture group names (importType, conversionType) that do not match the regular expression's actual group names (import, type), so round-tripping through Create → Parse always loses imaging intent and conversion type (BR-37) — a known defect in the current contract implementation, not an architectural choice.

Sources

  • PdfAPI.Core\PdfAPI.Core.csproj
  • PdfAPI.Core\Document.cs
  • PdfAPI.Core\Extract\DocumentRange.cs
  • PdfAPI.Core\Extract\PageRange.cs
  • PdfAPI.Core\Services\PdfClientService.cs
  • PdfAPI.Core\PdfRequest.cs
  • PdfAPI.Core\PdfResult.cs
  • PdfAPI.Core\PdfTrackingMetadata.cs
  • PdfAPI.Core\Cache\
  • PdfAPI.Core\v1\*.cs
  • PdfAPI.Core\Services\PdfSettings.cs
  • PdfAPI\Services\PdfService.cs
  • PdfAPI\Services\PdfTrackingService.cs
  • PdfAPI\Services\ActivePdf\ActivePdfService.cs
  • PdfAPI.Client\PdfClient.cs