---
title: Title-case a string
summary: Normalize free-text input into title case while preserving organization abbreviations, Roman numerals, US state/direction codes, and listed lowercase articles/prepositions.
status: draft
owner: Framework.NCore maintainers
last_reviewed: 2026-10-02
library: SAIF.NetCore.Common
reference_type: package
operation_id: OP-01
trigger: A consumer calls `StringExtensions.ToTitleCase(value)`.
---

# Title-case a string

Normalize free-text input into title case while preserving organization abbreviations, Roman numerals, US state/direction codes, and listed lowercase articles/prepositions. This operation is triggered when a consumer calls `StringExtensions.ToTitleCase(value)`.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-01 |
| **Trigger** | A consumer calls `StringExtensions.ToTitleCase(value)`. |
| **Inputs** | `value` (string) |
| **Outputs** | The title-cased string, or the original value unchanged for null/empty input. |
| **Primary components** | `StringExtensions.ToTitleCase`, `InternalUtility.TitleCase.ToTitleCase` |
| **Entry point** | `src/SAIF.NetCore.Common/SAIF.NetCore.Common/SAIF.NetCore.Common/Extensions/StringExtensions.cs` |

## Steps

1. Check `value` for null or empty.
   - If null or empty: return the value unchanged.
2. Split `value` on non-word characters with a regex, keeping the delimiters.
3. Classify each word token against the engine's word lists and casing rules. ([BR-019](../business-rules.md#br-019-title-casing-preserves-a-fixed-set-of-organization-abbreviations-roman-numerals-and-lowercase-words))
   - Mixed-case words are left unchanged; words in the upper-case list are upper-cased; words in the mixed-case list (`PhD`, `LaCombe`) are replaced with their listed form; words in the lower-case list are lower-cased; ordinal suffixes after digits are lower-cased; any other word is proper-cased with the current thread culture; words starting with `Mc` or `O'` capitalize the letter after the prefix.
4. Reassemble the words with their original delimiters.
5. Lowercase a possessive `'s` suffix.
6. Always uppercase the first character of the result.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([Call ToTitleCase]) --> NullCheck{value null or empty?}
	NullCheck -->|Yes| ReturnAsIs([Return value unchanged])
	NullCheck -->|No| Split["Split on non-word chars,<br>keep delimiters"]
	Split --> Classify["Classify each word token<br>against word lists"]
	Classify --> Reassemble["Reassemble words<br>with delimiters"]
	Reassemble --> Possessive["Lowercase possessive 's suffix"]
	Possessive --> FirstCap[Uppercase first character]
	FirstCap --> End([Return title-cased string])
```

## Failure and edge-case behavior

- Null or empty input: returned unchanged without error.
- A word not found in any list is proper-cased using `CurrentCulture.TextInfo`, so results vary by server culture*.

## 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/SAIF.NetCore.Common/SAIF.NetCore.Common/SAIF.NetCore.Common/Extensions/StringExtensions.cs`
- `src/SAIF.NetCore.Common/SAIF.NetCore.Common/SAIF.NetCore.Common/InternalUtility/TitleCase.cs`
