Skip to main content

Saving a Record

Persisting data is always your backend's responsibility. The Buildocs SDK sends form data to your endpoint — your handler validates and saves it to whatever storage you use.

After saving, your handler returns a /runevent response containing commands that tell the SDK what to do next — show a message, close the form, reload a table, or redirect.


Two save patterns

Pattern A — Save via DataRecord helper

If you are using the FormEventHandler library with DynamoDB, DataRecord provides a built-in save method:

public async Task Form_onClick(string widgetName)
{
if (widgetName != "savebtn") return;

await record.Save();

ShowMessage("success", "Record saved.");
CloseForm();
}

DataRecord.Save() handles create vs. update automatically based on whether the record exists. The record field is pre-populated with the current form data by the base Form_onInit — no manual loading required.


Pattern B — Direct database save

For any other storage (SQL Server, PostgreSQL, MongoDB, etc.) you write the persistence logic directly:

public async Task Form_onClick(string widgetName)
{
if (widgetName != "savebtn") return;

// Validate first
if (string.IsNullOrWhiteSpace(record.GetField("firstName")?.ToString()))
{
ShowMessage("warning", "First name is required.");
return;
}

if (record.IsNewByRequest())
{
var employee = new Employee
{
Id = Guid.NewGuid(),
FirstName = record.GetField("firstName")?.ToString()!,
LastName = record.GetField("lastName")?.ToString()!,
Email = record.GetField("email")?.ToString()!,
StatusId = int.Parse(record.GetField("status")?.ToString() ?? "1"),
CreatedAt = DateTime.UtcNow
};
await _db.Employees.AddAsync(employee);
}
else
{
var employee = await _db.Employees.FindAsync(Guid.Parse(record.GetRecordGuid()!));
if (employee == null)
{
ShowMessage("error", "Record not found.");
return;
}

employee.FirstName = record.GetField("firstName")?.ToString()!;
employee.LastName = record.GetField("lastName")?.ToString()!;
employee.Email = record.GetField("email")?.ToString()!;
employee.StatusId = int.Parse(record.GetField("status")?.ToString() ?? "1");
employee.UpdatedAt = DateTime.UtcNow;

_db.Employees.Update(employee);
}

await _db.SaveChangesAsync();

ShowMessage("success", "Employee saved.");
CloseForm();
}

After saving — common follow-up commands

// Show confirmation and close
cmd.SuccessMessage("Saved.");
cmd.CloseForm();

// Show confirmation and stay on the form (e.g. for continued editing)
cmd.SuccessMessage("Changes saved.");

// Refresh the current form after saving
cmd.RedrawScreen();

Returning the new GUID

When a new record is created, call cmd.SetAfterRecordSave() with the new GUID. This tells the SDK that a save has completed and provides the record's actual ID:

var newId = Guid.NewGuid();
// ... create record with newId ...
cmd.SetAfterRecordSave(newId.ToString());

SetAfterRecordSave does three things:

  • Updates the form's active GUID from "new" to the real record ID — subsequent saves will update rather than create.
  • Closes the modal if the form was opened in one.
  • Triggers a screen redraw.

For Pattern A (DataRecord.Save()), the base class calls cmd.SetAfterRecordSave() automatically — you do not need to call it yourself.