Skip to main content Link Search Menu Expand Document Toggle dark mode Copy Code (external link)
paperwork.help

Common Mistakes

Learn to identify and fix common data binding errors before they become problems.


Learning Objectives

By the end of this article, you’ll be able to:

  • Recognize common data binding errors
  • Fix syntax and formatting mistakes
  • Avoid null reference issues
  • Handle context and scope correctly
  • Debug template binding problems
  • Follow best practices for reliable templates

Mistake 1: Missing or Wrong Context

❌ Problem: Forgetting this in Loops

{{#each products}}
    <p>{{name}}</p>  <!-- May not bind correctly -->
{{/each}}

βœ… Solution: Always Use this

{{#each products}}
    <p>{{this.name}}</p>  <!-- Explicit context -->
{{/each}}

Why It Matters

Without this, the binding engine may look for the property in the wrong scope, especially in nested loops or complex templates.


Mistake 2: Incorrect Parent Context Navigation

❌ Problem: Using ../ for Values Passed to the Document

{{#each departments}}
    {{#each this.employees}}
        <p>{{../../companyName}}</p>  <!-- Won't work -->
    {{/each}}
{{/each}}

βœ… Solution: Use the Name Directly

Values added with WithData - such as companyName or model - are available everywhere by their name, inside any number of loops.

{{#each departments}}
    {{#each this.employees}}
        <p>{{companyName}}</p>
    {{/each}}
{{/each}}

../ is one level only

../ reads a property of the item in the loop directly outside the current one. It goes up a single level - ../../ is not supported.

{{#each departments}}
    {{#each this.employees}}
        <p>{{this.name}} - {{../name}}</p>  <!-- employee - department -->
    {{/each}}
{{/each}}

To use a value from further out, store it in a <var> in the outer loop. See Parent (../).


Mistake 3: Case Sensitivity Issues

❌ Problem: Mismatched Case

// C# code
builder.WithData("model", new { Name = "John" });  // Capital N
<!-- Template -->
<p>{{model.name}}</p>  <!-- lowercase n - Won't bind! -->

βœ… Solution: Match Case Exactly

builder.WithData("model", new { name = "John" });  // lowercase n
<p>{{model.name}}</p>  <!-- lowercase n - Will bind! -->

Best Practice

Use consistent casing convention:

  • camelCase for properties (recommended): firstName, orderTotal
  • PascalCase if matching C# classes: FirstName, OrderTotal

Mistake 4: Null Reference Errors

❌ Problem: Accessing Null Properties

builder.WithData("model", new
{
    customer = (object)null  // Null object
});
<p>{{model.customer.name}}</p>  <!-- Error! customer is null -->

βœ… Solution: Check for Null

{{#if model.customer}}
    <p>{{model.customer.name}}</p>
{{else}}
    <p>No customer information</p>
{{/if}}

Or provide defaults in C#:

builder.WithData("model", new
{
    customer = customerData ?? new { name = "N/A", email = "N/A" }
});

Mistake 5: Wrong Operator in Conditionals

❌ Problem: Using = Instead of ==

{{#if model.status = 'active'}}  <!-- Assignment, not comparison! -->
    <p>Active</p>
{{/if}}

βœ… Solution: Use == for Comparison

{{#if model.status == 'active'}}  <!-- Correct comparison -->
    <p>Active</p>
{{/if}}

Common Comparison Operators

  • == Equal to
  • != Not equal to
  • > Greater than
  • >= Greater than or equal
  • < Less than
  • <= Less than or equal

Mistake 6: Expression Syntax

❌ Problem: Expression in Quotes

{{'model.price + model.tax'}}  <!-- Outputs the text "model.price + model.tax" -->

βœ… Solution: Write the Expression Directly

{{model.price + model.tax}}

❌ Problem: Operator Precedence

<!-- a = 1, b = 2, c = 3 -->
{{model.a + model.b * model.c}}  <!-- 7: the multiplication is done first -->

βœ… Solution: Use Parentheses

{{(model.a + model.b) * model.c}}  <!-- 9 -->

calc() is not needed inside {{ }} - the operators work directly. See Operators.


Mistake 7: Forgetting Quotes in Strings

❌ Problem: Unquoted String Literals

{{concat(Hello, model.name)}}  <!-- Error: Hello is undefined -->

βœ… Solution: Quote String Literals

{{concat('Hello, ', model.name)}}  <!-- Correct -->

Mistake 8: Not Closing Blocks

❌ Problem: Missing {{/if}} or {{/each}}

{{#if model.showSection}}
    <div>Content</div>
<!-- Missing {{/if}} -->

<p>More content</p>

βœ… Solution: Always Close Blocks

{{#if model.showSection}}
    <div>Content</div>
{{/if}}

<p>More content</p>

Debugging Tip

Count your opening and closing tags:

  • {{#if}} must have {{/if}}
  • {{#each}} must have {{/each}}
  • Keep them properly nested

Mistake 9: Percentage Format Confusion

❌ Problem: Double Multiplication

<!-- If model.rate is already 15 (as in 15%) -->
{{format(model.rate, 'P0')}}  <!-- Shows 1500%! -->

βœ… Solution: Understand the Input

<!-- If model.rate is 0.15 (decimal) -->
{{format(model.rate, 'P0')}}  <!-- Shows 15% -->

<!-- If model.rate is 15 (already percentage) -->
{{model.rate}}%  <!-- Shows 15% -->

Remember: P format multiplies by 100!


Mistake 10: Modifying Parameters After Parsing

❌ Problem: Setting Params Too Late

var builder = factory.NewDocument().WithLayoutFile("template.html");
await builder.SaveAsync("output.pdf");
builder.WithData("model", data);  // Too late!

βœ… Solution: Set Parameters Before Saving

await factory.NewDocument()
    .WithLayoutFile("template.html")
    .WithData("model", data)   // Set first
    .SaveAsync("output.pdf");  // Then save

Mistake 11: Overwriting Parameters

❌ Problem: Same Key Used Twice

builder.WithData("model", customerData);
builder.WithData("model", invoiceData);  // Overwrites customer data!

βœ… Solution: Use Different Keys

builder.WithData("customer", customerData);
builder.WithData("invoice", invoiceData);

Mistake 12: Complex Inline Calculations

❌ Problem: Unreadable Template Logic

<p>{{format((model.price * model.quantity) + (model.price * model.quantity * 0.08), 'C2')}}</p>

βœ… Solution: Calculate in C#

var subtotal = price * quantity;
var tax = subtotal * 0.08;
var total = subtotal + tax;

builder.WithData("model", new
{
    price = price,
    quantity = quantity,
    subtotal = subtotal,
    tax = tax,
    total = total
});
<p>{{format(model.total, 'C2')}}</p>  <!-- Simple and readable -->

Mistake 13: Not Handling Empty Collections

❌ Problem: No Fallback for Empty Data

<h2>Products</h2>
{{#each products}}
    <div>{{this.name}}</div>
{{/each}}
<!-- Shows nothing if empty -->

βœ… Solution: Add Clause

<h2>Products</h2>
{{#each products}}
    <div>{{this.name}}</div>
{{else}}
    <p>No products available.</p>
{{/each}}

Mistake 14: Incorrect Date Formatting

❌ Problem: Wrong Format Specifiers

{{format(model.date, 'YYYY-MM-DD')}}  <!-- Wrong: YYYY should be yyyy -->

βœ… Solution: Use Correct Specifiers

{{format(model.date, 'yyyy-MM-dd')}}  <!-- Correct: lowercase yyyy -->

Common Mistakes:

  • YYYY β†’ Should be yyyy
  • DD β†’ Should be dd
  • mm (minutes) vs MM (month)

Mistake 15: Ignoring Data Types

❌ Problem: Treating Numbers as Strings

builder.WithData("model", new
{
    price = "123.45"  // String, not number
});
{{model.price *  2}}  <!-- May not work correctly -->

βœ… Solution: Use Correct Data Types

builder.WithData("model", new
{
    price = 123.45  // Numeric type
});
{{model.price *  2}}  <!-- Works correctly -->

Debugging Checklist

When data binding doesn’t work, check:

  • Case sensitivity - Property names match exactly?
  • Context - Using this in loops?
  • Null values - Checking for null before accessing properties?
  • Closed blocks - Every {{#if}} has {{/if}}?
  • Data added - WithData called with the name the template uses?
  • Data types - Numbers as numbers, not strings?
  • Format strings - Using correct format specifiers?
  • Operators - Using == for comparison, not =?

Best Practices Summary

Do’s βœ…

  1. Always use this in loops
  2. Check for null before accessing nested properties
  3. Calculate complex values in C# code
  4. Use consistent naming conventions
  5. Provide fallbacks for empty collections
  6. Set parameters early before saving
  7. Use clear variable names in templates
  8. Test with empty/null data to catch edge cases

Don’ts ❌

  1. Don’t put complex logic in templates
  2. Don’t ignore null values
  3. Don’t forget to close blocks
  4. Don’t use = for comparisons (use ==)
  5. Don’t calculate everything in templates
  6. Don’t rely on default type conversions
  7. Don’t nest loops too deeply (> 3 levels)
  8. Don’t forget to quote string literals

Testing Your Templates

Create Test Data

public object CreateTestData()
{
    return new
    {
        // Normal cases
        customer = new { name = "John Doe", email = "john@example.com" },

        // Edge cases
        emptyList = new object[] { },
        nullValue = (string)null,
        largeNumber = 1234567890,
        smallDecimal = 0.001,
        date = DateTime.Now,

        // Boundary cases
        longText = new string('A', 1000),
        specialChars = "Test & <special> characters"
    };
}

Test Edge Cases

[Test]
public async Task TestTemplateWithEmptyData()
{
    var result = await _factory.NewDocument()
        .WithLayoutFile("template.html")
        .WithData("model", new
        {
            items = new object[] { }  // Empty collection
        })
        .BuildAsync();

    Assert.IsTrue(result.Success, result.Error);
    Assert.Greater(result.Document.Binary.Length, 0);
}

[Test]
public async Task TestTemplateWithNullValues()
{
    var result = await _factory.NewDocument()
        .WithLayoutFile("template.html")
        .WithData("model", new
        {
            optionalField = (string)null
        })
        .BuildAsync();

    // Should still generate
    Assert.IsTrue(result.Success, result.Error);
}

Quick Reference: Common Fixes

Error Fix
Property not binding Check case sensitivity
Null reference Add {{#if}} check
Wrong parent context Use names directly for document values; ../ is one level only
Wrong calculation result Add parentheses - * and / are done before + and -
Percentage shows wrong Check if value needs P format
Block not rendering Check for closing {{/if}} or {{/each}}
Data not appearing Check the WithData name matches the template
Empty collection shows nothing Add {{else}} clause

Next Steps

Now that you know how to avoid common mistakes:

  1. Styling PDFs - Apply advanced styling
  2. Layout Techniques - Master page layout
  3. Practical Applications - Build real-world documents

Continue learning β†’ Styling PDFs**