---
title: Retrieve the Business Online menu for a user
summary: Query the Oracle-backed menu repository for a user's visible menu items and favorites.
status: draft
owner: SAIF Documentation
last_reviewed: 2026-09-17
library: SAIF.Framework.Web.Mvc
reference_type: package
operation_id: OP-12
trigger: OP-11 (build and attach the Business Online menu) step 3 (session cache miss)
---

# Retrieve the Business Online menu for a user

Query the Oracle-backed menu repository for a user's visible menu items and favorites. Trigger: OP-11 (build and attach the Business Online menu) step 3 (session cache miss).

| Field | Value |
| --- | --- |
| **Operation ID** | OP-12 |
| **Trigger** | OP-11 (build and attach the Business Online menu) step 3 (session cache miss) |
| **Inputs** | `mailId`, typically `DOMAIN\user` from `User.Identity.Name` |
| **Outputs** | `BusinessOnlineMenu` with `Favorites` and `Items` arrays |
| **Primary components** | `MenuService.GetBusinessOnlineMenu(string mailId)` |
| **Entry point** | `src/Web.Mvc/Classes/MenuService.cs` |

## Steps

1. `Enforce.ArgumentNotNullOrEmpty(mailId, "mailId")` ([BR-01](../business-rules.md#br-01-guarded-arguments-reject-null-or-empty-input)).
2. When `mailId` contains a backslash, keep only the portion after it — strips the domain prefix ([BR-26](../business-rules.md#br-26-domain-qualified-mail-id-reduced-before-lookup)).
3. Build the user filter set `{ mailId.ToUpper(), "UNSECURED" }` so every user also receives the shared unsecured menu ([BR-27](../business-rules.md#br-27-every-user-also-receives-the-shared-unsecured-menu)).
4. Query `menuRepository.Query()` (NHibernate `IRepository<SAIF.Data.Model.Menu.BusinessOnlineMenuItem>`) for rows whose `MenuUser` is in that set and whose `IsVisible == "Y"`, ordered by `SortOrder`, materialized with `.ToList()` ([BR-28](../business-rules.md#br-28-only-visible-menu-rows-are-returned), [BR-29](../business-rules.md#br-29-menu-rows-are-ordered-by-sort-order)). The underlying table and mapping are defined in `SAIF.Framework.Data.NHibernate`, not in this repository.**
5. Partition the result: rows with `IsFavorite == "Y"` become `Favorites`, rows with `IsFavorite == "N"` become `Items`. Rows with any other `IsFavorite` value appear in neither collection ([BR-30](../business-rules.md#br-30-favorite-flag-partitions-rows-into-favorites-and-items)).
6. Map each data-model row onto a `BusinessOnlineMenuItem` contract object, converting `PageId` to string.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([Session cache miss])
	Guard[Guard mailId]
	Strip[Strip domain prefix]
	Filter[Build user filter set]
	Query[Query menu repository]
	Partition[Partition Favorites vs Items]
	EndOk([Return BusinessOnlineMenu])
	Start --> Guard
	Guard --> Strip
	Strip --> Filter
	Filter --> Query
	Query --> Partition
	Partition --> 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/Classes/MenuService.cs`
