diff --git a/docs/en/low-code/model-json.md b/docs/en/low-code/model-json.md index ce59b0b3ec..2c11503553 100644 --- a/docs/en/low-code/model-json.md +++ b/docs/en/low-code/model-json.md @@ -362,9 +362,10 @@ Forms are named definitions referenced by pages through `formName`, `createFormN "id": "details", "title": "Details", "isDefault": true, - "rows": [ - { "cells": [{ "fieldId": "name", "colSpan": 4 }] }, - { "cells": [{ "fieldId": "status", "colSpan": 2 }, { "fieldId": "ownerId", "colSpan": 2 }] } + "fields": [ + { "fieldId": "name", "row": 0, "colSpan": 4 }, + { "fieldId": "status", "row": 1, "colSpan": 2 }, + { "fieldId": "ownerId", "row": 1, "colSpan": 2 } ] } ] @@ -526,10 +527,12 @@ The complete example below shows the logical aggregate shape. Split projects sto "id": "details", "title": "Details", "isDefault": true, - "rows": [ - { "cells": [{ "fieldId": "name", "colSpan": 4 }] }, - { "cells": [{ "fieldId": "status", "colSpan": 2 }, { "fieldId": "budget", "colSpan": 2 }] }, - { "cells": [{ "fieldId": "startDate", "colSpan": 2 }, { "fieldId": "coverImage", "colSpan": 2 }] } + "fields": [ + { "fieldId": "name", "row": 0, "colSpan": 4 }, + { "fieldId": "status", "row": 1, "colSpan": 2 }, + { "fieldId": "budget", "row": 1, "colSpan": 2 }, + { "fieldId": "startDate", "row": 2, "colSpan": 2 }, + { "fieldId": "coverImage", "row": 2, "colSpan": 2 } ] } ] diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbpDynamicSortingGuard.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbpDynamicSortingGuard.cs index 25f7f72439..2f67547b0b 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbpDynamicSortingGuard.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbpDynamicSortingGuard.cs @@ -16,9 +16,11 @@ namespace Volo.Abp.Application.Services; /// constrained to plain property or field access. Methods, comparisons, ternaries /// and constants in the sort key are rejected with . /// Property-bag / shadow-property access through a constant string indexer -/// (e.g. it["Prop"], Data["Prop"]) is treated as plain property access -/// and allowed, since it carries no side effects and is the canonical way to sort -/// dynamically-mapped entities. +/// (e.g. it["Prop"], Data["Prop"]) is treated like plain property +/// access and allowed, because it is the canonical way to sort dynamically-mapped +/// entities. The guard assumes the matching indexer getter behaves like a property +/// getter; defining an indexer that performs IO or mutates state will expose those +/// effects through sorting. /// internal static class AbpDynamicSortingGuard { @@ -88,9 +90,10 @@ internal static class AbpDynamicSortingGuard protected override Expression VisitMethodCall(MethodCallExpression node) { // Allow property-bag / shadow-property access through a constant string - // indexer (it["Prop"], Data["Prop"], mainEntity["Prop"], ...). This is a - // pure read of a named member, not an arbitrary method invocation, so it - // does not open the injection surface the guard protects against. + // indexer (it["Prop"], Data["Prop"], mainEntity["Prop"], ...). The + // constant key cannot smuggle in an arbitrary method invocation, so this + // does not widen the injection surface the guard protects against; it + // treats the indexer access like ordinary property access. if (IsConstantStringIndexer(node)) { if (node.Object != null) diff --git a/schemas/low-code/definitions/form-descriptor.schema.json b/schemas/low-code/definitions/form-descriptor.schema.json index 3508ff58a9..102193ee10 100644 --- a/schemas/low-code/definitions/form-descriptor.schema.json +++ b/schemas/low-code/definitions/form-descriptor.schema.json @@ -34,7 +34,7 @@ }, "layout": { "$ref": "form-layout-descriptor.schema.json", - "description": "Visual layout for the fields. Every layout cell fieldId must refer to a field in fields." + "description": "Visual layout for the fields. Every layout placement fieldId must refer to a field in fields." }, "rules": { "type": "array",