System Services & Utilities

The Struktural execution context exposes a variety of built-in services and utility classes to facilitate complex integrations, querying, and file management without requiring external NuGet packages.

1. External API Clients (Services)

If you have defined ExternalServiceDefinition objects in your Schema via the Studio (or OpenAPI imports), the engine generates strongly-typed clients for them.

var dto = new Struktural.Generated.Services.Stripe.Models.ChargeDto { Amount = 500 };
var response = await Services.Stripe.CreateCharge(dto);

if (!response.Success) {
    AddError($"Gateway error: {response.ErrorMessage}");
}

2. Secrets Management (Secrets)

Provides access to the ISecretManagerService configured for the current Tenant (Azure Key Vault, AWS Secrets Manager, or Local).

string apiKey = await Secrets.GetSecretAsync("ThirdPartyApiKey");

3. Email Dispatcher (Email)

Provides access to the IEmailService. Requires SMTP configuration in the Tenant's app-config.json settings.

await Email.SendEmailAsync(
    Entity.CustomerEmail, 
    "Order Confirmation", 
    $"<h1>Thank you!</h1> Your order <b>#{Entity.Id}</b> is confirmed."
);

4. Secure Downloads (SecureDownloads)

The ISecureDownloadService allows you to generate ephemeral, highly secure download links for sensitive files stored in the Struktural_Sys_File table. These links do not expose the underlying Azure/AWS Blob URL and decrypt the file on-the-fly.

// Generate a link valid for 1 use only, expiring in 24 hours
string url = await SecureDownloads.CreateLinkAsync(Entity.ConfidentialDocumentId, 1, DateTime.UtcNow.AddHours(24));

Ui.ShowAlert($"Your download link is ready: {url}", "Secure Link", "info");

5. Dynamic Archives (Archives)

The IArchiveService enables the dynamic generation of ZIP files on the server without consuming physical disk space. It streams the referenced files directly from cloud storage to the client.

var map = new Dictionary<string, int>
{
    { "Contracts/Lease_2024.pdf", 104 },
    { "Identification/Passport.jpg", 105 }
};

string token = await Archives.RegisterDynamicZipAsync("Client_Dossier.zip", map);
Ui.ShowToast($"Download initiated. Token: {token}", "success");

6. Filter Utilities (FilterUtils)

When interacting with the GridFilter property (to override grid data) or when using Ui.Navigate(viewId, filterNode), you must supply a FilterNode object. FilterUtils simplifies building these complex JSON trees programmatically.

// Example: Navigate to the Invoices grid, showing only Unpaid invoices for the current customer
var f1 = FilterUtils.CreateSimple("CustomerId", Entity.Id, "eq");
var f2 = FilterUtils.CreateSimple("Status", "Unpaid", "eq");

var combinedFilter = FilterUtils.Combine(f1, f2);

Ui.Navigate(Views.Invoice_Grid_1, combinedFilter);