- Add DocumentService.Tests.Live (xUnit live tests, GUID CC5A7D7B) to solution
under the existing Tests solution folder
- Add DocumentService.Tests.NuGet (smoke-test console app, GUID EE3E7C50) to
solution under the Tests solution folder
- Expand GlobalSection(SolutionConfigurationPlatforms) to include x64 and x86
variants for Debug and Release alongside the existing Any CPU entries
- Add corresponding ProjectConfigurationPlatforms entries for all projects
(existing + new) so VS/MSBuild can resolve the correct output paths when
targeting x64/x86 explicitly
End-to-end tests that run against a real, deployed API instance to verify that
all controllers respond correctly over HTTP - bypassing WebApplicationFactory.
Project setup:
- Targets net8.0; xUnit 2.9.3 + FluentAssertions 7.0.0
- References DocumentService.Client, Application and Domain as project refs
- Embeds 4 test PDFs as EmbeddedResources:
valid.pdf, pdfWithSwissQRCode.pdf, pdfWithMoreThanOneAttachment.pdf,
encryptedPdf.pdf
LiveApiTestBase:
- Base URL defaults to http://172.24.12.39:9393, overridable via
LIVE_API_BASE_URL env var
- Constructs typed clients (PdfValidationClient, PdfAttachmentClient,
PdfOperationsClient, SwissQrCodeClient) backed by a single HttpClient
- LoadPdfBytes / LoadPdfStream helpers for EmbeddedResource access
Test coverage per file:
- PdfValidationLiveTests : Stream + byte[] overloads for validate and
validate-pdfa; empty/corrupted inputs assert 4xx/5xx
- PdfAttachmentLiveTests : check + extract endpoints; stream and byte[] variants
- PdfOperationsLiveTests : merge and stamp endpoints
- SwissQrCodeLiveTests : extract Swiss QR bill; invalid content asserts error
Tests are intentionally skipped in CI (no live server); run manually with
the LIVE_API_BASE_URL variable pointing to a running instance.
Standalone console application that references the published DocumentService.Client
NuGet package (v1.2.2) and verifies the full happy-path against a live API instance.
- Targets net8.0; references DocumentService.Client 1.2.2 via NuGet (not project ref)
- Embeds valid.pdf as an EmbeddedResource so no file-system path is required
- Calls Client.Validation.ValidateAsync(Stream) and prints PageCount, PdfVersion,
IsEncrypted, AttachmentCount, FileSizeBytes to stdout
- Handles HttpRequestException and InvalidOperationException with descriptive output
- Intended to run once after a new package is pushed to confirm the .nupkg bundles
Application and Domain DLLs correctly (validates the embedding targets added in
the previous commit)
- Bump Version, AssemblyVersion, FileVersion from 1.2.0 to 1.2.2
- Mark Application and Domain ProjectReferences as PrivateAssets=all so they
are not propagated as transitive dependencies to consumers
- Add IncludeReferencedProjectDlls MSBuild target to pack Application.dll and
Domain.dll into the correct lib/<tfm>/ path inside the .nupkg
- Add CopyProjectReferencesToPackage target (TargetsForTfmSpecificBuildOutput)
as the per-TFM companion needed for multi-targeting builds to pick up both
referenced project DLLs correctly
- Fix stray UTF-8 BOM on the opening Project element
Added a section explaining the limitations of the `ValidatePdfAAsync` method, highlighting that it performs heuristic PDF/A detection rather than full ISO-19005 compliance checks. Listed specific requirements not validated and clarified the meaning of `IsValid = true`. Updated the API endpoint table to reflect the heuristic nature of the `ValidatePdfAAsync()` method.
Updated `DocumentService.Client.csproj` to version 1.2.0, reflecting new features and improvements. Enhanced `README.md` with detailed examples for the new `InspectSwissQrCodeAsync` method, showcasing two approaches (TryExtract and direct null-check) for accessing QR code data. Added PowerShell-specific notes and improved code formatting for better readability. Clarified that `TryExtract` is an optional helper method.
Replaced the fully qualified reference to
`DocumentService.Application.Common.DTOs.PdfValidationResult.IsValid`
with the simpler `PdfValidationResult.IsValid`.
Added a `TryExtract` method to the `SwissQrCodeResult` record to
improve code readability and usability. The method follows the
standard `TryXxx` pattern, allowing for an `if/else` branch
instead of a direct null-check on the `QrCode` property. It
returns `true` if the PDF was valid and a Swiss QR Code was
successfully extracted, and `false` otherwise.
Relocated the `WorkflowsClientExtensions` class from `WorkflowsClient.cs` to `IWorkflowsClient.cs` to improve discoverability by defining it alongside the `IWorkflowsClient` interface.
The `InspectSwissQrCodeAsync` extension method was moved as part of this change. Its functionality remains unchanged, as it still opens a `FileStream` for the provided file path and delegates to the `IWorkflowsClient.InspectSwissQrCodeAsync(Stream, bool, CancellationToken)` method.
Replaced `ExtractSwissQrCodeAsync` with `InspectSwissQrCodeAsync`,
which combines validation and extraction into a single operation.
Updated README examples and code snippets (C#, VB.NET, PowerShell)
to reflect the new method. Removed `throwIfInvalid` parameter and
deprecated the old method with `[Obsolete]` warnings.
Documented the new method's behavior, including always returning
a `SwissQrCodeResult` object and handling invalid documents
gracefully without exceptions. Updated API reference table and
removed outdated error-handling examples. Added a note about the
planned server-side implementation of the new endpoint.
Refactored `ExtractSwissQrCodeAsync` to `InspectSwissQrCodeAsync`, introducing `SwissQrCodeResult` to encapsulate both validation and extraction results. Removed `throwIfInvalid` parameter, ensuring validation details are always returned without exceptions. Added extension methods for file path handling to improve usability.
Updated tests to reflect the new behavior, ensuring extraction is never attempted on invalid documents and validation results are always populated. Simplified API surface by removing redundant overloads and improving stream handling. Enhanced documentation and performed general code cleanup for better maintainability.
Replaced `ExtractAsync` with `ExtractSwissQrCodeAsync` in C#, VB.NET, and PowerShell examples for Swiss QR Code extraction. Updated the `throwIfInvalid` parameter to allow handling invalid PDFs without exceptions.
Revised the API endpoint table in README.md to reflect updated method names (`ExtractSwissQrCodeAsync` replaced with `ExtractAsync` for `Client.Attachment`, `Client.SwissQrCode`, and `Client.Zugferd`). Retained `ExtractSwissQrCodeAsync` for `Client.Workflows`.
These changes improve clarity, consistency, and functionality in the API and documentation.
The NuGet package version for `documentservice.client` has been
updated from `1.0.0` to `1.1.0` in the documentation. Changes
include:
- Updating the **NuGet-Paket** URL under the "Installation" section.
- Updating the PowerShell script example for downloading and
extracting the package.
This ensures users reference the latest version of the package.
Updated the project version from 1.0.0 to 1.1.0 to reflect new changes or improvements. Updated `AssemblyVersion` and `FileVersion` to 1.1.0.0 to maintain consistency with the new project version.
Renamed methods across multiple client classes for consistency,
shortening and aligning naming conventions (e.g., `CheckAttachmentsAsync` → `CheckAsync`, `ValidatePdfAsync` → `ValidateAsync`).
Updated corresponding interfaces, unit tests, and documentation
to reflect the new method names. Standardized method signatures
to support both `Stream` and `byte[]` overloads consistently.
Improved error handling in tests and updated examples in the
README for batch processing and validation scenarios. Enhanced
API endpoint overview for clarity.
Introduced the `Client.Workflows` feature to enable combined
operations with pre-validation. Added the method
`ExtractSwissQrCodeValidatedAsync()` for extracting Swiss QR
Code data with validation in one step.
Updated the README to document the new feature, including
usage examples in C#, VB.NET, and PowerShell, details on the
`throwIfInvalid` parameter, and method signature.
Added the method to the API Endpoints section with a note
about its current `NotImplementedException` status. Clarified
the use of `[Obsolete]` for unimplemented endpoints. Enhanced
the PowerShell note to recommend threading for long-running
operations.
Added `WorkflowsClientTests` to validate the behavior of the
`WorkflowsClient` class, covering PDF validation and Swiss QR
code extraction. Introduced test doubles for `IPdfValidationClient`
and `ISwissQrCodeClient` using `Moq`.
Implemented tests for all overloads of `ExtractSwissQrCodeValidatedAsync`:
- Byte array, stream, and file path inputs.
- Valid, invalid, and empty PDFs.
- Raw mode and cancellation token handling.
- Exception propagation and orchestration contracts.
Ensured comprehensive test coverage for all branches and edge cases.
Introduced a new `WorkflowsClient` to orchestrate multi-step
operations, combining `IPdfValidationClient` and
`ISwissQrCodeClient`. Added methods to validate PDFs and extract
Swiss QR Codes in a single call, with overloads for byte arrays,
streams, and file paths. Registered `WorkflowsClient` as a scoped
service in `ServiceCollectionExtensions`.
Updated `PdfValidationResult` with an `IsValid` property to
simplify PDF validity checks. Added `IWorkflowsClient` interface
to define the contract for the new client, with detailed XML
documentation for its methods.
Enhanced README with German translation and examples.
- Added German translation to README alongside English content.
- Expanded installation, configuration, and usage examples.
- Documented static `Client` entry point and error handling.
- Removed STREAM_API_DESIGN.md as it is no longer relevant.
- Changed solution configuration to build in Release mode by default.
Updated versioning details in the `.csproj` file:
- Incremented `Version` to 1.1.0.
- Updated `FileVersion`, `AssemblyVersion`, and `InformationalVersion` to reflect the new version.
This update likely includes new features or enhancements while maintaining backward compatibility.
Consolidated DTOs under `DocumentService.Application.Common.DTOs.Requests`
to centralize and align them with the application layer. Introduced
`PdfBase64RequestBase` to encapsulate shared properties, reducing
redundancy across request DTOs. Updated controllers, clients, and tests
to use the new DTO structure. Removed redundant DTOs and cleaned up
unused namespaces and comments. Improved documentation and ensured
consistent naming conventions across the codebase.
The `AddAttachmentsRequest` record has been removed. This record was previously used as a request DTO for adding attachments to a Base64-encoded PDF. It included a `Base64Pdf` property for the PDF document and an `Attachments` property for the list of attachments to embed.
The `ExtractPdfAttachmentsRequest` and `AttachmentRequestDto` records remain unchanged.
Refactored the codebase to use shared DTOs from `DocumentService.Application.Common.DTOs`, removing inline DTO definitions in client interfaces and tests. Introduced conditional compilation to handle framework-specific differences in DTOs and handlers.
Updated test cases to align with the new DTO structures, including `SwissQrCodeExtractionResult`, `PdfValidationResult`, and `ZugferdExtractionResult`. Adjusted test data to match updated DTO properties.
Cleaned up solution and project files, ensuring proper references and organization. Removed unused files and fixed project references in `DocumentService.Tests.csproj`. Improved maintainability and consistency across the codebase.
Enabled multi-targeting in `DocumentService.Application` to support `net462`, `net480`, and `net8.0`. Updated dependencies with framework-specific versions and added conditional configurations for compatibility.
Refactored `DocumentService.Client` by removing redundant enums and unused code. Adjusted namespaces and project references to streamline the codebase and improve maintainability.
These changes modernize the project, enhance compatibility, and align with modular design principles.
Updated the project to target multiple frameworks (`net462`,
`net480`, and `net8.0`) by replacing `<TargetFramework>` with
`<TargetFrameworks>`. Added `<LangVersion>` property set to
`latest` to enable the use of the latest C# language features.
Adjusted `<Nullable>` property formatting for consistency.
Updated project and solution files to rename and restructure
`DocumentOperator` to `DocumentService`. Modified project
references in `DocumentService.API.csproj`, `DocumentService.Application.csproj`,
and `DocumentService.Infrastructure.csproj` to reflect the new
naming convention. Updated `DocumentService.sln` to remove
old project references, add new ones, and adjust configuration
and nested project mappings accordingly. This change aligns
the project structure with the new naming convention.
Minimal hand-crafted PDF containing a Standard encryption dictionary
referenced from the trailer (/Encrypt 4 0 R). Used by DetectEncryption
unit tests to verify byte-level encryption detection.
Registered as EmbeddedResource in DocumentService.Tests.csproj.
Old implementation used Encoding.ASCII.GetString() which:
- Corrupts binary PDF bytes 0x80-0xFF -> '?' (false negatives)
- Matches '/Encrypt' anywhere in document content (false positives)
- Matches '/Encrypted', '/EncryptionKey' etc. (token boundary not checked)
New implementation uses ReadOnlySpan<byte> with three strategies:
1. Search last 2KB (trailer region) - fast path, covers standard PDFs
2. Search first 2KB (linearized PDFs have duplicate trailer at start)
3. Full-file fallback for PDF 1.5+ compressed xref streams, with token
boundary check (next byte must be space/newline/tab/'<'/'/'/'[')
to avoid matching '/Encrypted' or '/EncryptionKey'
Also: DevExpressPdfProcessor.ValidateAsync now returns PdfValidationResult
directly (no more PdfMetadata wrapper), includes IsEncrypted field.
Introduced multiple interfaces and DTOs to support a wide range of
PDF-related operations, including attachment handling, conversion,
validation, annotation, stamping, and metadata extraction.
Key changes:
- Added `DocumentServiceClientOptions` for HTTP client config.
- Introduced `IPdfAttachmentClient` for attachment operations.
- Added `IPdfConversionClient` for PDF/A conversion (marked obsolete).
- Added `IPdfOperationsClient` for merge, annotate, and stamp ops.
- Introduced `IPdfValidationClient` for PDF and PDF/A validation.
- Added `ISwissQrCodeClient` for Swiss QR Code extraction.
- Added `IZugferdClient` for ZUGFeRD detection and extraction.
- Created request DTOs for Base64-encoded operations.
- Added enums for annotation, stamp, and validation configurations.
These changes provide a flexible and extensible foundation for
interacting with PDF documents, supporting both multipart and
Base64-encoded inputs, and ensuring type safety with enums and records.
Introduced a new `DocumentService.Client` project targeting `net462`, `net480`, and `net8.0`. The project includes metadata for NuGet packaging, such as `PackageId`, `Authors`, and `Company`, and references `Microsoft.Extensions.DependencyInjection` and `Microsoft.Extensions.Logging`.
Updated `DocumentService.sln` to include the new project, its build configurations, and solution folder associations.
Added `icon.png` as the NuGet package icon and included it in the project file.
The `DocumentOperator.sln` file was completely removed, along with all associated projects (`DocumentService.API`, `DocumentService.Application`, `DocumentService.Infrastructure`, `DocumentService.Domain`, `DocumentService.Tests`) and solution folders (`Solution Items`, `fake-pfd`, `core`, `presentation`, `infrastructure`, `src`, `tests`).
Markdown files (`AGENTS.md`, `CONTROLLER_ENDPOINTS.md`, `REQUIRED_FEATURES.md`) and PDF files (`form.pdf`, `multi-page.pdf`, `one-page.pdf`, `with-image.pdf`) were also deleted.
Solution configurations, platform settings, project nesting, and the `SolutionGuid` were removed, indicating the solution is no longer part of the codebase. This change may be part of a restructuring, migration, or deprecation effort.
This commit implements a complete rebranding of the project:
- Updated all namespaces from `DocumentOperator` to `DocumentService`.
- Renamed file paths, embedded resources, and test data references.
- Updated configuration keys, logging paths, and Redis instance names.
- Revised documentation to reflect the new project name.
- Modified project and solution files to align with the new structure.
- Updated class names, DTOs, commands, queries, and handlers.
- Adjusted middleware, controllers, and API endpoints.
- Updated Swagger metadata and API titles to `DocumentService API`.
- Refactored test namespaces, resource paths, and embedded resources.
- Updated build and deployment configurations for the new name.
- Replaced all references to `DocumentOperator` in comments and literals.
These changes ensure consistency across the codebase and documentation.
Renamed and restructured project references across the solution
to replace `DocumentOperator` projects with `DocumentService`
projects. Updated all `.csproj` files to reflect the new project
names and references.
Modified the solution file (`DocumentOperator.sln`) to remove
`DocumentOperator` projects and add corresponding `DocumentService`
projects, including `DocumentService.API`, `DocumentService.Application`,
`DocumentService.Infrastructure`, `DocumentService.Domain`, and
`DocumentService.Tests`.
This change aligns the project structure with the new naming
convention or organizational standards.
Added the following projects to `DocumentOperator.sln`:
- `core`, `presentation`, `infrastructure`, `src`, `tests`
Updated `GlobalSection(NestedProjects)` to define hierarchical
relationships between projects for better organization. Nested
projects include `core`, `presentation`, and `infrastructure`
under `src`, among others.
Introduced endpoints for embedding attachments in PDFs and converting
between standard PDFs and PDF/A formats. Added `PdfAttachmentController`
and `PdfConversionController` with multipart/form-data and Base64-based
support. Implemented commands, handlers, and validators for these
operations.
Extended `IPdfProcessor` with methods for adding attachments and
PDF/A conversion. Partially implemented functionality in
`DevExpressPdfProcessor`, including `ConvertFromPdfAAsync`.
Added `attachment.xml` and `withoutAttachment.pdf` as resources for
testing. Marked endpoints as `[Obsolete]` to indicate incomplete
implementation. Improved validation and error handling for commands.
Enhanced `ExtractZugferdFromFile` and `ExtractZugferdFromBase64`
methods to support output as an XML file (`application/xml`)
or JSON (default). Introduced `asFile` and `format` query
parameters to control the output format. Updated XML
documentation and `ProducesResponseType` attributes to reflect
these changes. Default values for `CancellationToken` were
set to `default` for improved usability.