Skip to main content

Overview

Commands returned by your backend inside the feCommand object control all frontend behavior — opening modals, showing messages, redirecting, validating, and more.

Response Structure​

Your backend endpoints return commands in this format:

{
"fieldAllowedValues": null,
"data": {
"fieldName1": "fieldValue1",
"fieldName2": "fieldValue2"
},
"widgetData": {},
"definition": null,
"widgetsState": null,
"feCommand": {
"CommandName1": null,
"CommandName2": null
}
}

Multiple commands can be included in a single response by adding multiple keys to the feCommand object.

Available Commands​

CommandCategoryDescription
OpenModalNavigationOpen a form in a modal window
RedirectNavigationRedirect the browser to a URL
MoveToTabNavigationSwitch to a specific tab
FetchUserMenuNavigationReload the user navigation menu
RedrawScreenForm StateForce the form to reload
AfterRecordSaveForm StateClose modal and refresh parent after save
ReplaceContextRecordGuidForm StateReplace the current record GUID
FormValidationDataForm StateDisplay server-side validation errors
MessagesNotificationsShow notification messages
DisplayErrorPageNotificationsShow a full-page error
DownloadFilesTrigger a file download
PreviewDocumentFilesOpen a document preview modal
DisplayComponentComponentsOpen a custom UI component
CloseDisplayComponentComponentsClose a custom UI component
CustomResponseAdvancedReturn a custom data object

Command Combinations​

Multiple commands can be combined in a single response.

Save and Show Message​

{
"feCommand": {
"Messages": [{ "Code": "success", "Text": "Record saved successfully!" }],
"AfterRecordSave": { "guid": "550e8400-e29b-41d4-a716-446655440000" },
"RedrawScreen": true
}
}
string newRecordGuid = SaveRecordToDatabase(formData);

response.Set("FECommand", new Dictionary<string, object>
{
["Messages"] = new List<object> { new { Code = "success", Text = "Record saved successfully!" } },
["AfterRecordSave"] = new { guid = newRecordGuid },
["RedrawScreen"] = true
});

Validate and Focus Tab​

{
"feCommand": {
"FormValidationData": {
"email": "Invalid email format",
"phone": "Phone number is required"
},
"MoveToTab": { "widgetName": "contactInfoTab" }
}
}
response.Set("FECommand", new Dictionary<string, object>
{
["FormValidationData"] = new Dictionary<string, string>
{
{ "email", "Invalid email format" },
{ "phone", "Phone number is required" }
},
["MoveToTab"] = new { widgetName = "contactInfoTab" }
});

Download​

{
"feCommand": {
"Download": { "outFileName": "Monthly_Report.pdf", "filePath": "/path/to/report.pdf" }
}
}
// At the top of your runEvent method — handle the follow-up download request
DownloadFileDetailsDto downloadFileData = _pluginContextProvider.GetFECommandProvider().GetDownloadDetails();
if (downloadFileData != null && System.IO.File.Exists(downloadFileData.filePath))
{
S3FileStorageService s3FileStorageService = (S3FileStorageService)_pluginServiceProvider.GetFileStorageProvider();
Response.ContentType = S3FileStorageService.GetMimeType(downloadFileData.outFileName);
Response.Headers.Add("Content-Disposition", $"attachment; filename*=UTF-8''{Uri.EscapeDataString(downloadFileData.outFileName)}");

using (FileStream fileStream = new FileStream(downloadFileData.filePath, FileMode.Open, FileAccess.Read))
{
await s3FileStorageService.WriteFileInChunks(Response.Body, fileStream);
}

System.IO.File.Delete(downloadFileData.filePath);
return new EmptyResult();
}

// Normal event handling — set the Download command to trigger the follow-up request
string filePath = GenerateReport();

response.Set("FECommand", new Dictionary<string, object>
{
["Download"] = new { outFileName = "Monthly_Report.pdf", filePath = filePath }
});
info

When Download is present, the frontend makes a follow-up request to runEvent solely to stream the file. Any other commands included in the same response will not be executed.


Important Notes​

Command Execution Order​

Commands in the feCommand object are executed in the order they are added.

Validation Clears Other Commands​

FormValidationData clears all other commands. Validation errors stop all other form actions.

When a form is opened in a modal:

  • AfterRecordSave closes the modal instead of redirecting
  • Redirect commands may behave differently

Multiple Messages​

Messages accepts an array — multiple messages can be displayed at once:

"Messages": [
{ "Code": "warning", "Text": "Some fields are missing" },
{ "Code": "info", "Text": "Please complete all required fields" }
]