Open Source Web Application Framework for ASP.NET Core
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

9.6 KiB

//[doc-seo]
{
    "Description": "Define dynamic entities using model.json in the ABP Low-Code Module. Learn about entity properties, enums, foreign keys, validators, UI configuration, and migration requirements."
}

model.json Structure

The model.json file defines all your dynamic entities, their properties, enums, relationships, interceptors, custom endpoints, and UI configurations. It is an alternative configuration source to C# Attributes and Fluent API, ideal when you prefer a declarative JSON approach.

File Location

Place your model.json in a _Dynamic folder inside your Domain project:

YourApp.Domain/
└── _Dynamic/
    └── model.json

The module automatically discovers and loads this file at application startup.

A JSON Schema file (model.schema.json) is available in the module source for IDE IntelliSense. Reference it using the $schema property:

{
  "$schema": "path/to/model.schema.json",
  "entities": []
}

Top-Level Structure

The model.json file has three root sections:

{
  "$schema": "...",
  "enums": [],
  "entities": [],
  "endpoints": []
}
Section Description
enums Enum type definitions
entities Entity definitions with properties, foreign keys, interceptors, and UI
endpoints Custom REST API endpoints with JavaScript handlers

Enum Definitions

Define enums that can be used as property types:

{
  "enums": [
    {
      "name": "LowCodeDemo.Organizations.OrganizationType",
      "values": [
        { "name": "Corporate", "value": 0 },
        { "name": "Enterprise", "value": 1 },
        { "name": "Startup", "value": 2 },
        { "name": "Consulting", "value": 3 }
      ]
    }
  ]
}

Reference enums in entity properties using the enumType field:

{
  "name": "OrganizationType",
  "enumType": "LowCodeDemo.Organizations.OrganizationType"
}

Entity Definition

Each entity has the following structure:

{
  "name": "LowCodeDemo.Products.Product",
  "displayProperty": "Name",
  "parent": null,
  "properties": [],
  "foreignKeys": [],
  "interceptors": [],
  "ui": {}
}

Entity Attributes

Attribute Type Description
name string Required. Full entity name with namespace (e.g., "MyApp.Products.Product")
displayProperty string Property to display in lookups and foreign key dropdowns
parent string Parent entity name for parent-child (master-detail) relationships
properties array Property definitions
interceptors array CRUD lifecycle interceptors
ui object UI configuration

Parent-Child Relationships

Use the parent field to create nested entities. Children are managed through the parent entity's UI:

{
  "name": "LowCodeDemo.Orders.OrderLine",
  "parent": "LowCodeDemo.Orders.Order",
  "properties": [
    {
      "name": "ProductId",
      "foreignKey": {
        "entityName": "LowCodeDemo.Products.Product"
      }
    },
    { "name": "Quantity", "type": "int" },
    { "name": "Amount", "type": "decimal" }
  ]
}

Multi-level nesting is supported (e.g., Order > OrderLine > ShipmentItem > ShipmentTracking).

Property Definition

{
  "name": "Price",
  "type": "decimal",
  "isRequired": true,
  "isUnique": false,
  "isMappedToDbField": true,
  "serverOnly": false,
  "allowSetByClients": true,
  "enumType": null,
  "foreignKey": null,
  "validators": [],
  "ui": {}
}

Property Types

Type Description
string Text (default if type is omitted)
int 32-bit integer
long 64-bit integer
decimal Decimal number
DateTime Date and time
boolean True/false
Guid GUID/UUID
Enum Enum type (requires enumType field)

Property Flags

Flag Type Default Description
isRequired bool false Property must have a value
isUnique bool false Value must be unique across all records
isMappedToDbField bool true Property is stored in the database
serverOnly bool false Property is hidden from API clients
allowSetByClients bool true Whether clients can set this value

Foreign Key Properties

Define a foreign key relationship inline on a property:

