Skip to content

Cross-application navigation

Navigate/Navigate2 implement outbound navigation from the current page, either within the same SAIF application or across to a different one. Cross-application navigation persists in-memory context values to the shared Context table so the target application can retrieve them on arrival (see Cross-application context hand-off).

Field Value
Operation ID OP-MVC-003
Trigger Explicit call to clsControllerBase.Navigate(TargetApp, TargetView) or the new-model overload Navigate2(TargetApp, TargetView) from a concrete controller
Inputs Target application/view, popup flags, optional new-model GUID
Outputs HTTP redirect or window.open client script; persisted context row(s) in Context
Primary components clsControllerBase.Navigate, clsControllerBase.Navigate2, clsContext.SaveContext
Entry point SAIF.Presentation.Web.MVC\clsControllerBase.vb

Steps

  1. Compute SourceApp from the current ApplicationPath; build NavTarget (absolute URL, path-rooted, or /{TargetApp}/{TargetView}).
  2. Stash targetView/targetApp/sourceApp/sourceView into Model.Context (in-memory, not yet persisted).
  3. If SourceApp <> TargetApp (cross-application navigation) (BR-MVC-005):
  4. If SupportsMultiModel, also stash the current ViewID under __SAIFPID.
  5. Unless the session has timed out, call Model.Context.SaveContext(SessionID):
    • Executes SQL-MVC-004 (DELETE FROM Context WHERE AppName=@AppName AND SessionID=@SessionID) against Context.
    • Executes SQL-MVC-001 once per stored context key (an INSERT INTO Context statement supplying the application name, session ID, context key, and context value) against Context.
  6. If SourceApp = TargetApp (same-application navigation), store the (possibly new) ViewID/model GUID into Session[__SAIFPID] instead of persisting to the database.
  7. If Popup is true, register a client startup script that calls window.open with the computed target URL, window name, and popup features, plus an optional focus-blur script.
  8. Otherwise: Response.Redirect(NavTarget) and Response.End().
  9. On failure: ThreadAbortException is swallowed via Thread.ResetAbort().
  10. Navigate2 additionally, before delegating to Navigate:
  11. Requires SupportsMultiModel (BR-MVC-004); throws ApplicationException("Navigate2 only supported with Multiple Model configuration.") otherwise.
  12. Creates a brand-new clsModelBase via the factory, assigns a fresh clsSecurityPrincipal, runs Pre_Init().
  13. Invokes the overridable OnNewModel(newModel, newViewData) hook to let the concrete controller copy state from the old model to the new one.
  14. On success, copies existing ViewData entries into the new view-data dictionary, stores the new model/view-data in Session under a new GUID, then delegates to Navigate(inTargetApplication, inTargetView, inNewModel:=NewGuid).

Process flow

flowchart TD
    Start([Navigate called]) --> Compute[Compute SourceApp / NavTarget]
    Compute --> StashCtx[Stash targetView/targetApp/sourceApp/sourceView in Model.Context]
    StashCtx --> CrossApp{SourceApp <> TargetApp?}
    CrossApp -->|Yes| SaveCtx[SaveContext: delete then insert rows]
    CrossApp -->|No| SessionStore[Store ViewID in Session]
    SaveCtx --> PopupCheck{Popup?}
    SessionStore --> PopupCheck
    PopupCheck -->|Yes| Script([Register window.open startup script])
    PopupCheck -->|No| Redirect([Response.Redirect + Response.End])

Failure and edge-case behavior

  • Navigate2 throws ApplicationException immediately if SupportsMultiModel is False — no partial state is created.
  • SaveContext's delete-then-insert has no rowcount/contention validation; a concurrent SaveContext call for the same application/session could interleave.
  • ThreadAbortException from Response.Redirect/Response.End is caught and suppressed in both Navigate and HandleErrors.

Sources

  • SAIF.Presentation.Web.MVC\clsControllerBase.vb
  • SAIF.Presentation.Web.MVC\clsContext.vb