Table of Contents

Class ContentOptions

Namespace
Quilt4Net.Toolkit
Assembly
Quilt4Net.Toolkit.dll

This option can be configured by code or with appsettings.json on location "Quilt4Net/Content"

public record ContentOptions : IEquatable<ContentOptions>
Inheritance
ContentOptions
Implements
Inherited Members

Properties

AdminRoles

Roles that grant content admin access (edit, debug, reload). Checked against the authenticated user's claim roles (e.g. Entra ID). Default is ["ContentAdmin", "Developer"].

public string[] AdminRoles { get; set; }

Property Value

string[]

ApiKey

Api key to be used for calls to the server. This key can be retrieved from https://quilt4net.com/.

public string ApiKey { get; set; }

Property Value

string

Application

Name of the application that will be used in Quilt4Net. Default is the name of the assembly.

public string Application { get; set; }

Property Value

string

AssumeAdmin

When true, always grant content admin access regardless of authentication state. Useful during development when no identity provider is configured. Default is false.

public bool AssumeAdmin { get; set; }

Property Value

bool

CacheDuration

Cache lifetime to request from the server. When null (the default) the server's own configured lifetime applies, as before.

public TimeSpan? CacheDuration { get; set; }

Property Value

TimeSpan?

Remarks

Issue #163: remote configuration has always been able to request a lifetime — GetAsync and GetToggleAsync take a ttl — and content could not. Content that changes a few times a week was expiring on the server's default of ten minutes.

This composes with the periodic re-warm rather than replacing it: WarmUpRefreshFraction is applied to whatever lifetime the server reports, so asking for 24 hours turns a bulk call every 8 minutes into one every 19.2 hours with nothing else to change.

The server clamps this to its own maximum, so a value it considers unreasonable is reduced rather than refused. The trade-off is visibility of edits: content changed on the server takes up to this long to reach an instance that is not restarted or reloaded — "Reload Content" in the admin UI remains the immediate path.

FailureCacheDuration

How long to stop calling for a key after a failed call — a timeout, a transport error or a non-success status other than 404. Doubles per consecutive failure up to MaxFailureCacheDuration and resets on the first success. Default is 5 seconds.

public TimeSpan FailureCacheDuration { get; set; }

Property Value

TimeSpan

Remarks

This option previously had no effect for any key that had ever succeeded: the failure path preferred the last successful response's TTL, which is a content-freshness interval and has nothing to do with how long a fault should be believed. That is what pinned a value to its fallback for a full cache lifetime per failed attempt (issue #174), so the preference is gone and this value now governs the failure hold-off outright.

A 429 carrying Retry-After still wins over both this and the back-off — the server saying when it will be ready beats any local guess.

HttpTimeout

Timeout for HTTP calls to the Quilt4Net server. Default is 5 seconds. When a stale cached value exists and StaleWhileRevalidate is enabled, the caller gets the stale value immediately and the refresh happens in the background, so this timeout only blocks when no cached value exists. When StaleWhileRevalidate is disabled, an expired entry is refreshed synchronously and this timeout applies to that call.

public TimeSpan HttpTimeout { get; set; }

Property Value

TimeSpan

MaterializationWait

How long a caller waits for a key the server has never seen before giving up and rendering its own declared default. The materialization still completes in the background, so the next render shows the stored value. Default is 200 ms. Zero disables the bounded wait, restoring the previous behaviour of waiting up to HttpTimeout.

public TimeSpan MaterializationWait { get; set; }

Property Value

TimeSpan

Remarks

