diff --git a/docs/en/images/quick-look.png b/docs/en/images/quick-look.png new file mode 100644 index 0000000000..50b5725d4e Binary files /dev/null and b/docs/en/images/quick-look.png differ diff --git a/docs/en/low-code/fluent-api.md b/docs/en/low-code/fluent-api.md index 1d122963c1..ab98e6f636 100644 --- a/docs/en/low-code/fluent-api.md +++ b/docs/en/low-code/fluent-api.md @@ -16,7 +16,7 @@ C# Attributes and the Fluent API are the **recommended way** to define dynamic e ````csharp [DynamicEntity] [DynamicEntityUI(PageTitle = "Products")] -public class Product +public class Product : DynamicEntityBase { [DynamicPropertyUnique] public string Name { get; set; } @@ -30,18 +30,7 @@ public class Product } ```` -### Step 2: Register the Assembly - -````csharp -public override void ConfigureServices(ServiceConfigurationContext context) -{ - AbpDynamicEntityConfig.SourceAssemblies.Add( - new DynamicEntityAssemblyInfo(typeof(YourDomainModule).Assembly) - ); -} -```` - -### Step 3: Add Migration and Run +### Step 2: Add Migration and Run ```bash dotnet ef migrations add Added_Product @@ -50,12 +39,12 @@ dotnet ef database update You now have a complete Product management page with data grid, create/edit modals, search, sorting, and pagination. -### Step 4: Add Relationships +### Step 3: Add Relationships ````csharp [DynamicEntity] [DynamicEntityUI(PageTitle = "Orders")] -public class Order +public class Order : DynamicEntityBase { [DynamicForeignKey("MyApp.Customers.Customer", "Name", ForeignAccess.Edit)] public Guid CustomerId { get; set; } @@ -65,7 +54,7 @@ public class Order } [DynamicEntity(Parent = "MyApp.Orders.Order")] -public class OrderLine +public class OrderLine : DynamicEntityBase { [DynamicForeignKey("MyApp.Products.Product", "Name")] public Guid ProductId { get; set; } @@ -97,7 +86,7 @@ Marks a class as a dynamic entity. The entity name is derived from the class nam ````csharp [DynamicEntity] -public class Product +public class Product : DynamicEntityBase { public string Name { get; set; } public decimal Price { get; set; } @@ -108,7 +97,7 @@ Use the `Parent` property for parent-child (master-detail) relationships: ````csharp [DynamicEntity(Parent = "MyApp.Orders.Order")] -public class OrderLine +public class OrderLine : DynamicEntityBase { public Guid ProductId { get; set; } public int Quantity { get; set; } @@ -122,7 +111,7 @@ Configures entity-level UI. Entities with `PageTitle` get a menu item and a dedi ````csharp [DynamicEntity] [DynamicEntityUI(PageTitle = "Product Management")] -public class Product +public class Product : DynamicEntityBase { // ... } @@ -215,7 +204,7 @@ Defines JavaScript interceptors on a class for CRUD lifecycle hooks: InterceptorType.Post, "context.log('Deleted: ' + context.commandArgs.entityId);" )] -public class Organization +public class Organization : DynamicEntityBase { public string Name { get; set; } } @@ -245,7 +234,7 @@ Reference in an entity: ````csharp [DynamicEntity] [DynamicEntityUI(PageTitle = "Organizations")] -public class Organization +public class Organization : DynamicEntityBase { public string Name { get; set; } public OrganizationType OrganizationType { get; set; } @@ -276,28 +265,38 @@ The Fluent API has the **highest priority** in the configuration system. Use `Ab ### Basic Usage -Configure in your Domain module's `ConfigureServices`: +Configure in your Low-Code Initializer (e.g. `MyAppLowCodeInitializer`): ````csharp -public override void ConfigureServices(ServiceConfigurationContext context) +public static class MyAppLowCodeInitializer { - AbpDynamicEntityConfig.EntityConfigurations.Configure( - "MyApp.Products.Product", - entity => - { - entity.DefaultDisplayPropertyName = "Name"; + private static readonly AsyncOneTimeRunner Runner = new(); - var priceProperty = entity.AddOrGetProperty("Price"); - priceProperty.AsRequired(); - priceProperty.UI = new EntityPropertyUIDescriptor - { - DisplayName = "Unit Price", - CreationFormAvailability = EntityPropertyUIFormAvailability.Available - }; + public static async Task InitializeAsync() + { + await Runner.RunAsync(async () => + { + AbpDynamicEntityConfig.EntityConfigurations.Configure( + "MyApp.Products.Product", + entity => + { + entity.DefaultDisplayPropertyName = "Name"; + + var priceProperty = entity.AddOrGetProperty("Price"); + priceProperty.AsRequired(); + priceProperty.UI = new EntityPropertyUIDescriptor + { + DisplayName = "Unit Price", + CreationFormAvailability = EntityPropertyUIFormAvailability.Available + }; + + entity.AddOrGetProperty("InternalNotes").AsServerOnly(); + } + ); - entity.AddOrGetProperty("InternalNotes").AsServerOnly(); - } - ); + await DynamicModelManager.Instance.InitializeAsync(); + }); + } } ```` @@ -439,7 +438,7 @@ public enum OrderStatus // Customer entity [DynamicEntity] [DynamicEntityUI(PageTitle = "Customers")] -public class Customer +public class Customer : DynamicEntityBase { [DynamicPropertyUnique] public string Name { get; set; } @@ -457,7 +456,7 @@ public class Customer // Product entity [DynamicEntity] [DynamicEntityUI(PageTitle = "Products")] -public class Product +public class Product : DynamicEntityBase { [DynamicPropertyUnique] public string Name { get; set; } @@ -478,7 +477,7 @@ public class Product } }" )] -public class Order +public class Order : DynamicEntityBase { [DynamicForeignKey("MyApp.Customers.Customer", "Name", ForeignAccess.Edit)] public Guid CustomerId { get; set; } @@ -489,7 +488,7 @@ public class Order } [DynamicEntity(Parent = "MyApp.Orders.Order")] -public class OrderLine +public class OrderLine : DynamicEntityBase { [DynamicForeignKey("MyApp.Products.Product", "Name")] public Guid ProductId { get; set; }