Commands
Create snippets of code that work across the Jetveo application. Allows for direct data manipulation inside application database.
Testing is also available. See Test in the upper right of the App Builder screen. See below for more information.
Creating a new a command
General
- Name - name of a command, shown in a list of commands
- Code identifier - code identifier of the command used internally and when logging application errors
- Type - type of a Business command
- Custom command - has it's own input model and it's own page that allows app user to fill it's model values
- Entity command - a command executed on a specific entity record
- Entity batch command - a command executed on a collection of entity records
- Child entity command - a command that needs both entity and it's parent references
- Child entity batch command - a command executed on a collection of entities that has a reference to parent entity
- Result type - result of the command. Allows for creating Data grids or Documents from command results.
UI
- Default title for action button - default label used on a new Action button and on a Custom command page
- Default icon for action button - default icon used in a label of a new Action button and on a Custom command page
Security
- Execution condition - security condition that needs to return true for the command to be executed
Custom Command Input Model
Lets you set up a custom input Model for the command.
First, go to the "Model" tab and define Model's Attributes and References. You can use Inherited aspects. Attribute and reference values can be sent to a command through Parameters (that you set up when creating an Action button), or from command Page accessible to application user.
To set up such page, go to the "View" tab. As with any other view, select a layout and populate it with Data fields and/or Elements.
Local functions
If you want to use a function exclusively for your command, you can declare the function within the scope of the command. The following is a simple example:
(exampleEntity, db, ctx) =>
{
int sum = 0;
int foo()
{
App.Log.Info("Calling foo");
return 2;
}
for (int i = 0; i < 5; i++)
{
sum += foo();
}
}
Using a command
Business commands can be attached to different places or events depending on their type:
Entity commands:
- Entity pages (page Actions)
- Entity page tab (page Actions)
- List page (as a command or batch command)
- Data grid (as a command or batch command)
- Entity events (on created, on deleted, on attribute updated)
Child entity commands:
- Data grid (command, batch command)
- Child Entity events (on child created, on child deleted, on child modified)
Custom commands:
- Entity pages (page Actions)
- Entity page tab (page Actions)
- List page (page Actions)
- Application menu item (they have their own page)
- API endpoint to allow 3rd party integration
- Scheduled events
Command results
Command results let you show or save result of a command.
Report result
Returns a table of rows and columns rendered as a report in the Jetveo UI, or consumed directly by REST API callers as an array of objects.
In the following example we create a Data grid that lists application users and their emails:
The most convenient entry points are the two static factory methods:
// From a collection — reflects public properties as columns
return ReportResult.FromEnumerable(orders);
// From a single object — same reflection, one row
return ReportResult.FromSingle(summary);
For full control, use the direct constructor:
var columns = new[]
{
new ReportResult.Column("Product", ReportResult.ColumnType.Text),
new ReportResult.Column("Quantity", ReportResult.ColumnType.Number),
};
var rows = items.Select(i => new ReportResult.Row(i.Product, i.Quantity));
return new ReportResult(columns, rows, message: "Stock levels");
FromEnumerable and FromSingle support string, Guid, bool, int, long, float, and decimal properties.
Properties of other types are silently excluded from the output.
Report results expire after 60 minutes. After that the report is no longer available.
Document result
Returns a document that the Jetveo UI presents as a download link, inline preview, or automatic download depending on the configured options.
In the following example, we use Razor + HTML template to render a new html page and then create a byte stream out of it to allow app users to save it:
var htmlTable = App.Templates.HtmlReport.Render(templateModel);
var tableBytes = Encoding.UTF8.GetBytes(htmlTable);
return new DocumentResult("report.html", tableBytes);
You can specify Options to control the behavior of the user interface:
- ShowDownloadLink: Displays a file download link if the file name is not empty. The default value is TRUE.
- ShowPreview: Enables a document preview in the results window. This option is applicable only for the following file extensions: .html, .htm, .pdf, .jpg, .png, .svg. The default value is TRUE.
- AutoDownload: Automatically downloads the document and closes the command results window. The default value is FALSE.
- AllowPublicAccess: Enables anonymous users to download the document. The default value is FALSE.
- DownloadAsAttachment: Forces the document to be downloaded instead of displayed inline by the browser. The default value is FALSE.
In the following example, the application will begin downloading the document immediately and will close the command window.
Constructors:
// Ad-hoc byte array — no storage lookup required
return new DocumentResult("export.xlsx", excelBytes);
// Ad-hoc string content — encoded as UTF-8
return new DocumentResult("report.html", "<h1>Report</h1>");
// Persistent document already in document storage
return new DocumentResult(document); // IDocument
return new DocumentResult(documentRevision); // IDocumentRevision
Pass a DocumentResult.Options record to control how the document is presented in the UI:
return new DocumentResult("report.pdf", pdfBytes, options: new DocumentResult.Options(
AutoDownload: true, // download immediately and close the result window (default: false)
ShowPreview: false, // suppress inline preview (default: true)
ShowDownloadLink: true, // show a download link (default: true)
DownloadAsAttachment: true, // force download instead of inline browser display (default: false)
AllowPublicAccess: false // allow unauthenticated download (default: false, use with caution)
));
Preview is supported for .html, .htm, .pdf, .jpg, .png, and .svg files.
Redirect result
Specialized type of CommandResult that enables users to specify a URL to which they want to redirect, along with the target behavior of the redirect. This class is particularly useful for scenarios where navigation control is required within an application.
Parameters:
- Url: A string representing the URL to which the user will be redirected.
- OpenTarget: An enumeration value that specifies how the URL should be opened. The possible values are:
- SameTab: Opens the URL in the current tab, replacing the existing content.
- NewTab: Opens the URL in a new browser tab.
- Modal: Opens the URL in a modal dialog within the application.
string dashboardUrl = "https://example.com/dashboard";
return new RedirectResult(dashboardUrl, RedirectResult.Target.NewTab);
Data result
DataResult is a command result type for returning data payloads from Jetveo commands exposed via the REST Command API. When a command returns a DataResult, the framework serializes it directly into the HTTP response — no extra wiring needed.
Use it when a command needs to return structured data rather than a simple success/failure acknowledgement:
(model, db, ctx) =>
{
var report = db.Orders.Where(o => o.UserId == ctx.User.Id).ToList();
return DataResult.Json(report);
}
Six response formats are available out of the box: enveloped JSON following the Jetveo command protocol (CommandJson), plain JSON (Json), pre-serialized JSON pass-through (Json(string)), XML (Xml), plain text and other text formats (Text), and raw binary for file downloads (Data). All formats except the legacy constructor use System.Text.Json.
See full reference in Command API documentation.
Queued vs Asynchronous commands
Queued commands
The default mode of command execution is queued. This means when the command is invoked, it is placed into the command queue, and executes only after all preceding commands in the queue. This is usually not a problem, as the command queue is usually empty.
Asynchronous commands
Asynchronous commands start executing immediately upon invocation. You can think of it as a second thread, separate from the main command queue. This can be particularly useful if you expect the command execution to last for a long duration, and when the following commands do not depend on the changes made by the current one.
The platform limits the number of concurrent asynchronous commands to 64.
There is no way to lock shared data in an asynchronous commands, so be aware that race conditions can occur.
Invoking Commands in code
Each command has an object accessible in the code: App.Commands.ExampleCommand. You can invoke a command by calling the InvokeAsync(ExampleCommandModel model) method on this object, while passing in the command model.
This method immediately invokes the command, and proceeds to the next line. Notably this means the code does not wait for the command to finish executing, and cannot use the command's result. When dealing with synchronous commands, the invoked command begins executing only after the invoker command has finished.
Special case: Deadlock
When an app uses its own command API within a command, the command API must be asynchronous. Otherwise this will result in a deadlock.