SAIF.Presentation.Web.Binding.Infragistics111 architecture¶
SAIF.Presentation.Web.Binding.Infragistics111 implements SAIF's declarative "object binder" — a two-way data binding and validation framework that connects SAIF BOF business objects to ASP.NET WebForms and Infragistics 11.1 controls, with automatic error-message aggregation and error-state control formatting. Unlike its sibling presentation libraries, it has no compile-time reference to the SAIF BOF framework; it detects business objects purely by walking the runtime base-class chain for the names clsBusinessBase / clsBusinessCollectionBase.
Responsibilities¶
- Provide a page-level binding container (
clsObjectBindManager) that registers, initializes, validates, and synchronizes ~24 control-specific binders against business-object properties. - Define the binder contract (
clsObjectBinderBase) —Init,ObjectToControl,ControlToObject— shared reflection get/set helpers, padding support, andIDataErrorInfo-driven error harvesting. - Aggregate validation errors from bound business objects and application-supplied custom validators (
clsCustomValidator) into a single formatted message surfaced to an error label orSAIFMessagecontrol. - Supply strongly-typed binding-argument data contracts (
clsObjectBindingArgshierarchy,PadArgs) so applications can configure a binding without long positionalAddcalls.
Component boundaries¶
- Manager layer (
clsObjectBindManager, aSystem.Web.UI.Control): owns the binder collection, the validation-object dictionary, the aggregated error list, and the page-lifecycle hooks (OnLoad→ initialize binders,OnPreRender→ optional auto-bind). It is the library's only public entry point. - Binder abstraction layer (
clsObjectBinderBase): the three-method binder contract plus shared reflection, padding, and error-formatting behavior common to every concrete binder. - Binder implementation layer — 24 concrete binders split across ASP.NET controls, Infragistics classic (
WebUI) controls, and Infragistics current (Web.UI) controls, each knowing how to read/write its specific control property and which control event to subscribe to. - Argument/data-contract layer (
clsObjectBindingArgshierarchy,PadArgs): strongly-typed parameter objects for theAddoverloads. - Validation layer (
clsCustomValidatorplusPropertyValidator/MethodValidator/CustomValidatordelegates): application-supplied validation participating in the same error pipeline as property-level errors.
Interaction model¶
- A consuming page registers bindings during setup (
Configure/Page_Load) via one ofclsObjectBindManager's ~60Addoverloads; overload resolution on the control's compile-time type selects the matching concrete binder. - On
OnLoad, each binder'sInitwires up control change-event handlers (whenUseEventsisTrue). DataBind()(orPreRender-triggered auto-bind) pushes business-object property values into controls (ObjectToControl);BindToObject()pulls edited control values back onto business objects (ControlToObject), either on a control's change event or on demand.Validate()reads each bind source'sIsValidproperty (triggering BOF rule evaluation as a side effect†), then harvests per-property errors throughIDataErrorInfoand runs any registeredclsCustomValidatorchecks, aggregating distinct messages intoFormattedErrorMessage.- The library never references
SAIF.BOF.Frameworkat compile time:IsSAIFFrameWorkObject(duplicated inclsObjectBinderBaseandclsObjectBindManager) walks the bound object's runtime base-class chain looking for the type namesclsBusinessBaseorclsBusinessCollectionBase; when matched, the binder reads that object'sMyGuidproperty (aSAIF.Framework.Coremember†) as the validation key.
Architecture diagram¶
The following diagram shows one full page cycle through the binder.
flowchart TD
A["Page Configure/Load<br>binder.Add(control, object, property, bindType)"] --> B["clsObjectBindManager<br>m_Bindings + m_ValidationObjects"]
B --> C["OnLoad: Binder.Init()<br>subscribe to control change events"]
C --> D{"BindType"}
D -->|ObjectToControl or TwoWay| E["DataBind()<br>Binder.ObjectToControl()"]
E --> F["Control shows object value"]
F --> G["User edits control"]
G --> H{"UseEvents?"}
H -->|Yes| I["Change event handler<br>ControlToObject()"]
H -->|No| J["BindToObject()<br>ControlToObject()"]
I --> K["Business object property updated"]
J --> K
K --> L["Validate()"]
L --> M["ValidateBindSources()<br>read IsValid on each bind source"]
L --> N["Binder.GetErrors()<br>IDataErrorInfo.Item(property)"]
L --> O["clsCustomValidator.PerformValidation()"]
N --> P["Aggregate distinct messages<br>SetControlFormat(False)"]
O --> P
P --> Q["ErrorLabel.Text / SAIFMessage.Text<br>= FormattedErrorMessage"]
Sequence diagram¶
The following diagram shows the primary validate/error-aggregation sequence.
sequenceDiagram
participant Page
participant Manager as clsObjectBindManager
participant Binder as clsObjectBinderBase
participant BizObj as Bound business object
Page->>Manager: Validate()
Manager->>BizObj: Read IsValid (per bind source)
BizObj-->>Manager: rule evaluation side effect
Manager->>Binder: GetErrors()
Binder->>BizObj: IDataErrorInfo.Item(property)
BizObj-->>Binder: Error message(s)
Binder-->>Manager: Aggregated errors
Manager->>Manager: SetControlFormat(False)
Manager-->>Page: FormattedErrorMessage
Design constraints¶
- No compile-time dependency on
SAIF.BOF.Frameworkexists; business-object detection is purely behavioral (base-class name matching), so this library's correctness depends on the naming convention ofclsBusinessBase/clsBusinessCollectionBaseremaining stable inSAIF.Framework.Core†. - The library performs no data access, configuration, or security logic of its own; it is a pure in-memory presentation/binding layer between controls and whatever business object the caller supplies.
- Error messages are concatenated into
FormattedErrorMessagewithout HTML encoding — a potential XSS path if any bound business-rule message contains attacker-influenced text.* Validate()andRefreshValidation()share ~50 lines of duplicated logic; the only difference is thatRefreshValidationomits the bind-sourceIsValidread.clsObjectBinderBase.SetObjectValueAsStringcomputes a padded value but writes the object property from the unpadded value, soPadTarget.Objectpadding has no observable effect.
Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts. Statements marked with ** could not be confirmed; treat as unknown until verified. Statements marked with † were retrieved from a dependency library's own documentation via the Legends CLI RAG service.
Related documentation¶
Sources¶
SAIF.Presentation.Web.Binding.Infragistics111/clsObjectBindManager.vbSAIF.Presentation.Web.Binding.Infragistics111/clsObjectBinderbase.vbSAIF.Presentation.Web.Binding.Infragistics111/clsCustomValidator.vbSAIF.Presentation.Web.Binding.Infragistics111/clsObjectBindingArgs.vbSAIF.Presentation.Web.Binding.Infragistics111/Enums.vbSAIF.Presentation.Web.Binding.Infragistics111/SAIF.Presentation.Web.Binding.Infragistics111.vbproj