Scripting API Reference
This document provides an exhaustive technical reference of the properties, methods, and injected services available within the Struktural C# Scripting Sandbox (IScriptContextBridge).
It is optimized to serve as a strict technical guide for developers and AI assistants.
1. Core Context Properties
These properties expose the current state of the application and the data being manipulated.
public T? Entity { get; set; }The strongly-typed instance of the current business entity. Modifying this object inBeforeCreateorBeforeUpdateautomatically saves the changes to the database.public T? OldEntity { get; }The pristine database state of the entity before current modifications were applied. Available only inBeforeUpdateandAfterUpdatehooks.public DbContext Db { get; }The Entity Framework Core database context scoped to the current tenant. Used to query or mutate other tables.public ClaimsPrincipal? User { get; }The currently authenticated user. UseUser.IsInRole("RoleName")to check permissions.public string RecordId { get; }The string representation of the ID requested by the client. Especially useful inOnLoadscripts for Virtual Entities.public string ChangedFieldName { get; }Populated only during theOnChangehook. Indicates the exact field name that triggered the event.public string ActionName { get; }Populated only during theCustomActionhook. Identifies the specific button key clicked by the user.public IScriptWorkflowContext? WorkflowContext { get; }Populated only if the script is executed by a Workflow node. ContainsWorkflowId,ReferenceKey, and a mutableVariablesdictionary.public bool Cancel { get; set; }Set totrueto cancel the default persistence operation. Critical for bypassing EF Core inserts when dealing with Virtual Entities.
2. Data Fetching & EF Core Operations
Because scripts run asynchronously within a high-performance engine, synchronous database calls (e.g., .ToList(), .FirstOrDefault()) are strictly forbidden as they cause thread-pool starvation.
Mandatory EF Core Async Methods
You must import Microsoft.EntityFrameworkCore and use its asynchronous extensions for all queries:
await Db.Set<T>().FirstOrDefaultAsync(x => x.Condition)await Db.Set<T>().ToListAsync()await Db.Set<T>().AnyAsync(x => x.Condition)await Db.Set<T>().CountAsync()await Db.Set<T>().ExecuteUpdateAsync(s => s.SetProperty(...))await Db.Set<T>().ExecuteDeleteAsync()
Optimized Navigation Loaders
To prevent the overhead of deep Include() chains or N+1 query problems, Struktural provides optimized lazy-loading methods:
public Task<TProperty?> LoadItemAsync<TProperty>(Expression<Func<T, TProperty>> selector) where TProperty : classAsynchronously resolves a Many-to-One Foreign Key into its full object. Example:var customer = await LoadItemAsync(x => x.Customer);public Task<List<TElement>> LoadCollectionAsync<TElement>(Expression<Func<T, ICollection<TElement>>> selector) where TElement : classAsynchronously fetches all records belonging to a One-to-Many collection. Example:var lines = await LoadCollectionAsync(x => x.OrderLines);public IQueryable<TElement> LoadCollection<TElement>(Expression<Func<T, ICollection<TElement>>> selector) where TElement : classReturns anIQueryable, allowing you to append filters before executing the query. Example:var activeLines = await LoadCollection(x => x.OrderLines).Where(l => l.IsActive).ToListAsync();
Out-of-Band Persistence
public Task SaveEntityAsync<TRecord>(TRecord entity, bool deepSave = false) where TRecord : classCRITICAL: When modifying records inside aCustomActionor modifying secondary entities in anAfterUpdatehook, standard EF tracking collisions can occur. You MUST use this extension method on theDbcontext to save safely. Example:await Db.SaveEntityAsync(Entity);
3. The UI Controller (Ui)
The Ui property exposes the IUiContext interface, allowing backend scripts to push reactive updates to the frontend browser.
void ShowToast(string message, string type = "info");Displays a temporary popup. Types:"info","success","warning","danger". Example:Ui.ShowToast("Record updated", "success");void ShowAlert(string message, string title = "Alert", string type = "info");Displays a blocking modal alert requiring user dismissal.void ShowConfirm(string message, string title, string yesAction, string noAction = "");Displays a confirmation modal.yesActionandnoActionmust map to validCustomActionnames defined in your schema. Example:Ui.ShowConfirm("Proceed?", "Confirm", "ExecuteTask");void Navigate(string viewId, int? entityId = null);Redirects the browser to a specific view. Use theViewsgenerated constants. Example:Ui.Navigate(Views.Customer_Grid_1);void Navigate(string viewId, FilterNode filter);Redirects the browser to a Grid view with an advanced filter automatically applied.void SetReadOnly(string fieldName, bool isReadOnly);Dynamically locks or unlocks an input field in the active form.void Focus(string fieldName);Forces the user's cursor to focus on a specific input field.
4. Execution Interruption
public void AddError(string message)Adds a global error and fails validation gracefully without throwing exceptions.public void AddError(string field, string message)Fails validation and explicitly highlights the faulty field in red on the frontend.public void Abort(string message)Throws aScriptAbortException. Instantly halts execution and forces an EF Core transaction rollback.
5. System Services
These services are natively injected into the script context.
IEmailService EmailTask SendEmailAsync(string to, string subject, string body, bool isHtml = true);Example:await Email.SendEmailAsync("test@demo.com", "Hi", "<b>Hello</b>");ISecretManagerService SecretsTask<string?> GetSecretAsync(string secretName);Task SetSecretAsync(string secretName, string value);Example:var token = await Secrets.GetSecretAsync("ApiToken");ISecureDownloadService SecureDownloadsTask<string> CreateLinkAsync(int fileId, int maxUses, DateTime? expirationDate);Example:string url = await SecureDownloads.CreateLinkAsync(Entity.FileId, 1, DateTime.UtcNow.AddHours(1));IArchiveService ArchivesTask<string> RegisterDynamicZipAsync(string archiveName, Dictionary<string, int> fileMap);
6. Utilities
FilterUtilsUsed to build dynamic JSON filters for the Grid or Navigation.FilterNode CreateSimple(string field, object? value, string op = "eq")(Auto-translates*tocontains).FilterNode? Combine(params FilterNode?[] nodes)Example:var f = FilterUtils.CreateSimple("Status", "Active");