---
title: Render the Business Online menu
summary: Emit the favorites and category-grouped navigation menu markup for the current view.
status: draft
owner: SAIF Documentation
last_reviewed: 2026-09-17
library: SAIF.Framework.Web.Mvc
reference_type: package
operation_id: OP-19
trigger: Razor view calling the helper
---

# Render the Business Online menu

Emit the favorites and category-grouped navigation menu markup for the current view. Trigger: Razor view calling the helper.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-19 |
| **Trigger** | Razor view calling the helper |
| **Inputs** | `HtmlHelper`, `MenuViewModel`, `WebContextViewModel` |
| **Outputs** | Markup written to `helper.ViewContext.Writer`; the "old school" variants return an `HtmlString` instead |
| **Primary components** | `MenuExtensions.RenderMenu` and `RenderTopMenu`, plus the legacy `RenderOldSchoolMenu` and `RenderOldSchoolTopMenu` |
| **Entry point** | `src/Web.Mvc/Extensions/MenuExtensions.cs` |

## Steps

1. `Enforce.ArgumentNotNull` on `helper`, `menu`, and `webContext` ([BR-01](../business-rules.md#br-01-guarded-arguments-reject-null-or-empty-input)).
2. Emit the Favorites header containing a hard-coded link to `/MenuCache/frmFavoriteMaint.aspx` and open `<ul class="nav nav-tabs nav-stacked bo-apps-favorites">`.
3. Emit one `<li>` per favorite through `FavoriteLink`, which renders `<a data-mid="{PageId}" href="/{ApplicationName}/{PageLink}" title="{MenuCategory} - {Tooltip}">{FavoriteName or PageName}</a>`. The `title` attribute is emitted only when `Tooltip` is non-blank, and the link text falls back to `PageName` when `FavoriteName` is blank ([BR-42](../business-rules.md#br-42-favorite-display-text-falls-back-to-page-name), [BR-43](../business-rules.md#br-43-menu-link-title-attribute-is-conditional)).
4. Emit the "All Applications" header and a `<ul id="menu">` carrying `data-current-app`, `data-current-item-id`, `data-expanded` (lower-cased boolean), and `data-menu-category` — the hooks the client-side script uses to highlight the active item.*
5. Order items by `MenuCategory`, group by `MenuCategoryCode`, and for each group emit a category anchor plus a nested `<ul class="nav nav-list is-hidden">` containing one `<li>` per item rendered through `MenuLink` ([BR-44](../business-rules.md#br-44-menu-items-ordered-by-category-and-grouped)).
6. Write the accumulated string to `helper.ViewContext.Writer`.
7. `RenderTopMenu` emits only the items whose `MenuCategoryCode` equals `menu.MenuCategory`, both upper-cased ([BR-45](../business-rules.md#br-45-top-menu-shows-only-the-controller's-declared-category)).
8. The two `RenderOldSchool*` helpers produce the same data with the legacy `<nav>`/`<header>` markup and render favorites through `MenuLink` rather than `FavoriteLink` — so favorite names and category tooltips are not applied on the legacy path.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([Razor view calls RenderMenu])
	Guard[Guard helper/menu/webContext]
	Fav[Emit favorites list]
	All[Emit All Applications header]
	Group[Group items by category code]
	Write[Write markup to ViewContext.Writer]
	EndOk([Markup emitted])
	Start --> Guard
	Guard --> Fav
	Fav --> All
	All --> Group
	Group --> Write
	Write --> EndOk
```

## Failure and edge-case behavior

- No unexpected failure paths beyond argument-guard exceptions and delegated dependency behavior were identified for this operation.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.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
- `src/Web.Mvc/Extensions/MenuExtensions.cs`
