Skip to content

SAIF.Presentation architecture

SAIF.Presentation is a single-purpose presentation-tier library that provides a per-user, per-application/page preference (settings) store. It contains one functional class, clsPreferences (plus its supporting PrefScope enum), which mediates between calling UI code (web pages or Windows Forms) and the SAIF BOF data-access layer, delegating all persistence to SAIF.Framework.Preferences.PreferenceData.

Responsibilities

  • Cache all Preference groups for the authenticated portal user in memory on construction (Load() → PreferenceData.GetPreferencesForUser), scoped by application name and page name.
  • Provide scoped read/write access to preference key-value pairs via PrefScope.AppLevel, PrefScope.PageLevel, and PrefScope.WebLevel, exposed through the Item indexer and the Add/Remove/Clear/Delete members.
  • Resolve the "current page" identity using a dual strategy: parsing System.Web.HttpContext.Current.Request.Path in web contexts, or falling back to an explicit OverridePage value or System.Diagnostics.StackTrace reflection in non-web contexts*.
  • Persist in-memory preference changes back to the Oracle-backed PreferenceData store on explicit Save() calls, serializing each preference group's items to JSON via JavaScriptSerializer.
  • Resolve the Oracle connection target for its own persistence needs through the SAIF.Framework.Common environment-service abstraction (AppGlobal.EnvironmentService.GetConfigSetting(EnvironmentConfigKeys.OracleDatabase)), rather than reading configuration locally (see Configuration).

Component boundaries

  • clsPreferences: the sole public service boundary of this library — an in-memory preference cache plus a thin persistence-orchestration layer. It owns no SQL and implements no IBusinessCriteria pattern itself; all durable storage is delegated to the external PreferenceData type.
  • PrefScope: a public enum (AppLevel, PageLevel, WebLevel) that defines the boundary at which a preference key is stored/retrieved; it is the contract consumers use to select scoping behavior on every Item/Add/Remove/Clear call.
  • External boundary — SAIF.Framework.Preferences.PreferenceData/Preference: the actual persistence layer (Oracle-backed), consumed but not defined in this library; its internal SQL/BOF implementation is out of scope for this library**.
  • External boundary — SAIF.Framework.Common (clsMSOracleDataLayer, AppGlobal.EnvironmentService, EnvironmentConfigKeys): supplies the Oracle data-portal context (IDataPortalInfo) and configuration resolution used by Load().
  • Cross-cutting boundary — clsLogTrace (from SAIF.BOF.Framework): method-entry/exit tracing wrapped around Remove() and Save().

Interaction model

  • Consumers (web pages, Windows Forms, or other SAIF.Presentation.* libraries) construct a clsPreferences instance, supplying a user ID and application name; construction eagerly loads all preference groups for the authenticated data-portal user (m_DPI.UserID), not the constructor's inUserID parameter*.
  • Reads use the Item indexer (three overloads) to fetch a value scoped by application/page/key entirely from the in-memory _Preferences list — no database round-trip occurs on read.
  • Writes (Add, Remove, Clear, Delete) mutate only the in-memory list; nothing is written to the database until the consumer explicitly calls Save().
  • Save() persists only the preference groups whose ApplicationName matches the current m_Application, via PreferenceData.SavePreferences; its Boolean return value is not a reliable success indicator because of a dead-code path that always returns False*.
  • This library is consumed as a same-repo <ProjectReference> (its .vb source, not a compiled binary, is recompiled by each consumer per the package's nuspec) by four other libraries in this repository: SAIF.Presentation.Web.Core.Infragistics103, SAIF.Presentation.Web.MVC (clsModelBase, exposing a Preferences property backed by clsPreferences), SAIF.Presentation.Web.Controls.V2.Menu (SAIFMenu, using PrefScope.AppLevel to persist a SHOWAPPS menu preference), and SAIF.Presentation.Web.Controls.AJAX.Infragistics103 (InfragisticsGridCustomizer, resolving a clsPreferences instance via BindingUtility.GetObject).

Architecture diagram

The following diagram shows how consumer libraries obtain and use the clsPreferences service, and how it delegates persistence downstream.

flowchart TD
    A[SAIF.Presentation.Web.MVC<br>clsModelBase] --> D[clsPreferences]
    B[SAIF.Presentation.Web.Controls.V2.Menu<br>SAIFMenu] --> D
    C[SAIF.Presentation.Web.Controls.AJAX.Infragistics103<br>InfragisticsGridCustomizer] --> D
    D --> E[PreferenceData<br>SAIF.Framework.Preferences]
    D --> F[clsMSOracleDataLayer<br>SAIF.Framework.Common]
    F --> G[AppGlobal.EnvironmentService<br>GetConfigSetting]
    E --> H[(Oracle DB<br>DB user CLM)]

Sequence diagram

The following diagram shows the primary construct-read-write-save sequence for a preference consumer.

sequenceDiagram
    participant Consumer
    participant clsPreferences
    participant PreferenceData
    participant OracleDB
    Consumer->>clsPreferences: New(userId, application)
    clsPreferences->>PreferenceData: GetPreferencesForUser(m_DPI.UserID)
    PreferenceData->>OracleDB: Query preferences (CLM schema)
    OracleDB-->>PreferenceData: Preference rows
    PreferenceData-->>clsPreferences: List(Of Preference)
    Consumer->>clsPreferences: Add(key, value, scope)
    Note over clsPreferences: In-memory mutation only
    Consumer->>clsPreferences: Save()
    clsPreferences->>PreferenceData: SavePreferences(app, page, userId, json)
    PreferenceData->>OracleDB: Persist preference JSON
    clsPreferences-->>Consumer: Boolean (always False)*

Design constraints

  • The library has zero <ProjectReference> dependencies of its own — it is a leaf/foundational presentation utility, but four other libraries in this repository depend on it via project reference, so its public surface (clsPreferences, PrefScope) is a de facto internal contract.
  • All persistence is hard-wired to Oracle under the fixed DB user "CLM" (m_DBUserName), independent of which consuming application constructs the instance — this couples every consumer to the same database schema/user context.
  • The only externalized configuration touchpoint is the Oracle connection setting EnvironmentConfigKeys.OracleDatabase, resolved via AppGlobal.EnvironmentService.GetConfigSetting; the library defines no App.config/Web.config and reads no AppSettings directly.
  • Save()'s boolean return value cannot be trusted to detect failure (dead code after Return result); only a thrown ApplicationException signals a save error*.
  • The 3-argument constructor's XML documentation describes file-based storage via a preferencesRootDirectory parameter, but the parameter is accepted and ignored — the live implementation always loads from the Oracle-backed PreferenceData, so the documented and actual behavior diverge*.
  • This project's compiled binary is not what ships in the SAIF.BOF.Presentation.Web.Infragistics103 NuGet package; only its .vb source is bundled (per the root .nuspec) for consumers to recompile alongside SAIF.Presentation.Web.Core.Infragistics103's compiled output*.

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.

Sources

  • SAIF.Presentation\clsPreferences.vb
  • SAIF.Presentation\SAIF.Presentation.vbproj
  • SAIF.Presentation\packages.config
  • SAIF.Presentation.Web.MVC\clsModelBase.vb
  • SAIF.Presentation.Web.Controls.V2.Menu\SAIFMenu.vb
  • SAIF.Presentation.Web.Controls.AJAX.Infragistics103\InfragisticsGridCustomizer.vb
  • SAIF.BOF.Presentation.Web.Infragistics103.nuspec