Skip to content

SAIF.Presentation.Web.MVC architecture

SAIF.Presentation.Web.MVC supplies the shared base-class framework for a "poor-man's MVC" pattern layered on classic ASP.NET WebForms, used across SAIF's legacy front-end applications. It does not implement ASP.NET MVC (no routing, no Controller/ActionResult types); instead it retrofits Model/View/Controller/Factory roles onto WebForms Page/UserControl classes and adds cross-application session/context hand-off, menu-driven authorization, and centralized error handling.

Responsibilities

  • Orchestrate the WebForms page/control request lifecycle (clsControllerBase.Initialize/CallRetrieve/UnInitialize) on behalf of concrete controllers supplied by each consuming application.
  • Enforce two authorization gates on every request: authenticated-principal presence (SecurityCheck) and menu-driven page authorization (RedirectUnauthorizedUsers via NavigationContext) — see Security and authorization.
  • Persist and retrieve cross-application "context" hand-off values (claim ID, policy number, SAIF claim number, provider location sequence number) in a SQL Server Context table so a user's in-flight state survives navigation between separate SAIF web applications — see Database tables and SQL catalog.
  • Provide an abstract clsModelBase/clsFactoryBase contract that consuming applications implement to supply concrete models, controllers, and validation/write behavior.
  • Centralize unhandled-exception routing (ViewPageBase.ProcessError/clsControllerBase.HandleErrors), including SAIF-exception-type dispatch, logging, and redirect to a configurable error page.
  • Resolve environment- and deployment-specific settings (SQL Server/Oracle connection keys, trace toggles, error-page overrides, ViewState-in-session behavior) through the Environment API and Web.config <appSettings> — see Configuration.

Component boundaries

  • ViewPageBase / ViewControlBase — View layer: WebForms Page/UserControl code-behind base classes; own the ASP.NET page lifecycle events (Page_Init, Page_Load, Page_PreRender, Page_Unload, Page_Error) and delegate all non-rendering behavior to a clsControllerBase instance obtained from a clsFactoryBase. ViewPageBase also owns ViewState-in-session persistence (PageStatePersister) and Infragistics-control-aware client focus scripting (NavigationManager nested class, reflection-only coupling — no compile-time Infragistics.* reference).
  • clsControllerBase — Controller layer: orchestrates security checks, NavigationContext construction/caching in Session("navdata"), cross-application context hand-off (CheckContext/Navigate/Navigate2), and error handling. It is the central coordination boundary between the View and Model layers.
  • clsModelBase — Model layer (abstract): holds a clsContext and clsPreferences reference, defines the ValidateData/WriteData contract invoked by the Write() template method, and exposes shared input-validation helpers. Concrete models are implemented entirely by consuming applications; this library defines only the contract.
  • clsFactoryBase — Factory abstraction (abstract): lets each consuming application supply its own concrete Controller/Model pair via GetController()/GetModel(), decoupling ViewPageBase/ViewControlBase from any specific application's concrete types.
  • clsContext / clsOnlineContext — cross-request/cross-application state-transfer boundary: a plain (non-BOF-criteria) class whose private nested clsContextRepository/clsSQL perform direct ADO.NET SQL Server access against the Context table. clsOnlineContext is a thin subclass fixing ApplicationName = "Online".
  • NavigationContext — menu-authorization lookup boundary: wraps SAIF.Business.Menu collections (clsMenuAuthorizedItemCollection, clsApplicationCodeCollection, clsMenuCategoryCodeCollection), sourced through an Oracle data layer (clsMSOracleDataLayer) constructed in this library, to answer "is this page authorized for this user" queries.

Interaction model

  • A request enters through ViewPageBase.Page_Init, which asks the concrete clsFactoryBase.GetController() for a controller instance and calls clsControllerBase.Initialize().
  • Initialize() performs, in order: session-timeout redirect check, SecurityCheck() (principal presence/NTLM challenge), lazy construction/reuse of NavigationContext in Session("navdata"), RedirectUnauthorizedUsers() (menu-based page gate), Model.Pre_Init(), the overridable Load() hook, query-string processing, and — if a referrer is present — CheckContext() for cross-application state hand-off.
  • ViewPageBase.Page_Load calls clsControllerBase.CallRetrieve(), which reflects over page controls and invokes the concrete controller's abstract Retrieve(controls, targetView) hook.
  • ViewPageBase.Page_PreRender triggers client-focus script generation (NavigationManager.GenerateScripts) and optional trace output.
  • ViewPageBase.Page_Unload calls clsControllerBase.UnInitialize(), persisting Model and ViewData into Session.
  • ViewPageBase.Page_Error calls ProcessError(), which dispatches on SAIF-exception type (via reflection on the runtime type name clsSAIFException) or falls through to clsControllerBase.HandleErrors() for logging, emailing, and redirect to a central error page.
  • Cross-application navigation (Navigate/Navigate2) persists context values to the shared SQL Server Context table (delete-then-insert) when navigating to a different application, or reuses the in-session ViewID when navigating within the same application (see BR-MVC-005).
  • The Write() template method on clsModelBase only invokes the concrete WriteData() if the concrete ValidateData() returns True (see BR-MVC-006).

Architecture diagram

The following diagram shows the layered component structure and where it crosses out to external databases and the consuming application's concrete types.

