---
title: Build a toolbar through the fluent API
summary: Configure a server-rendered toolbar component through a fluent builder chain.
status: draft
owner: SAIF Documentation
last_reviewed: 2026-09-17
library: SAIF.Framework.Web.Mvc
reference_type: package
operation_id: OP-23
trigger: Razor view calling `Html.SAIF().Toolbar()`
---

# Build a toolbar through the fluent API

Configure a server-rendered toolbar component through a fluent builder chain. Trigger: Razor view calling `Html.SAIF().Toolbar()`.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-23 |
| **Trigger** | Razor view calling `Html.SAIF().Toolbar()` |
| **Inputs** | Fluent configuration lambda |
| **Outputs** | A configured `Toolbar` whose `Render()` and `ToHtmlString()` currently emit no markup |
| **Primary components** | `HtmlHelperExtensions.SAIF` into `ViewComponentFactory.Toolbar()` into `ToolbarBuilder.Items(Action<ToolbarItemFactory>)` into `ToolbarItemFactory.Add()` / `AddSaveButton()` |
| **Entry point** | `src/Web.Mvc/UI/Extensions/HtmlHelperExtensions.cs` |

## Steps

1. `Html.SAIF()` wraps the helper in a `ViewComponentFactory`.
2. `Toolbar()` constructs a `Toolbar` bound to `HtmlHelper.ViewContext` and wraps it in a `ToolbarBuilder`.
3. `Items(addAction)` invokes the caller's lambda with a `ToolbarItemFactory` bound to the toolbar and view context.
4. `Add()` creates an empty `ToolbarItem`, appends it to `Toolbar.Items`, and returns a `ToolbarItemBuilder`.
5. `AddSaveButton()` creates a `ToolbarItem` pre-populated with `Id = "lnk-save"`, `ImageUrl = "/Resources/MenuImages/save.png"`, and `Tooltip = "Save (Alt + S)"` ([BR-54](../business-rules.md#br-54-standard-save-button-uses-a-fixed-id%2C-icon%2C-and-tooltip)).
6. `ToolbarItemBuilder`, through `NavigationItemBuilder`, sets `Enabled`, `Id`, `Text`, `Tooltip`, `Url`, `Visible`, and the three html-attribute dictionaries; each `HtmlAttributes`-family setter clears the dictionary before merging. The `Action` overloads (`Action(RouteValueDictionary)`, `Action(string, string)`, `Action(string, string, object)`, `Action(string, string, RouteValueDictionary)`) and `Route` overloads (`Route(string, object)`, `Route(string, RouteValueDictionary)`) accept values and discard them.
7. `ViewComponentBuilderBase.Render()` calls `ViewComponentBase.Render()`, which wraps `ViewContext.Writer` in an `HtmlTextWriter` and invokes the virtual `WriteHtml` — empty in `ViewComponentBase`, and `Toolbar.WriteHtml` only calls `base`. No output is produced, and `ToString()` returns an empty string.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start(["Html.SAIF().Toolbar()"])
	Wrap[Wrap in ViewComponentFactory]
	Build[Construct Toolbar and ToolbarBuilder]
	Items[Invoke caller lambda via Items]
	Add[Add / AddSaveButton items]
	Render[Call Render/ToHtmlString]
	EndOk([No markup emitted])
	Start --> Wrap
	Wrap --> Build
	Build --> Items
	Items --> Add
	Add --> Render
	Render --> EndOk
```

## Failure and edge-case behavior

- The `Action` and `Route` overload no-ops and empty `WriteHtml` mean a rendered `Toolbar` currently emits no markup regardless of how it was configured — this may be abandoned work in progress rather than intended behavior.*

## 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/UI/Extensions/HtmlHelperExtensions.cs`
- `src/Web.Mvc/UI/Toolbar/*.cs`
- `src/Web.Mvc/UI/ViewComponentFactory.cs`