{
  "name": "CustomerId",
  "foreignKey": {
    "entityName": "LowCodeDemo.Customers.Customer",
    "displayPropertyName": "Name",
    "access": "edit"
  }
}
Attribute Description
entityName Required. Full name of the referenced entity
displayPropertyName Property to display in lookups (defaults to entity's displayProperty)
access Foreign access level: "none", "view", or "edit"

Validators

Add validation rules to properties:

{
  "name": "EmailAddress",
  "validators": [
    { "type": "required" },
    { "type": "emailAddress" },
    { "type": "minLength", "length": 5 },
    { "type": "maxLength", "length": 255 }
  ]
}
Validator Parameters Description
required Value is required
minLength length Minimum string length
maxLength length Maximum string length
emailAddress Must be a valid email
range min, max Numeric range

UI Configuration

Entity-Level UI

{
  "ui": {
    "pageTitle": "Products"
  }
}

Only entities with ui.pageTitle get a menu item and a dedicated page in the UI.

Property-Level UI

{
  "name": "RegistrationNumber",
  "ui": {
    "displayName": "Registration Number",
    "isAvailableOnDataTable": true,
    "isAvailableOnDataTableFiltering": true,
    "creationFormAvailability": "Hidden",
    "editingFormAvailability": "NotAvailable",
    "quickLookOrder": 100
  }
}
Attribute Type Default Description
displayName string Property name Display label in UI
isAvailableOnDataTable bool true Show in data grid
isAvailableOnDataTableFiltering bool true Show in filter panel
creationFormAvailability string "Available" Visibility in create form
editingFormAvailability string "Available" Visibility in edit form
quickLookOrder int -2 Order in quick-look panel (-2 = not shown)

Form Availability Values

Value Description
Available Visible and editable
Hidden Not visible in the form
NotAvailable Visible but disabled/read-only

Interceptors

Define JavaScript interceptors for CRUD lifecycle hooks:

{
  "interceptors": [
    {
      "commandName": "Create",
      "type": "Pre",
      "javascript": "if(!context.commandArgs.data['Name']) { globalError = 'Name is required!'; }"
    }
  ]
}

See Interceptors for details.

Endpoints

Define custom REST endpoints with JavaScript handlers:

{
  "endpoints": [
    {
      "name": "GetProductStats",
      "route": "/api/custom/products/stats",
      "method": "GET",
      "requireAuthentication": false,
      "javascript": "var count = await db.count('Products.Product'); return ok({ total: count });"
    }
  ]
}

See Custom Endpoints for details.

Complete Example

{
  "enums": [
    {
      "name": "ShipmentStatus",
      "values": [
        { "name": "Pending", "value": 0 },
        { "name": "Shipped", "value": 2 },
        { "name": "Delivered", "value": 4 }
      ]
    }
  ],
  "entities": [
    {
      "name": "LowCodeDemo.Products.Product",
      "displayProperty": "Name",
      "properties": [
        { "name": "Name", "isUnique": true, "isRequired": true },
        { "name": "Price", "type": "decimal" },
        { "name": "StockCount", "type": "int" },
        { "name": "ReleaseDate", "type": "DateTime" }
      ],
      "ui": { "pageTitle": "Products" }
    },
    {
      "name": "LowCodeDemo.Orders.Order",
      "displayProperty": "Id",
      "properties": [
        {
          "name": "CustomerId",
          "foreignKey": {
            "entityName": "LowCodeDemo.Customers.Customer",
            "access": "edit"
          }
        },
        { "name": "TotalAmount", "type": "decimal" },
        { "name": "IsDelivered", "type": "boolean" }
      ],
      "interceptors": [
        {
          "commandName": "Create",
          "type": "Post",
          "javascript": "context.log('Order created: ' + context.commandArgs.entityId);"
        }
      ],
      "ui": { "pageTitle": "Orders" }
    },
    {
      "name": "LowCodeDemo.Orders.OrderLine",
      "parent": "LowCodeDemo.Orders.Order",
      "properties": [
        {
          "name": "ProductId",
          "foreignKey": { "entityName": "LowCodeDemo.Products.Product" }
        },
        { "name": "Quantity", "type": "int" },
        { "name": "Amount", "type": "decimal" }
      ]
    }
  ]
}

Migration Requirements

When you modify model.json, you need database migrations for the changes to take effect:

  • New entity: dotnet ef migrations add Added_{EntityName}
  • New property: dotnet ef migrations add Added_{PropertyName}_To_{EntityName}
  • Type change: dotnet ef migrations add Changed_{PropertyName}_In_{EntityName}

The same migration requirement applies when using C# Attributes. Any change to entity structure requires an EF Core migration.

See Also