---
title: Read a preference value
summary: Looks up a single preference item by key, scope, or explicit application/page.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-08-17
library: SAIF.Presentation
reference_type: package
operation_id: OP-PRES-002
trigger: Consuming code indexes into the preference store
---

# Read a preference value

This operation serves keyed lookups entirely from the in-memory `Preference` set loaded by [Construct and load a user's preferences](construct-and-load-preferences.md); it issues no database calls.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-PRES-002 |
| **Trigger** | Consuming code indexes into the preference store via `Item` |
| **Inputs** | Key (and optionally scope, or explicit application + page) |
| **Outputs** | The stored value, or `Nothing` when not found |
| **Primary components** | `clsPreferences.Item` (three overloads), `clsPreferences.PageKey`, `clsPreferences.Page`, `clsPreferences.IsWeb` |
| **Entry point** | `SAIF.Presentation/clsPreferences.vb` |

## Steps

1. Return `Nothing` immediately if the key is `Nothing` ([BR-PRES-006](../business-rules.md#br-pres-006-a-nothing-key-is-a-no-op)).
2. Lower-case the key ([BR-PRES-007](../business-rules.md#br-pres-007-preference-keys-are-case-insensitive)).
3. Resolve the page key: `PrefScope.PageLevel` yields the derived page name; every other scope yields an empty string ([BR-PRES-008](../business-rules.md#br-pres-008-only-pagelevel-scope-binds-to-a-page)).
4. Derive the page name via the `Page` property:
   - If `System.Web.HttpContext.Current` is non-null (web context), take the substring of `Request.Path` after the last `/` ([BR-PRES-009](../business-rules.md#br-pres-009-web-page-name-derived-from-request-path)).
   - Otherwise use `OverridePage` when it is non-empty, else reflect the declaring type name from stack frame 1 of a `StackTrace(4)` ([BR-PRES-010](../business-rules.md#br-pres-010-non-web-page-name-derived-from-override-or-call-stack)).
5. Find the first `Preference` whose `ApplicationName` matches the current application and whose `Pagename` matches the page key ([BR-PRES-011](../business-rules.md#br-pres-011-preference-record-identified-by-application-and-page)).
   - If no record matches: return `Nothing`.
6. Return `PreferenceItems(key)` when the key exists in that record, otherwise `Nothing`.
7. For the three-argument overload (`Item(inApplication, inPage, inKey)`), scope resolution is skipped entirely: application, page, and key are lower-cased (mapping `Nothing` to an empty string) and matched directly against the lower-cased record fields ([BR-PRES-012](../business-rules.md#br-pres-012-explicit-three-argument-lookup-matches-lower-cased-fields)).

No SQL is executed by any read — all reads are served from the collection loaded in [Construct and load a user's preferences](construct-and-load-preferences.md).

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([Item lookup]) --> D1{Key is Nothing?}
	D1 -->|Yes| EndNull1([Return Nothing])
	D1 -->|No| S1[Lower-case key]
	S1 --> S2[Resolve page key from scope]
	S2 --> S3[Derive page name: web path or OverridePage/call stack]
	S3 --> S4[Find matching Preference record]
	S4 --> D2{Record found?}
	D2 -->|No| EndNull2([Return Nothing])
	D2 -->|Yes| S5[Look up key in PreferenceItems]
	S5 --> D3{Key present?}
	D3 -->|Yes| EndVal([Return value])
	D3 -->|No| EndNull3([Return Nothing])
```

## Failure and edge-case behavior
- A `Nothing` key returns `Nothing` rather than throwing ([BR-PRES-006](../business-rules.md#br-pres-006-a-nothing-key-is-a-no-op)).
- No matching `Preference` record for the application/page returns `Nothing` rather than throwing.
- Outside a web context with no `OverridePage` set, the page name is derived by reflecting the call stack, which is brittle to refactors that add or remove stack frames.*

## 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.

## Sources
- `SAIF.Presentation/clsPreferences.vb`
