---
title: Navigate to a view
summary: Moves the user to another view, in-app or cross-app, persisting context to SQL Server or opening a popup as needed.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-08-17
library: SAIF.Presentation.Web.MVC
reference_type: package
operation_id: OP-MVC-04
trigger: Derived controller decides to leave the current view; also used by ViewPageBase.ProcessError
---

# 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](../business-rules.md#br-mvc-009-absolute-navigation-targets-are-preserved-verbatim)).
3. Store `targetView`, `targetApp`, `sourceApp`, and `sourceView` into the model context ([BR-MVC-010](../business-rules.md#br-mvc-010-every-navigation-records-sourcetarget-app-and-view)).
4. If source and target applications differ:
   - When `SupportsMultiModel`, also store the current `ViewID` under `__SAIFPID` ([BR-MVC-008](../business-rules.md#br-mvc-008-multi-model-view-state-is-keyed-by-a-per-view-guid)).
   - Unless the session has timed out, call `Model.Context.SaveContext(Session.SessionID)` to persist the context rows ([BR-MVC-010](../business-rules.md#br-mvc-010-every-navigation-records-sourcetarget-app-and-view), [BR-MVC-011](../business-rules.md#br-mvc-011-context-is-persisted-only-on-genuine-cross-app-transitions)).
     - Embeds [Persist context rows](persist-context-rows.md), which deletes any prior rows ([SQL-004](../sql/SQL-004-delete-context-rows.md)) and inserts one row per context key ([SQL-001](../sql/SQL-001-insert-context-row.md), [Context](../database-tables.md#context)).

> **Origin**: Steps 4.1–4.2 are implemented in [`Persist context rows`](persist-context-rows.md) (`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](../business-rules.md#br-mvc-008-multi-model-view-state-is-keyed-by-a-per-view-guid)).
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](../business-rules.md#br-mvc-013-popup-navigation-uses-a-fixed-window-geometry)).
7. Otherwise `Response.Redirect(NavTarget)` ([BR-MVC-012](../business-rules.md#br-mvc-012-redirect-induced-thread-aborts-are-suppressed)).
   - 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.

```mermaid
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.**

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [SQL catalog](../sql/index.md)
- [Database tables](../database-tables.md)

> **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
