Skip to content

Navigate to a view

The single navigation primitive used by every SAIF WebForms screen to move the user to another view. It decides whether the target is same-app or cross-app, persists hand-off context to the SQL Server Context table only for genuine cross-application transitions, and either redirects or opens a popup window.

Field Value
Operation ID OP-MVC-04
Trigger Derived controller decides to leave the current view; also used by ViewPageBase.ProcessError
Inputs TargetApp, TargetView, popup options, optional new model GUID
Outputs Context rows saved to SQL Server (cross-app case), a session __SAIFPID entry (same-app case), and either a redirect or a popup script
Primary components clsControllerBase.Navigate
Entry point SAIF.Presentation.Web.MVC/clsControllerBase.vb

Steps

  1. Read SourceApp from Request.ApplicationPath (leading / stripped).
  2. If TargetApp starts with HTTP (case-insensitive) or /, treat it as an absolute target; otherwise build /<TargetApp>/<TargetView> (BR-MVC-009).
  3. Store targetView, targetApp, sourceApp, and sourceView into the model context (BR-MVC-010).
  4. If source and target applications differ:
  5. When SupportsMultiModel, also store the current ViewID under __SAIFPID (BR-MVC-008).
  6. Unless the session has timed out, call Model.Context.SaveContext(Session.SessionID) to persist the context rows (BR-MVC-010, BR-MVC-011).

Origin: Steps 4.1–4.2 are implemented in Persist context rows (clsContext.SaveContext, this library) and executed on behalf of this operation. - If the session has timed out: context is not saved — no persistence occurs on this transition. 5. If source and target applications match, add __SAIFPID to session holding either the supplied new-model GUID or the current ViewID (BR-MVC-008). 6. If Popup, register a startup script that opens window.open(target, windowName, features) and focuses either the child (MyWin.focus()) or the opener (window.focus()) (BR-MVC-013). 7. Otherwise Response.Redirect(NavTarget) (BR-MVC-012). - On failure: any exception is swallowed with Thread.ResetAbort() and Response.End() runs in Finally. - Note: this Catch traps all exception types, not just ThreadAbortException, and calls ResetAbort unconditionally — a non-abort exception here would fail with ThreadStateException.* 8. Return True in all non-throwing paths.

Process flow

The following diagram visualizes this operation's control flow.

flowchart TD
    Start([Navigate called]) --> S1[Build absolute or relative target]
    S1 --> S2[Store source/target app+view in context]
    S2 --> D1{Source app <> target app?}
    D1 -->|Yes| S3{Session timed out?}
    S3 -->|No| S4[SaveContext: persist rows]
    S3 -->|Yes| S5[Skip persistence]
    D1 -->|No| S6[Store __SAIFPID in session]
    S4 --> D2{Popup?}
    S5 --> D2
    S6 --> D2
    D2 -->|Yes| S7([Open popup window + focus])
    D2 -->|No| S8([Response.Redirect])

Failure and edge-case behavior

  • A session-timeout at the moment of a cross-app navigation silently drops context persistence rather than failing the navigation.
  • The redirect's broad Catch ex As Exception calling Thread.ResetAbort() unconditionally would raise ThreadStateException for a genuine (non-abort) exception; whether this path is exercised in practice is unknown.**

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/clsControllerBase.vb