Files

10 KiB

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

dotnet add package DocumentService.Client

Configuration

ASP.NET Core / .NET 8.0

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

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

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

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)

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<Stream> MergePdfsAsync(List<string> pdfPaths)
    {
        var streams = pdfPaths.Select(File.OpenRead).ToList();
        
        // Returns merged PDF as Stream
        var mergedStream = await _operationsClient.MergeAsync(
            streams, 
            pageRanges: new List<string?> { "1-2", null, "3,5" } // Optional
        );
        
        foreach (var stream in streams) stream.Dispose();
        
        return mergedStream; // Caller responsible for disposing
    }

    public async Task MergePdfsToFileAsync(List<string> 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<byte[]> 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<Stream> 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

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

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.