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 havemust 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 beyyyyDD→ Should beddmm(minutes) vsMM(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
thisin loops? - Null values - Checking for null before accessing properties?
- Closed blocks - Every
has? - Parameters set -
doc.Paramsset beforeSaveAsPDF()? - Data types - Numbers as numbers, not strings?
- Format strings - Using correct format specifiers?
- Operators - Using
==for comparison, not=?
Best Practices Summary
Do’s ✅
- Always use
thisin loops - Check for null before accessing nested properties
- Calculate complex values in C# code
- Use consistent naming conventions
- Provide fallbacks for empty collections
- Set parameters early before saving
- Use clear variable names in templates
- Test with empty/null data to catch edge cases
Don’ts ❌
- Don’t put complex logic in templates
- Don’t ignore null values
- Don’t forget to close blocks
- Don’t use
=for comparisons (use==) - Don’t calculate everything in templates
- Don’t rely on default type conversions
- Don’t nest loops too deeply (> 3 levels)
- 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:
- Styling PDFs - Apply advanced styling
- Layout Techniques - Master page layout
- Practical Applications - Build real-world documents
Continue learning → Styling PDFs**