Attributes
Attributes modify field behavior on both the frontend and backend.
Quick Reference
| Attribute | Effect | Enforcement | Example |
|---|---|---|---|
| UIName | Sets lookup display field | UI | [UIName] public string Name { get; set; } |
| UIDescription | Sets lookup description | UI | [UIDescription] public string Info { get; set; } |
| UIDisplayName | Custom field label (field) or BaseEntity overrides (class) | UI | [UIDisplayName("Serial #")] public string Name |
| UIRequired | Required field with validation | UI + Backend | [UIRequired] public string Name { get; set; } |
| UIRecommended | Shows blue cross indicator | UI only | [UIRecommended] public decimal Price { get; set; } |
| UIHide | Hidden from UI | Backend | [UIHide] public decimal InternalCost { get; set; } |
| UIReadOnly | Display only, no editing (field) or BaseEntity protection (class) | Backend | [UIReadOnly] public decimal Price { get; set; } |
| UICreateOnly | Editable on create only (field) or BaseEntity protection (class) | Backend | [UICreateOnly] public Guid OfferId { get; set; } |
| UIOption | Dropdown from Options table | UI | [UIOption("Category")] public Guid? CategoryId |
| UIDateFormat | Date display format | UI | [UIDateFormat("lll")] public DateTime OrderDate |
| UIMultiSelect | Many-to-many via junction table | Backend | [UIMultiSelect(...)] public ICollection<T> Tags |
| CascadeDelete | Cascade delete on FK | Backend | [CascadeDelete] public Guid? AddressId { get; set; } |
Complete Example
Widget Entity with Multiple Attributes
UIName & UIDescription
When selecting a Widget in a lookup, the Name field is displayed with the Description underneath.


UIRequired
Shows asterisk (*) and validates on submit.

UIRecommended
Shows blue cross (✚) to indicate recommended field.

UIDisplayName
Custom label instead of property name.

UIOption Setup
Options are managed from the Admin Dashboard under System → Options.


Option Entity Fields:
- Name: Option group identifier (matches UIOption parameter, e.g. "TodoPriority")
- Label: Display text shown in dropdown
- Value: Optional code/value for the option
- Order: Sort order in dropdown
Example:
This creates a dropdown populated with all Options where Name == "TodoPriority".
UIHide
UICreateOnly
Field can be set on create but becomes read-only afterward.
Field-level:
Class-level (BaseEntity fields):
UIDateFormat
Uses Day.js format strings:
"lll"→ Oct 14, 2025 9:30 PM"YYYY-MM-DD"→ 2025-10-14"MMM D, YYYY"→ Oct 14, 2025
UIMultiSelect
Creates many-to-many relationships through junction tables with automatic UI and data management.

Entity with UIMultiSelect:
Junction Table:
Target Entity:
Frontend Usage:
Data Format:
Read requests return UIMultiSelect fields as arrays of objects with id (target entity ID) and name properties:
On create or update, adding/removing objects with id (target entity ID) and name properties will add or remove the corresponding N:N junction records.
Permissions:
- Primary entity: CREATE (on create) or UPDATE (on update) required
- Junction entity: CREATE and DELETE required
- Target entity: READ required
- Permissions can be at USER, TEAM, or SYSTEM level
Limitations: Requires Guid primary keys. Target entity must have Name property or [UIName] attribute. Junction table can have additional fields but UIMultiSelect only manages the two FK fields.
Cascade Delete Rules
Cascade behavior is determined by nullable operator and [CascadeDelete] attribute:
| Configuration | Behavior |
|---|---|
public Guid ForeignId (required) | Deleting parent deletes this record |
public Guid? ForeignId (optional) | Deleting parent sets FK to null |
[CascadeDelete] public Guid? ForeignId | Deleting parent deletes this record |
Delete permissions are only checked on the record being deleted, not on cascaded records. This matches enterprise CRM behavior.