Enum values can be localized using ABP's localization system. Add localization keys in the format `Enum:{EnumTypeName}.{ValueName}` to your localization JSON files:
```json
{
"culture": "en",
"texts": {
"Enum:OrganizationType.Corporate": "Corporate",
"Enum:OrganizationType.Enterprise": "Enterprise",
"Enum:OrganizationType.Startup": "Startup",
"Enum:OrganizationType.Consulting": "Consulting"
}
}
```
The Blazor UI automatically uses these localization keys for enum dropdowns and display values. If no localization key is found, the enum member name is used as-is.
## Fluent API
The Fluent API has the **highest priority** in the configuration system. Use `AbpDynamicEntityConfig.EntityConfigurations` to override any attribute or JSON setting programmatically.
@ -263,47 +281,98 @@ public override void ConfigureServices(ServiceConfigurationContext context)
The `Configure` method provides an `EntityDescriptor` instance. You can set its properties directly:
| Property / Method | Description |
|--------|-------------|
| `SetDisplayProperty(name)` | Set the display property for lookups |
| `SetParent(entityName)` | Set parent entity for nesting |
| `SetUI(action)` | Configure entity-level UI |
| `ConfigureProperty(name, action)` | Configure a specific property |
| `AddInterceptor(name, type, js)` | Add a JavaScript interceptor. `name`: `"Create"`, `"Update"`, or `"Delete"`. `type`: `Pre`, `Post`, or `Replace`. `Replace-Create` must return the new entity's Id |
| `DefaultDisplayPropertyName` | Set the display property for lookups |
| `Parent` | Set parent entity name for nesting |
| `UI` | Set entity-level UI (`EntityUIDescriptor` with `PageTitle`) |
| `AddOrGetProperty(name)` | Get or create a property descriptor for configuration |
| `FindProperty(name)` | Find a property descriptor by name (returns `null` if not found) |
| `GetProperty(name)` | Get a property descriptor by name (throws if not found) |
| `Interceptors` | List of `CommandInterceptorDescriptor` — add interceptors directly |
### Property Configuration
### Property Configuration Methods
`AddOrGetProperty` returns an `EntityPropertyDescriptor`. Configure it using direct property assignment and extension methods:
| **Foreign Access** | View/Edit related entities from the parent's UI | [Foreign Access](foreign-access.md) |
| **Export** | Export entity data to Excel (XLSX) or CSV | See below |
## Export (Excel / CSV)
The Low-Code System provides built-in export functionality for all dynamic entities. Users can export filtered data to **Excel (XLSX)** or **CSV** directly from the Blazor UI.
### How It Works
1. The client calls `GET /api/low-code/entities/{entityName}/download-token` to obtain a single-use download token (valid for 30 seconds).
2. The client calls `GET /api/low-code/entities/{entityName}/export-as-excel` or `GET /api/low-code/entities/{entityName}/export-as-csv` with the token and optional filters.
### API Endpoints
| Endpoint | Description |
|----------|-------------|
| `GET /api/low-code/entities/{entityName}/download-token` | Get a single-use download token |
| `GET /api/low-code/entities/{entityName}/export-as-excel` | Export as Excel (.xlsx) |
| `GET /api/low-code/entities/{entityName}/export-as-csv` | Export as CSV (.csv) |
Export requests accept the same filtering, sorting, and search parameters as the list endpoint. Server-only properties are automatically excluded, and foreign key columns display the referenced entity's display value instead of the raw ID.
## Custom Commands and Queries
The Low-Code System allows you to replace or extend the default CRUD operations by implementing custom command and query handlers in C#.
### Custom Commands
Create a class that implements `ILcCommand<TResult>` and decorate it with `[CustomCommand]`:
public class CustomProductCreateCommand : LcCommandBase<DynamicEntityDto>
{
public override async Task<DynamicEntityDto> ExecuteWithResultAsync(DynamicCommandArgs commandArgs)
{
// Your custom create logic here
// ...
}
}
````
| Parameter | Description |
|-----------|-------------|
| `commandName` | The command to replace: `"Create"`, `"Update"`, or `"Delete"` |
| `entityName` | Full entity name (e.g., `"MyApp.Products.Product"`) |
### Custom Queries
Create a class that implements `ILcQuery<TResult>` and decorate it with `[CustomQuery]`:
````csharp
[CustomQuery("List", "MyApp.Products.Product")]
public class CustomProductListQuery : ILcQuery<DynamicQueryResult>
{
public async Task<DynamicQueryResult> ExecuteAsync(DynamicQueryArgs queryArgs)
{
// Your custom list query logic here
// ...
}
}
````
| Parameter | Description |
|-----------|-------------|
| `queryName` | The query to replace: `"List"` or `"Single"` |
| `entityName` | Full entity name (e.g., `"MyApp.Products.Product"`) |
Custom commands and queries are automatically discovered and registered at startup. They completely replace the default handler for the specified entity and operation.
## Internals
@ -182,8 +250,12 @@ See [model.json Structure](model-json.md) for the full specification.
### Application Layer
* `DynamicEntityAppService`: CRUD operations for all dynamic entities.
* `DynamicEntityUIAppService`: UI definitions, menu items, and page configurations.
* `DynamicEntityAppService`: CRUD operations for all dynamic entities (Get, GetList, Create, Update, Delete, Export).
* `DynamicEntityUIAppService`: UI definitions, menu items, and page configurations. Provides:
| `max` | `maximum` | Numeric | Maximum numeric value |
> All validators accept an optional `message` parameter for a custom error message. The `regularExpression` validator also accepts the alias `pattern`, and `emailAddress` also accepts `email`.