Secure Exchanges SDK Documentation
Search Results for

    Show / Hide Table of Contents

    Signature Zones

    This guide details the creation of signature zones on PDF documents.

    The ZoneBuilder Class

    The ZoneBuilder class is the recommended approach for creating signature zones. It opens the PDF document once and caches page dimensions for optimal performance.

    using (var zoneBuilder = new ZoneBuilder("document.pdf", isPki: false))
    {
        var signZone = zoneBuilder.CreateFieldSignZone(1, "signature1", 10, 300, 100, 40);
        var textZone = zoneBuilder.CreateFieldTextZone(1, "text1", 10, 400, 200, 30);
        var dateZone = zoneBuilder.CreateFieldDateSignZone(2, "date1", 10, 500, 100, 25);
    }
    

    Properties

    Property Type Description
    PageCount int Total number of pages in the PDF document
    FilePath string PDF file path
    IsPki bool Indicates whether PKI mode is enabled (allows TextArea, OptionList, Dropdown)

    Constructor

    public ZoneBuilder(string filePath, bool isPki)
    
    Parameter Type Description
    filePath string Path to the PDF file
    isPki bool Enables PKI mode for advanced zone types

    Common Parameters

    All CreateField*Zone methods share these parameters:

    Parameter Type Description
    page int Page number (1 = first page)
    fieldName string Unique field identifier
    x float Horizontal position (from left)
    y float Vertical position (from top)
    width float Field width
    height float Field height
    Note

    Standard Letter page dimensions are 612 x 792 points (72 DPI). Use GetPageDimensions(page) to get the exact dimensions of a page.

    Getting Page Dimensions

    using (var zoneBuilder = new ZoneBuilder(filePath, isPki: false))
    {
        var (pageWidth, pageHeight) = zoneBuilder.GetPageDimensions(1);
        Console.WriteLine($"Page 1: {pageWidth} x {pageHeight} points");
    }
    

    Zone Types

    Signature Zone

    using (var zoneBuilder = new ZoneBuilder(filePath, isPki: false))
    {
        var signZone = zoneBuilder.CreateFieldSignZone(
            page: 1,
            fieldName: "client_signature",
            x: 100, y: 650,
            width: 200, height: 50
        );
    }
    

    Initials Zone

    var initialsZone = zoneBuilder.CreateFieldInitialZone(
        page: 1,
        fieldName: "client_initials",
        x: 500, y: 700,
        width: 60, height: 30
    );
    

    Text Zone

    var textZone = zoneBuilder.CreateFieldTextZone(
        page: 1,
        fieldName: "full_name",
        x: 100, y: 600,
        width: 200, height: 25,
        defaultValue: "",      // Default value
        fontSize: 12,
        required: true         // Required field
    );
    

    Number Zone

    var numberZone = zoneBuilder.CreateFieldNumberZone(
        page: 1,
        fieldName: "amount",
        x: 100, y: 550,
        width: 100, height: 25,
        defaultValue: 0,
        fontSize: 12,
        required: true
    );
    

    Date Zone (Auto-filled on Signature)

    This zone is automatically filled with the signature date.

    var dateSignZone = zoneBuilder.CreateFieldDateSignZone(
        page: 1,
        fieldName: "signature_date",
        x: 100, y: 500,
        width: 100, height: 25,
        fontSize: 12
    );
    

    Date Zone (Picker)

    Allows the signer to choose a date via a picker.

    var dateZone = zoneBuilder.CreateFieldDateZone(
        page: 1,
        fieldName: "contract_date",
        x: 100, y: 450,
        width: 100, height: 25,
        fontSize: 12,
        required: true
    );
    

    Checkbox

    var checkbox = zoneBuilder.CreateFieldCheckBoxZone(
        page: 1,
        fieldName: "accept_terms",
        x: 100, y: 400,
        isChecked: false,       // Default checked state
        required: true,         // Required
        requiredFocus: false    // Must receive focus before submission
    );
    
    Note

    Checkbox dimensions are fixed (10x10 points). If required is true, the checkbox cannot be pre-checked (isChecked will be ignored).

    Radio Button

    Radio buttons are grouped by groupId. Only one button can be selected per group.

    // Radio button group
    var radio1 = zoneBuilder.CreateFieldRadioZone(
        page: 1,
        fieldName: "Option A",        // Value of this option
        x: 100, y: 350,
        groupId: "option_choice",     // Group identifier
        isSelected: true              // Default selected option
    );
    
    var radio2 = zoneBuilder.CreateFieldRadioZone(
        page: 1,
        fieldName: "Option B",        // Value of this option
        x: 130, y: 350,
        groupId: "option_choice",     // Same group
        isSelected: false
    );
    
    Note

    Radio button dimensions are fixed (10x10 points).

    PKI-Only Zone Types

    The following zone types require isPki: true when initializing the ZoneBuilder.

    Multiline Text Zone (TextArea)

    using (var zoneBuilder = new ZoneBuilder(filePath, isPki: true))
    {
        var textAreaZone = zoneBuilder.CreateFieldTextAreaZone(
            page: 1,
            fieldName: "description",
            x: 100, y: 300,
            width: 300, height: 100,
            defaultValue: "Enter your description here...",
            fontSize: 12,
            required: false
        );
    }
    

    Option List (Multiple Selection)

    var optionListZone = zoneBuilder.CreateFieldOptionListZone(
        page: 1,
        fieldName: "services",
        x: 100, y: 150,
        width: 200, height: 80,
        options: new[] { "Service A", "Service B", "Service C", "Service D" },
        selectedValues: new[] { "Service A", "Service C" },  // Pre-selected values (optional)
        multiSelect: true,
        required: false
    );
    

    For single selection:

    var singleSelectZone = zoneBuilder.CreateFieldOptionListZone(
        page: 1,
        fieldName: "country",
        x: 100, y: 250,
        width: 150, height: 25,
        options: new[] { "Canada", "United States", "France", "Belgium" },
        selectedValues: new[] { "Canada" },
        multiSelect: false,
        required: true
    );
    

    Dropdown

    var dropdownZone = zoneBuilder.CreateFieldDropdownZone(
        page: 1,
        fieldName: "province",
        x: 100, y: 200,
        width: 150, height: 25,
        options: new[] { "Quebec", "Ontario", "Alberta", "British Columbia" },
        selectedValue: "Quebec",    // Pre-selected value (optional)
        fontSize: 12,
        required: true
    );
    

    Complete Example: Contract Form

    public SignZoneDetails[] CreateContractFormZones(string filePath)
    {
        var zones = new List<SignZoneDetails>();
    
        using (var zoneBuilder = new ZoneBuilder(filePath, isPki: false))
        {
            // Client information
            zones.Add(zoneBuilder.CreateFieldTextZone(1, "last_name", 150, 700, 200, 25, "", 12, true));
            zones.Add(zoneBuilder.CreateFieldTextZone(1, "first_name", 150, 670, 200, 25, "", 12, true));
            zones.Add(zoneBuilder.CreateFieldTextZone(1, "email", 150, 640, 250, 25, "", 12, true));
    
            // Amount
            zones.Add(zoneBuilder.CreateFieldNumberZone(1, "amount", 150, 600, 100, 25, 0, 12, true));
    
            // Terms acceptance
            zones.Add(zoneBuilder.CreateFieldCheckBoxZone(1, "terms", 50, 400, false, true));
    
            // Auto-filled date
            zones.Add(zoneBuilder.CreateFieldDateSignZone(1, "contract_date", 350, 300, 100, 25, 12));
    
            // Signature
            zones.Add(zoneBuilder.CreateFieldSignZone(1, "signature", 100, 150, 200, 60));
    
            // Initials on each page
            for (int i = 1; i <= zoneBuilder.PageCount; i++)
            {
                zones.Add(zoneBuilder.CreateFieldInitialZone(i, $"initials_p{i}", 500, 50, 50, 25));
            }
        }
    
        return zones.ToArray();
    }
    

    Example with PKI Mode

    public SignZoneDetails[] CreateAdvancedFormZones(string filePath)
    {
        var zones = new List<SignZoneDetails>();
    
        using (var zoneBuilder = new ZoneBuilder(filePath, isPki: true))
        {
            // Standard text fields
            zones.Add(zoneBuilder.CreateFieldTextZone(1, "name", 150, 700, 200, 25));
    
            // Multiline text zone (PKI only)
            zones.Add(zoneBuilder.CreateFieldTextAreaZone(1, "comments", 150, 500, 300, 100));
    
            // Dropdown (PKI only)
            zones.Add(zoneBuilder.CreateFieldDropdownZone(
                1, "contract_type", 150, 450, 200, 25,
                new[] { "Standard", "Premium", "Enterprise" },
                "Standard"
            ));
    
            // Signature
            zones.Add(zoneBuilder.CreateFieldSignZone(1, "signature", 100, 150, 200, 60));
        }
    
        return zones.ToArray();
    }
    

    Assigning Zones to Recipients

    string filePath = @"c:\temp\document.pdf";
    
    // Get the SHA512 hash of the PDF file
    string sha512 = CryptoHelper.GetSHA512OfFile(filePath);
    
    // Create the recipient
    var recipient = new RecipientInfo { Email = "signer@example.com" };
    
    // Build zone definitions
    var zones = CreateContractFormZones(filePath);
    
    var recipientIndex = new Dictionary<RecipientInfo, List<FileZoneDefinition>>
    {
        {
            recipient,
            new List<FileZoneDefinition>
            {
                new FileZoneDefinition
                {
                    UniqueName = sha512,
                    ZonesDef = new SignZoneDefinition
                    {
                        Mode = "define",
                        Zones = zones
                    }
                }
            }
        }
    };
    
    // Convert to list for the API
    var zoneDefList = SignHelper.ConvertRecipientIndexToList(recipientIndex);
    

    Error Handling

    Constructor Exceptions

    Exception Cause
    ArgumentException File path is empty or null
    FileNotFoundException PDF file does not exist

    CreateField*Zone Method Exceptions

    Exception Cause
    ArgumentOutOfRangeException Page number is invalid (< 1 or > number of pages)
    ObjectDisposedException The ZoneBuilder has been disposed
    NotSupportedException PKI zone type used without isPki: true
    ArgumentException Invalid options (e.g., empty list for OptionList/Dropdown)
    try
    {
        using (var zoneBuilder = new ZoneBuilder(filePath, isPki: false))
        {
            var zone = zoneBuilder.CreateFieldSignZone(1, "signature", 100, 100, 200, 50);
        }
    }
    catch (FileNotFoundException ex)
    {
        Console.WriteLine($"File not found: {ex.FileName}");
    }
    catch (ArgumentOutOfRangeException ex)
    {
        Console.WriteLine($"Invalid page: {ex.Message}");
    }
    catch (NotSupportedException ex)
    {
        Console.WriteLine($"Unsupported zone type: {ex.Message}");
    }
    

    Best Practices

    1. Use using: The ZoneBuilder implements IDisposable. Always use a using block to release resources.

    2. Create all zones for a PDF in a single session: For better performance, create all your zones for a PDF within a single using block.

    3. Unique field names: Ensure each fieldName is unique within the document, except for radio buttons in the same group.

    See Also

    • Overview
    • PDF Certification
    • Complete Signature Example
    In this article
    Back to top Secure Exchanges Inc. - Documentation