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" }
]