flowchart TD
    View["ViewPageBase / ViewControlBase<br>(View layer)"] --> Factory["clsFactoryBase<br>(Factory, abstract)"]
    Factory --> Controller["clsControllerBase<br>(Controller layer)"]
    Controller --> Model["clsModelBase<br>(Model layer, abstract)"]
    Controller --> Nav["NavigationContext<br>(menu authorization)"]
    Controller --> Ctx["clsContext / clsOnlineContext<br>(cross-app state transfer)"]
    Model --> Prefs["clsPreferences<br>SAIF.Presentation"]
    Nav --> MenuLib["SAIF.Business.Menu<br>clsMenuAuthorizedItemCollection etc."]
    Nav --> OracleLayer["clsMSOracleDataLayer<br>SAIF.Framework.Common"]
    OracleLayer --> OracleDB[("Oracle DB<br>menu/authorization data")]
    Ctx --> SqlServerDB[("SQL Server<br>Context table<br>catalog NETFRAMEWORK")]
    Controller --> ErrorLog["clsLogError / clsLogTrace<br>SAIF.BOF.Framework"]

Sequence diagram

The following diagram shows the request lifecycle through the base classes, including the authorization gates and the cross-application context store.

sequenceDiagram
    participant Browser
    participant ViewPageBase
    participant clsControllerBase
    participant clsFactoryBase
    participant ConcreteModel as clsModelBase (concrete)
    participant NavigationContext
    participant Context as clsContext (Context table)

    Browser->>ViewPageBase: HTTP request
    ViewPageBase->>clsFactoryBase: GetController()
    clsFactoryBase-->>ViewPageBase: clsControllerBase instance
    ViewPageBase->>clsControllerBase: Initialize()
    clsControllerBase->>clsControllerBase: SecurityCheck()
    clsControllerBase->>NavigationContext: new NavigationContext(UserID)
    clsControllerBase->>NavigationContext: IsMenuItem(app, page)
    NavigationContext-->>clsControllerBase: authorized true/false
    clsControllerBase->>ConcreteModel: Pre_Init()
    clsControllerBase->>Context: CheckContext() / RetrieveContext()
    ViewPageBase->>clsControllerBase: CallRetrieve()
    clsControllerBase->>ConcreteModel: Retrieve(controls, targetView)
    ViewPageBase->>clsControllerBase: UnInitialize()
    clsControllerBase->>Browser: Session(Model, ViewData) persisted

Design constraints

  • No ASP.NET MVC routing or Controller/ActionResult types are used; the "MVC" naming is a role-based retrofit onto WebForms, and concrete Retrieve, HandleContext, HandleQuerystring, ValidateData, and WriteData behavior lives entirely in downstream consuming applications, not in this library.**
  • Authorization is coarse-grained and local/programmatic — no [SAIFAuthorize] attributes, no WCF SecurityService client, and no direct AD group checks exist in this library; page-level access is gated by database-provisioned menu entries (SAIF.Business.Menu) rather than named AD resources. See Security and authorization.
  • Cross-application state hand-off depends on a directly-owned SQL Server dependency: clsContext's private clsContextRepository opens raw SqlConnection/SqlCommand objects against a Context table in the NETFRAMEWORK catalog, resolved via EnvironmentConfigKeys.NetFrameworkSqlServer — this is not the standard BOF IBusinessCriteria pattern used elsewhere in SAIF. See Database tables and SQL catalog.
  • NavigationContext introduces an indirect Oracle dependency (EnvironmentConfigKeys.OracleDatabase via clsMSOracleDataLayer) for menu/authorization data, meaning this library's request pipeline depends on the availability of two separate database engines (SQL Server for context hand-off, Oracle for menu authorization) on every authorized request.
  • Session-timeout and internal-address classification hard-codes network literals (10.*, 131.131.*.*, 127.0.0.1) directly in clsControllerBase's local IsInsideClient property, coupling the session-timeout/ViewState-persistence behavior to the SAIF internal network topology (see BR-MVC-008). The unauthenticated HTTP 401 vs. deny outcome in SecurityCheck() is instead gated by the separate external clsEnvironment.InternalAddress dependency (see Security and authorization).
  • All environment-varying configuration is resolved through the plain-text GetConfigSetting Environment API — no GetSecureConfigSetting/SystemHashUtil.ComputeHash calls exist in this library, so the SQL Server and Oracle connection keys it resolves are not treated as secure settings. See Configuration.
  • The .aspx/.ascx markup files declare Inherits="SAIF.ViewPageBase"/Inherits="SAIF.ViewControlBase" (namespace SAIF), inconsistent with the project's actual root namespace (SAIF.Presentation.Web.MVC); this suggests the markup is legacy scaffolding not served directly, with real markup living in each consuming application.**
  • Per the root .nuspec, this library contributes source (.vb files), not a compiled binary, to the SAIF.BOF.Presentation.Web.Infragistics103 NuGet package; the compiled binary shipped in that package is built from SAIF.Presentation.Web.Core.Infragistics103.*

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.Web.MVC\clsContext.vb
  • SAIF.Presentation.Web.MVC\clsOnlineContext.vb
  • SAIF.Presentation.Web.MVC\clsControllerBase.vb
  • SAIF.Presentation.Web.MVC\clsFactoryBase.vb
  • SAIF.Presentation.Web.MVC\clsModelBase.vb
  • SAIF.Presentation.Web.MVC\NavigationContext.vb
  • SAIF.Presentation.Web.MVC\ViewControlBase.ascx.vb
  • SAIF.Presentation.Web.MVC\ViewPageBase.aspx.vb
  • SAIF.Presentation.Web.MVC\SAIF.Presentation.Web.MVC.vbproj
  • SAIF.BOF.Presentation.Web.Infragistics103.nuspec