C# hooks
Run your own C# before or after any data operation.
Hooks are C# classes stored as scripts on an entity. The data engine runs them around create, read, update, delete and bulk operations.
| Phase | Interface | Method | Use it to |
|---|---|---|---|
| Validate | IValidationHook | ValidateAsync(HookContext) | Refuse the operation with a message |
| Pre-execute | IPreExecutionHook | PreExecuteAsync(HookContext) | Change fields or the where-clause before the write |
| Post-execute | IPostExecutionHook | PostExecuteAsync(HookContext) | React after the write |
HookContext
HookContext carries the operation, the entity name, the Fields being written, bulk records, the WhereClause, the entity id, a correlation id, and Errors and Logs lists. Every message added to Errors in a validation hook refuses the save and is shown to the user.
using TAF.Infra.QueryHook.Interfaces;
using TAF.Infra.QueryHook.Models;
public class DiscountRule : IValidationHook
{
public Task ValidateAsync(HookContext context)
{
if (context.Fields.TryGetValue("DiscountPercent", out var value) && Convert.ToDecimal(value) > 20)
context.Errors.Add("Discounts above 20% need approval.");
return Task.CompletedTask;
}
}Running and caching
Scripts are compiled with Roslyn the first time they are needed and cached by content. Several hooks on one entity run in priority order. Bulk inserts run post-execute hooks only.
A validation hook that does not compile blocks every save on its entity. Use Check Script in TAF Studio before publishing.
How custom code runs
Hooks run inside the platform's data service with your application's permissions. A static check refuses scripts that use file-system, process or socket APIs, but it is a guard rail, not isolation: treat hooks as production code your team reviews and owns.
When to write a script
Most business rules in TechAppForce are configuration: required fields, lookups, lifecycles and allowed transitions, approvals, workflows built from ready-made actions, and role access. Reach for a script when a rule cannot be expressed that way, for example a check that reads other records before allowing a save, or a calculation a workflow step needs.
Kinds of script
- Record hooks (C#). Bound to one object and to the operations they apply to (insert, update, delete). Each hook runs in a phase: Validate, which can block the operation; PreExecute, before the database write; or PostExecute, after it. Hooks on the same object run in priority order.
- Workflow actions (C#). Custom steps you can use in a workflow alongside the built-in actions.
- Extensions (TypeScript or JavaScript). Code the web app loads for a screen, grid, kanban board, tree view or sign-in page.
Record hooks in C#
A hook is a C# class that implements one or more of IValidationHook, IPreExecutionHook and IPostExecutionHook. Each method receives a HookContext with the operation, the entity name, the submitted fields, and lists for errors and log lines.
using System.Threading.Tasks;
using TAF.Infra.QueryHook.Interfaces;
using TAF.Infra.QueryHook.Models;
using TAF.Infra.Contract.ValueObjects;
// Bound to the Order object, phase Validate, operations Insert and Update.
public class CustomHook : IValidationHook
{
public async Task ValidateAsync(HookContext context)
{
if (context.Fields.TryGetValue(new FieldName("Quantity"), out var qty)
&& System.Convert.ToDecimal(qty) <= 0)
{
// Any message added here blocks the save and is shown to the user.
context.Errors.Add("Quantity must be greater than zero.");
}
await Task.CompletedTask;
}
}- In the Validate phase, every message added to
context.Errorsblocks the save and becomes a validation error; the web app shows it to the user. - In PreExecute you can change
context.Fieldsbefore the write, for example to set a derived value. In PostExecute,context.Resultholds the result of the operation. - Lines added to
context.Logsare returned with the result of the run, and appear in TAF Studio's run report. - A hook can query other objects through the platform's query extensions, with the tenant, app and environment of the current request.
How scripts are checked
- The platform compiles C# with the .NET compiler and runs a static security analysis that rejects disallowed APIs before a script runs.
- You can compile a script without running it. In TAF Studio, Check Script shows compiler diagnostics and security findings on the exact line. Through the TAFI gateway, the same check is available as a tool.
- Compiled scripts are cached by content, so an unchanged script is not recompiled on every request.
Gotchas
A validation hook that does not compile blocks every save on its object. Always compile-check a hook before you publish it.
- A Validate hook that throws an exception does not block the save; the exception goes to the log. To block, add a message to
context.Errorsdeliberately. - On update,
context.Fieldsholds only the submitted columns. Read the saved record if you need the rest. - A newly added hook can take several minutes to take effect, because the platform caches which hooks each object has. Test after a short wait.