# DocumentService.Client .NET client library for DocumentService API - supports .NET Framework 4.6.2, 4.8, and .NET 8.0. ## Features - **Multi-target support**: .NET Framework 4.6.2, 4.8, and .NET 8.0 - **HttpClientFactory integration**: Proper lifecycle management and connection pooling - **Separate clients per controller**: `IPdfValidationClient`, `IPdfAttachmentClient`, `IPdfOperationsClient`, `ISwissQrCodeClient` - **Dual input support**: Multipart (Stream) and Base64 (byte[]) for all endpoints - **Strongly-typed models**: Shared request/response DTOs with XML documentation ## Installation ```bash dotnet add package DocumentService.Client ``` ## Configuration ### ASP.NET Core / .NET 8.0 ```csharp using DocumentService.Client.Extensions; var builder = WebApplication.CreateBuilder(args); // Register all DocumentService clients builder.Services.AddDocumentServiceClients(options => { options.BaseUrl = "https://documentservice.example.com"; options.Timeout = TimeSpan.FromMinutes(10); options.MaxRetries = 3; options.ThrowOnError = true; }); var app = builder.Build(); ``` ### .NET Framework 4.6.2 / 4.8 ```csharp using DocumentService.Client.Extensions; using Microsoft.Extensions.DependencyInjection; var services = new ServiceCollection(); services.AddDocumentServiceClients(options => { options.BaseUrl = "https://documentservice.example.com"; options.Timeout = TimeSpan.FromMinutes(10); }); var serviceProvider = services.BuildServiceProvider(); ``` ## Usage Examples ### 1. PDF Validation ```csharp using DocumentService.Client.Interfaces; public class PdfService { private readonly IPdfValidationClient _validationClient; public PdfService(IPdfValidationClient validationClient) { _validationClient = validationClient; } public async Task ValidatePdfAsync(Stream pdfStream) { // Option 1: From Stream (multipart) var result = await _validationClient.ValidatePdfAsync(pdfStream); Console.WriteLine($"Pages: {result.PageCount}"); Console.WriteLine($"Version: {result.PdfVersion}"); Console.WriteLine($"Encrypted: {result.IsEncrypted}"); } public async Task ValidatePdfFromBytesAsync(byte[] pdfBytes) { // Option 2: From byte array (Base64 JSON) var result = await _validationClient.ValidatePdfAsync(pdfBytes); Console.WriteLine($"File Size: {result.FileSizeBytes} bytes"); } public async Task ValidatePdfAAsync(string filePath) { using var stream = File.OpenRead(filePath); var result = await _validationClient.ValidatePdfAAsync(stream); Console.WriteLine($"Valid PDF/A: {result.IsValid}"); Console.WriteLine($"PDF/A Version: {result.PdfAVersion}"); if (result.Errors.Any()) { Console.WriteLine("Errors:"); foreach (var error in result.Errors) { Console.WriteLine($" - {error}"); } } } } ``` ### 2. PDF Attachments ```csharp using DocumentService.Client.Interfaces; using DocumentService.Client.Extensions; // For ToBase64StringAsync, ToBytesAsync public class AttachmentService { private readonly IPdfAttachmentClient _attachmentClient; public AttachmentService(IPdfAttachmentClient attachmentClient) { _attachmentClient = attachmentClient; } public async Task CheckAttachmentsAsync(byte[] pdfBytes) { var result = await _attachmentClient.CheckAttachmentsAsync(pdfBytes); Console.WriteLine($"Has Attachments: {result.HasAttachments}"); Console.WriteLine($"Attachment Count: {result.AttachmentCount}"); foreach (var attachment in result.Attachments) { Console.WriteLine($" - {attachment.FileName} ({attachment.Size} bytes)"); } } public async Task ExtractAttachmentsAsync(Stream pdfStream, string outputPath) { // Returns ZIP file as Stream (memory efficient!) using var zipStream = await _attachmentClient.ExtractAttachmentsAsync(pdfStream); // Option 1: Save directly to file using var fileStream = File.Create(outputPath); await zipStream.CopyToAsync(fileStream); Console.WriteLine($"Attachments extracted to: {outputPath}"); } public async Task ExtractAttachmentsToBase64Async(byte[] pdfBytes) { // Returns ZIP as Stream using var zipStream = await _attachmentClient.ExtractAttachmentsAsync(pdfBytes); // Option 2: Convert to Base64 using extension method string base64Zip = await zipStream.ToBase64StringAsync(); Console.WriteLine($"ZIP as Base64: {base64Zip.Substring(0, 50)}..."); } public async Task ExtractAttachmentsToBytesAsync(Stream pdfStream) { // Returns ZIP as Stream using var zipStream = await _attachmentClient.ExtractAttachmentsAsync(pdfStream); // Option 3: Convert to byte array using extension method byte[] zipBytes = await zipStream.ToBytesAsync(); Console.WriteLine($"ZIP size: {zipBytes.Length} bytes"); } } ``` ### 3. PDF Operations (Merge, Annotate, Stamp) ```csharp using DocumentService.Client.Interfaces; using DocumentService.Client.Models.Requests; using DocumentService.Client.Models.ValueObjects; using DocumentService.Client.Extensions; // For Stream extensions public class OperationsService { private readonly IPdfOperationsClient _operationsClient; public OperationsService(IPdfOperationsClient operationsClient) { _operationsClient = operationsClient; } // MERGE public async Task MergePdfsAsync(List pdfPaths) { var streams = pdfPaths.Select(File.OpenRead).ToList(); // Returns merged PDF as Stream var mergedStream = await _operationsClient.MergeAsync( streams, pageRanges: new List { "1-2", null, "3,5" } // Optional ); foreach (var stream in streams) stream.Dispose(); return mergedStream; // Caller responsible for disposing } public async Task MergePdfsToFileAsync(List pdfPaths, string outputPath) { using var mergedStream = await MergePdfsAsync(pdfPaths); // Save to file using var fileStream = File.Create(outputPath); await mergedStream.CopyToAsync(fileStream); } // ANNOTATE public async Task AddHighlightAsync(byte[] pdfBytes) { var request = new AddAnnotationBase64Request { Base64Pdf = Convert.ToBase64String(pdfBytes), AnnotationType = AnnotationType.TextMarkup, PageNumber = 1, X1 = 100, Y1 = 200, Width = 150, Height = 20, Color = "FFFF00", // Yellow TextMarkupStyle = TextMarkupStyle.Highlight, Origin = AnnotationOrigin.TopLeft }; // Returns Stream - convert to bytes using var annotatedStream = await _operationsClient.AnnotateAsync(pdfBytes, request); return await annotatedStream.ToBytesAsync(); } // STAMP public async Task AddStampAsync(Stream pdfStream) { var request = new AddStampBase64Request { Base64Pdf = string.Empty, // Will be filled by client StampType = StampType.Text, X = 300, Y = 50, Text = "CONFIDENTIAL", FontName = "Arial", FontSize = 24, Color = "FF0000", // Red Opacity = 0.5, Rotation = 45, Placement = StampPlacement.Foreground, Origin = AnnotationOrigin.BottomLeft }; // Returns stamped PDF as Stream return await _operationsClient.StampAsync(pdfStream, request); } } ``` ### 4. Swiss QR Code Extraction ```csharp using DocumentService.Client.Interfaces; public class QrCodeService { private readonly ISwissQrCodeClient _qrCodeClient; public QrCodeService(ISwissQrCodeClient qrCodeClient) { _qrCodeClient = qrCodeClient; } public async Task ExtractQrCodeAsync(byte[] pdfBytes) { // Get parsed Bill object var result = await _qrCodeClient.ExtractSwissQrCodeAsync(pdfBytes, raw: false); Console.WriteLine($"Bill: {result.Bill}"); } public async Task ExtractRawQrCodeAsync(Stream pdfStream) { // Get raw QR text lines var result = await _qrCodeClient.ExtractSwissQrCodeAsync(pdfStream, raw: true); Console.WriteLine("Raw QR Lines:"); foreach (var line in result.RawLines) { Console.WriteLine($" {line}"); } } } ``` ## API Endpoints | **Client** | **Method** | **API Endpoint** | **Description** | |---|---|---|---| | **IPdfValidationClient** | `ValidatePdfAsync()` | `POST /api/pdf/validation/validate` | Validates PDF and returns metadata | | **IPdfValidationClient** | `ValidatePdfAAsync()` | `POST /api/pdf/validation/validate-pdfa` | Validates PDF/A conformance | | **IPdfAttachmentClient** | `CheckAttachmentsAsync()` | `POST /api/pdf/attachments/check` | Checks for embedded attachments | | **IPdfAttachmentClient** | `ExtractAttachmentsAsync()` | `POST /api/pdf/attachments/extract` | Extracts attachments as ZIP | | **IPdfOperationsClient** | `MergeAsync()` | `POST /api/pdf/operations/merge` | Merges multiple PDFs | | **IPdfOperationsClient** | `AnnotateAsync()` | `POST /api/pdf/operations/annotate` | Adds annotations (highlight, notes, etc.) | | **IPdfOperationsClient** | `StampAsync()` | `POST /api/pdf/operations/stamp` | Adds text/image stamps | | **ISwissQrCodeClient** | `ExtractSwissQrCodeAsync()` | `POST /api/pdf/qr-code/extract-swiss` | Extracts Swiss QR Code data | ## Error Handling ```csharp try { var result = await validationClient.ValidatePdfAsync(pdfBytes); } catch (HttpRequestException ex) { Console.WriteLine($"HTTP error: {ex.Message}"); } catch (InvalidOperationException ex) { Console.WriteLine($"API returned null: {ex.Message}"); } ``` ## License Copyright © 2026 Digital Data GmbH. All rights reserved.