---
title: Render side navigation menu
summary: Renders the SAIFMenu left-side favorites and application/category accordion panel and wires its host-facing navigation events.
status: draft
owner: SAIF documentation team
last_reviewed: 2026-08-17
library: SAIF.Presentation.Web.Controls.V2.Menu
reference_type: package
operation_id: OP-MENU-001
trigger: ASP.NET page lifecycle (OnInit -> Page_PreLoad -> OnLoad -> RenderControl) when a SAIFMenu control is placed on a ViewPageBase-derived page
---

# Render side navigation menu

This operation renders the `SAIFMenu` left-side navigation panel — a favorites link list, a collapsible application/category accordion, and an optional context-value text box — and wires the control's host-facing navigation events for a hosting ASP.NET WebForms page.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-MENU-001 |
| **Trigger** | ASP.NET page lifecycle events (`OnInit`, `Page_PreLoad`, `OnLoad`, `RenderControl`) fired when a `SAIFMenu` control instance is present on a `ViewPageBase`-derived page |
| **Inputs** | Current Windows user identity (`HttpContext.Current.Request.LogonUserIdentity.Name`), session-cached `NavigationContext`, `ShowApps`/`SelectedCategory`/`ContextLabel` ViewState, per-user `clsPreferences("SHOWAPPS")` |
| **Outputs** | Rendered favorites link list, collapsible application/category accordion (`AjaxControlToolkit.Accordion`), and a context-value text box; `MenuNavigate`, `DefaultOnSubmit`, `OnContextChanged` events available to the host page |
| **Primary components** | `SAIFMenu.OnInit`, `SAIFMenu.Page_PreLoad`, `SAIFMenu.OnLoad`, `SAIFMenu.RenderControl`, `SAIFMenu.LinkButtonClick`, `SAIFMenu.NavigateToItem`, `SAIFMenu.ExpandClick`, `SAIFMenu.m_EnterControl_Click` |
| **Entry point** | `SAIF.Presentation.Web.Controls.V2.Menu\SAIFMenu.vb` |

## Steps

1. `OnInit` resolves `m_Page` as `ViewPageBase` ([SAIF.Presentation.Web.MVC](../../saif-presentation-web-mvc/overview.md)); calls `CreateControlsBegin()`, which invokes `BuildMenuIcons()` (builds the "default submit" and "Edit favorites" icon buttons) and `BuildFavoritesTop()` (assembles the favorites header panel).
2. `Page_PreLoad` (`Handles m_Page.PreLoad`) runs on first load (`Not m_Page.IsPostBack`) for an authenticated user:
   - Reads `Preferences("SHOWAPPS", PrefScope.AppLevel)` and sets `ShowApps` to the stored `"Y"/"N"` value.
     - If no preference exists: defaults `ShowApps` to expanded (`True`)*.
   - Lazily sets `CurrentPage` from `NavigationData.GetCurrentPage()`.
   - Restores a previously-saved context value from `Session("CVTextBox" & ViewID)` on non-postback.
3. `OnLoad` calls `CreateControls()`, which:
   - Invokes `InitializeControls()` — applies `ContextViewStyle` to the text box (`Normal`/`Read_Only`/`Hidden`), applies watermark text/CSS when the field is empty.
   - Invokes `AddLinks(NavigationData)` — builds the Favorites-Config and application/category accordion panes and links, sorted by `MenuCategory` then `MenuOrder`; skips categories with no visible items.
     - On failure: throws an `ApplicationException` if a duplicate or blank accordion pane ID is generated.
   - Invokes `AddFavorites(NavigationData)` — builds one `LinkButton` per authorized favorite item, sorted by `MenuOrder`, plus a conditional "Change Password" link when `AppGlobal.EnvironmentService.IsClientExternal` is true.
   - Invokes `BuildMyStuff()` — assembles the favorites section and applications section into the navigation `Panel`.
   - Registers client-side hotkey (F12-like context-focus) and watermark-focus/blur JavaScript blocks.
4. `RenderControl` refreshes `m_ContextValue.MaxLength` from `MaxContextValueLength` in non-design mode, then defers to `MyBase.RenderControl`.
   - On failure: the call is wrapped in `Try/Catch`; on exception, writes the exception message/source/stack trace directly to the output writer instead of re-throwing*.
5. User interaction — clicking a favorite/application link (`LinkButtonClick`):
   - Parses the numeric item sequence from the `LinkButton.ID` suffix (`"_LB" & seq`) and calls `NavigateToItem`.
   - `NavigateToItem` stashes the current context value into `Session("CVTextBox" & ViewID)` and raises `MenuNavigate(ApplicationPath, PageLink)` for the host page to act on.
   - If the clicked control is the special `"ChangePWLink"`: performs a direct `Response.Redirect("/BusinessOnline/Changepassword.aspx?__SAIFPID=" & ViewID)` instead of raising `MenuNavigate`.
   - If the "Edit favorites" icon is clicked: raises `MenuNavigate("MenuCache", "frmFavoriteMaint.aspx")`.
   - If the hidden default-submit icon is clicked: raises `DefaultOnSubmit()`.
6. User interaction — clicking the "expand/collapse applications" icon (`ExpandClick`):
   - Toggles `ShowApps` and rebuilds the accordion via `AddLinks`.
   - Persists the new state to `clsPreferences` (`Preferences.Add("SHOWAPPS", "Y"/"N", PrefScope.AppLevel)` then `Preferences.Save()`) when a preferences object is available.
7. User interaction — pressing Enter in the context box (`m_EnterControl_Click`, wired via generated `EnterPress` JavaScript calling `__doPostBack`):
   - Stores the context value into session and raises `MenuNavigate("ContextValue", "ENTER")`.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([Page lifecycle: OnInit]) --> Init[Resolve m_Page as ViewPageBase; build menu icons/favorites top]
	Init --> PreLoad[Page_PreLoad: restore ShowApps preference and context value]
	PreLoad --> OnLoad[OnLoad: InitializeControls, AddLinks, AddFavorites, BuildMyStuff]
	OnLoad --> Render[RenderControl: render Panel]
	Render --> D{User interaction?}
	D -->|Click favorite/app link| Nav[NavigateToItem: stash context, raise MenuNavigate]
	D -->|Click Change Password| Redirect([Direct Response.Redirect to Changepassword.aspx])
	D -->|Click expand/collapse icon| Expand[ExpandClick: toggle ShowApps, save preference]
	D -->|Press Enter in context box| Enter[Raise MenuNavigate ContextValue ENTER]
	D -->|No interaction| EndOk([Render complete])
	Nav --> EndNav([Host page handles MenuNavigate])
```

## Failure and edge-case behavior
- `RenderControl` exceptions are caught and written directly into the HTML output stream (message/source/stack trace) rather than logged or suppressed, a potential information-disclosure risk in production*.
- `AddLinks` throws `ApplicationException` on a duplicate or blank generated pane ID.
- The "Change Password" favorite link is only shown when `AppGlobal.EnvironmentService.IsClientExternal` is true; otherwise it is omitted from the favorites list. Internal-network deployments therefore never see a self-service password-change link*.
- **UI behavior note — default expanded accordion:** when no "Show Applications" preference exists for the current user, `Page_PreLoad` defaults the applications accordion to expanded (`ShowApps = True`); this is a presentational default, not a business rule.
- **UI behavior note — empty categories hidden:** `AddLinks` omits an application/category accordion pane entirely when it contains no visible authorized items, so empty categories never appear in the rendered navigation.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [API reference](../api/index.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.Controls.V2.Menu\SAIFMenu.vb`