This exists because the first request for a new key is a write, not a read: the caller supplies the text, the server stores it, and the caller waits out the storing. Measured at 1.5–3.3 s per key, which is what turned a dialog declaring thirteen new keys into an eighteen-second first open, and 106 ms on every open after (Toolkit issue #182).

The caller already holds the correct text — defaultValue and translations are literals in its own source — so waiting for the server to write down an answer it was just given buys nothing.

⚠️ The trade. This applies to any key not in the cache, not only to genuinely new ones, because the client cannot tell the two apart until the server answers. For an existing key whose cache is cold, a slow server therefore means one render of the code default before the stored value arrives — briefly the wrong language, where previously the render blocked. In practice the warm-up has already loaded every existing key, so the cold case is close to exclusively new keys. Set this to Zero if a correct first paint matters more than a responsive one.

MaxFailureCacheDuration

Ceiling for the consecutive-failure back-off described on FailureCacheDuration. A sustained outage settles here instead of retrying every few seconds per key. Default is 5 minutes.

public TimeSpan MaxFailureCacheDuration { get; set; }

Property Value

TimeSpan

MetricsEnabled

When true (default), content resolutions are published as metrics on the Quilt4Net.Toolkit.Content meter — a resolution counter and a duration histogram, both tagged by source, so a host gets call volume, latency and cache-hit ratio without enabling Debug logging.

public bool MetricsEnabled { get; set; }

Property Value

bool

Remarks

Defaults on because the cost is near zero when nobody subscribes to the meter, and because the number that matters most — the cache-hit ratio — cannot be computed outside this library: the public read returns a bare string, so a wrapper can time a call and never learn whether it was served from cache, stale cache, the server or a fallback.

MinimumWarmUpInterval

Floor for the periodic re-warm interval, whatever WarmUpRefreshFraction and the server's lifetime work out to. Default is 30 seconds — a bulk call is cheap, but a server reporting a very short lifetime must not turn the re-warm into its own source of load.

public TimeSpan MinimumWarmUpInterval { get; set; }

Property Value

TimeSpan

NotFoundCacheDuration

How long to remember that the server answered 404 for a key — i.e. there is no content override and the caller's default stands. Default is 10 minutes.

public TimeSpan NotFoundCacheDuration { get; set; }

Property Value

TimeSpan

Remarks

Deliberately not the failure back-off: a 404 is an answer, not a fault. The server was reached and replied. Holding it for seconds rather than minutes would re-request every unseeded key on nearly every render, which is the request flood this feature exists to remove. Where a previous successful response TTL is known for the key, that is used instead.

PeriodicWarmUpEnabled

When true (default), the bulk warm-up repeats on a timer rather than running once per process, so warmed entries are replaced shortly before they expire and the per-key path is never reached in steady state. Ignored when WarmUpEnabled is false.

public bool PeriodicWarmUpEnabled { get; set; }

Property Value

bool

Remarks

Without this the bulk endpoint effectively serves the first cache lifetime of a process's life and little else: every warmed key shares one ValidTo, so the whole set expires at the same instant and the next render fans out one HTTP call per key — hundreds at once, which is what trips a server's per-caller limit and starts the timeout loop described in issue #163.

Quilt4NetAddress

Address to the Quilt4Net server. Default is https://quilt4net.com/. Defaulted on the type so an unbound IOptions<ContentOptions> still carries a usable URL when only part of the toolkit is registered (e.g. AddQuilt4NetRemoteConfiguration without AddQuilt4NetContent).

public string Quilt4NetAddress { get; set; }

Property Value

string

SlowLogThreshold

Diagnostics (issue #132): when a content fetch or language-list load from the server takes at least this long, a single Warning is logged naming the endpoint, elapsed time and HTTP status — so slow content/language loads surface in production even when Debug logging is off. The detailed per-resolution timing lines (key, resolved language, cache hit/miss, source, elapsed) are logged at Debug on category Quilt4Net.Toolkit.Features.Content.RemoteContentCallService and are opt-in via normal log configuration. Set Zero to disable the slow-load warning. Default is 3 seconds.

public TimeSpan SlowLogThreshold { get; set; }

Property Value

TimeSpan

StaleWhileRevalidate

When true (default), an expired cache entry is returned immediately and refreshed in the background (stale-while-revalidate) — fast, but the caller may see one slightly stale value. When false, an expired entry is refreshed synchronously so the caller always gets a fresh value (subject to HttpTimeout), at the cost of blocking on the refresh.

public bool StaleWhileRevalidate { get; set; }

Property Value

bool

WarmUpEnabled

When true (default), the Blazor content registration runs a startup warm-up that pre-fills the cache with the default language in one bulk call (so pages render without a request per key). The user's selected language is warmed per-circuit when it differs from the default. Set false to disable warm-up and rely solely on lazy per-key fetching.

public bool WarmUpEnabled { get; set; }

Property Value

bool

WarmUpLanguages

Additional languages to warm at startup (and on "Reload Content"), on top of the default language which is always warmed. Identified by language name exactly as entered on the server (e.g. ["English", "Svenska"]), matching the naming convention used elsewhere in the content API. A name with no matching server language is skipped with a Warning. Empty (the default) preserves the previous behaviour — only the default language is warmed at startup, and other languages warm per-circuit when first selected. Ignored when WarmUpEnabled is false.

public IReadOnlyList<string> WarmUpLanguages { get; set; }

Property Value

IReadOnlyList<string>

WarmUpRefreshFraction

Where in the observed cache lifetime the periodic re-warm runs, as a fraction. Default is 0.8 — a re-warm at 80% of the lifetime, leaving headroom for a slow or failed pass before anything expires. Clamped to a sane range, and never faster than 30 seconds.

public double WarmUpRefreshFraction { get; set; }

Property Value

double