Skip to main content Link Search Menu Expand Document (external link)

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: Wrong Number of ../

{{#each departments}}
    {{#each this.employees}}
        <p>{{../companyName}}</p>  <!-- Too few ../ -->
    {{/each}}
{{/each}}

✅ Solution: Count Your Nesting Levels

{{#each departments}}
    {{#each this.employees}}
        <p>{{../../companyName}}</p>  <!-- Correct: goes up 2 levels -->
    {{/each}}
{{/each}}

Debugging Tip

Count the `` blocks you’re inside:

  • 1 level deep: ../property
  • 2 levels deep: ../../property
  • 3 levels deep: ../../../property

Mistake 3: Case Sensitivity Issues

❌ Problem: Mismatched Case

// C# code
doc.Params["model"] = new { Name = "John" };  // Capital N
<!-- Template -->
<p>{{model.name}}</p>  <!-- lowercase n - Won't bind! -->

✅ Solution: Match Case Exactly

doc.Params["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

doc.Params["model"] = new
{
    customer = 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#:

doc.Params["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: Incorrect calc() Syntax

❌ Problem: Operators Not as Strings

{{calc(model.price + model.tax)}}  <!-- Won't work -->

✅ Solution: Operators Must Be String Arguments

{{calc(model.price, '+', model.tax)}}  <!-- Correct -->

❌ Problem: Parentheses as Single Argument

{{calc((model.a + model.b), '*', model.c)}}  <!-- Won't work -->

✅ Solution: Parentheses as Separate Arguments

{{calc('(', model.a, '+', model.b, ')', '*', model.c)}}  <!-- Correct -->

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 or

{{#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:

  • must have
  • must have
  • 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 doc = Document.ParseDocument("template.html");
doc.SaveAsPDF("output.pdf");
doc.Params["model"] = data;  // Too late!

✅ Solution: Set Parameters Before Saving

var doc = Document.ParseDocument("template.html");
doc.Params["model"] = data;  // Set first
doc.SaveAsPDF("output.pdf");  // Then save

Mistake 11: Overwriting Parameters

❌ Problem: Same Key Used Twice

doc.Params["model"] = customerData;
doc.Params["model"] = invoiceData;  // Overwrites customer data!

✅ Solution: Use Different Keys

doc.Params["customer"] = customerData;
doc.Params["invoice"] = invoiceData;

Mistake 12: Complex Inline Calculations

❌ Problem: Unreadable Template Logic

<p>{{format(calc(calc(model.price, '*', model.quantity), '+',
            calc(calc(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;

doc.Params["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

doc.Params["model"] = new
{
    price = "123.45"  // String, not number
};
{{calc(model.price, '*', 2)}}  <!-- May not work correctly -->

✅ Solution: Use Correct Data Types

doc.Params["model"] = new
{
    price = 123.45  // Numeric type
};
{{calc(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 has?
  • Parameters set - doc.Params set before SaveAsPDF()?
  • 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 void TestTemplateWithEmptyData()
{
    var doc = Document.ParseDocument("template.html");
    doc.Params["model"] = new
    {
        items = new object[] { }  // Empty collection
    };

    byte[] pdf;
    using (var ms = new MemoryStream())
    {
        doc.SaveAsPDF(ms);
        pdf = ms.ToArray();
    }

    Assert.IsNotNull(pdf);
    Assert.Greater(pdf.Length, 0);
}

[Test]
public void TestTemplateWithNullValues()
{
    var doc = Document.ParseDocument("template.html");
    doc.Params["model"] = new
    {
        optionalField = (string)null
    };

    // Should not throw exception
    byte[] pdf;
    using (var ms = new MemoryStream())
    {
        doc.SaveAsPDF(ms);
        pdf = ms.ToArray();
    }

    Assert.IsNotNull(pdf);
}

Quick Reference: Common Fixes

Error Fix
Property not binding Check case sensitivity
Null reference Add `` check
Wrong parent context Count ../ correctly
calc() not working Operators as strings: '+'
Percentage shows wrong Check if value needs P format
Block not rendering Check for closing or
Data not appearing Verify doc.Params set before save
Empty collection shows nothing Add `` 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**