Skip to content

API reference

Every component parameter, service member, option and value type, with its default - the page to keep open while you write code. The topic pages explain why; this one answers what it's called.

Everything below lives in the Bit.Brouter namespace. Add @using Bit.Brouter to _Imports.razor once and none of it needs qualifying.

Components

<Brouter> - the router

One per app, usually in App.razor or a dedicated AppRouter.razor. Routes go in <Routes> (or directly as child content - the two are aliases; never use both).

ParameterTypePurpose
Routes / ChildContentRenderFragment?The route tree. Aliases of each other.
AppAssemblyAssembly?Assembly to scan for @page / [Route] components.
AdditionalAssembliesIEnumerable<Assembly>?Further assemblies to scan (Razor class libraries, lazily-loaded ones).
OnNavigateAsyncFunc<ctx, ValueTask<IEnumerable<Assembly>?>>?Lazy route loading; returned assemblies register within the same navigation.
NotFoundUrlstring?Redirect target when nothing matches.
NotFoundRenderFragment<BrouterLocation>?Rendered in place instead, leaving the URL alone.
NavigatingRenderFragment?Pending UI while loaders run; revealed lazily, so fast navigations never flash it.
ErrorContentRenderFragment<BrouterErrorContext>?Router-level error boundary - the last resort under every route's own.
ParallelLoadersbool (false)Run a chain's loaders concurrently instead of root → leaf sequentially.
FoundRenderFragment<RouteData>?The built-in Router's template, ported verbatim. Applies to Component-rendered routes.
DefaultLayoutType?Layout for pages without their own @layout.
NotAuthorizedRenderFragment<AuthenticationState>?Setting this (or Authorizing/Resource) routes through the framework's AuthorizeRouteView.
AuthorizingRenderFragment?Shown while an authorization policy is being evaluated.
Resourceobject?Resource passed to resource-based authorization policies.
OnMatchFunc<Broute, ValueTask>?Fired when a route matched, just before OnNavigated.
OnNotFoundFunc<BrouterLocation, ValueTask>?Fired when nothing matched.

<Broute> - one route

Routes are components, so nesting is just markup: a <Broute> inside another inherits its parent's template as a prefix. Render either a Component or a Content fragment - not both.

ParameterTypePurpose
Path (required)stringThe route template. Empty string on a child = the index route (matches the parent exactly).
ComponentType?Component type to render; route values bind to its [Parameter] properties by name.
ContentRenderFragment<BrouterRouteParameters>?Inline markup instead; the context argument is the parameter bag.
Routes / ChildContentRenderFragment?Child routes. Use Routes when the parent also has Content.
Namestring?Enables NavigateToName/ResolveUrl and names the generated URL builder.
RedirectTostring?Redirect instead of rendering. Guards on the route still run first.
Groupbool (false)Pathless group: contributes no URL segments, only shared guard/loader/layout/error boundary.
GuardFunc<ctx, ValueTask>?Enter guard; runs root → leaf before the URL commits.
LeaveGuardFunc<ctx, ValueTask>?Leave guard; runs leaf → root, only for routes actually being deactivated.
LoaderFunc<ctx, ValueTask<object?>>?Async data fetch; the result cascades as BrouterRouteData.
StaleTimeTimeSpan?Freshness window for this route's loader results. Falls back to DefaultLoaderStaleTime.
Metaobject?Static per-route metadata, cascaded as BrouterRouteMeta. No code runs.
KeepAlivebool (false)Retain the rendered component (hidden) when navigated away.
KeepAliveMaxint?Retained-instance budget. Above 1, one instance per distinct parameter set, LRU-evicted. Defaults to DefaultKeepAliveMax.
ErrorContentRenderFragment<BrouterErrorContext>?Error boundary for this route and its descendants; nearest boundary wins.

<BrouterLink> - navigation links

Renders a real <a>: Ctrl/middle/Shift clicks keep native browser behavior, only plain left clicks are intercepted. Extra attributes are splatted onto the anchor.

ParameterType (default)Purpose
Href (required)string ("/")Destination. Route-relative forms (./x, ../x) re-resolve after every navigation.
MatchBrouterLinkMatch (Prefix)Active detection. Prefix is segment-boundary aware; All is exact. Root / always matches exactly.
ActiveClassstring ("active")Class added when active; also sets aria-current="page".
Classstring?Base class list, always applied.
Replacebool (false)Replace the current history entry instead of pushing.
PreloadBrouterLinkPreload?Warm the loader cache before the click. Falls back to DefaultLinkPreload.
HistoryStatestring?State attached to the history entry this click creates.

Outlets, views & deferred data

ComponentParametersPurpose
<BrouterOutlet>Name (string, "")Placed in a parent's content to mark where matched children render. A name creates a secondary region.
<BrouterView>Name, ChildContentDeclared inside a child route's <Routes> to fill the same-named outlet of an ancestor.
<BrouterAwait<T>>Task (required), Pending, Resolved, ErrorRenders an unawaited Task<T> returned by a loader as it resolves.

IBrouter - the service

Methods

Inject anywhere with @inject IBrouter brouter. Every URL argument accepts route-relative forms.

MemberNotes
LocationBrouterLocation for the current URL. Never null.
Navigate(url, replace, forceLoad, historyState)Fire-and-forget. forceLoad does a full document load and skips the pipeline entirely.
NavigateAsync(url, replace, historyState)Awaits the whole pipeline and returns a BrouterNavigationOutcome. No forceLoad - nothing would survive to resolve the task.
Back() / BackAsync(delta = 1)Move back; the async form is awaitable and can jump several entries.
Forward() / ForwardAsync(delta = 1)The forward equivalents.
NavigateToName(name, parameters, query, replace, historyState)Target a Named route. Parameters not in the template become query pairs.
ResolveUrl(name, parameters, query)The same substitution, returned as a string instead of navigated to.
NavigateWithQuery(mutate, replace = true)Functional query update over a BrouterQueryBuilder; untouched parameters and the fragment survive.
RevalidateAsync()Re-runs the current chain's loaders in place. No URL change, no guards, content stays visible.
ReloadAsync()Rebuilds the current chain: components disposed and recreated, route guards and loaders re-run. No URL change, no navigation hooks, no leave guards. Loaders can tell a reload apart via BrouterNavigationContext.IsReload. Re-navigating to the same URL cannot do this - Blazor keeps the component.
PreloadAsync(url)Speculatively runs the destination's loaders. No guards, no render, failures swallowed.
ClearLoaderCache()Drops every cached loader result - e.g. on sign-out.
ClearKeepAlive()Disposes every retained keep-alive component. The visible page keeps its instance.
ClearKeepAlive(includeActive)With includeActive: true the page on screen is disposed and rebuilt in place too - fresh instance, no navigation, no guards or loaders re-run.
SetConfirmExternalNavigationAsync(enabled)Arms/disarms the browser's "leave site?" dialog at runtime. Idempotent.

Events

All three are async delegates. Subscribe in OnInitialized and unsubscribe in Dispose - a forgotten handler keeps its component alive for the router's lifetime.

EventSignatureFires
OnNavigatingFunc<ctx, ValueTask>Before every navigation, after leave guards. Can Cancel() / Redirect().
OnNavigatedFunc<ctx, ValueTask>After a navigation commits and renders.
OnErrorFunc<ctx, Exception?, ValueTask>On unhandled pipeline exceptions. Cancels and redirects are control flow and never raise it.
@inject IBrouter brouter
@implements IDisposable

@code {
    private Func<BrouterNavigationContext, ValueTask>? _handler;

    protected override void OnInitialized()
    {
        _handler = ctx => { Track(ctx.To.Path); return ValueTask.CompletedTask; };
        brouter.OnNavigated += _handler;
    }

    public void Dispose()
    {
        if (_handler is not null) brouter.OnNavigated -= _handler;
    }
}

BrouterOptions

Matching

OptionDefaultEffect
CaseSensitivefalseWhether literal segments match case-sensitively.
IgnoreTrailingSlashtrueTreat /users and /users/ as the same path.
Constraintsempty registryCustom constraints, scoped to this DI container: o.Constraints.Register("slug", ...).

Scroll & focus

OptionDefaultEffect
ScrollBehaviorNoneToTop scrolls to the top of the page after each navigation.
ScrollToFragmenttrue/docs#install scrolls #install into view and focuses it. Wins over everything else that navigation.
RestoreScrollPositionfalseRestore each page's scroll position on Back/Forward. Takes over history.scrollRestoration.
ScrollPositionStorageMemoryWhere those positions live. SessionStorage is the recommended upgrade.
FocusOnNavigateSelectornullMove focus to this selector after navigation so assistive tech announces the new page. Try "h1".

Data & caching

OptionDefaultEffect
DefaultLoaderStaleTimenullApp-wide freshness window for routes without their own StaleTime. Null = no caching.
StaleReloadModeBackgroundHow a stale hit is served: render cached data and refresh behind it, or Blocking to treat stale as a miss.
LoaderCacheGcTime30 minHard ceiling on how old a cached result may ever be.
MaxLoaderCacheEntries50Cache size cap; oldest-written entries evicted first.
DefaultLinkPreloadNonePreload mode for links that don't set their own.
PreloadDelay50 msHow long the pointer must rest on a link before Intent preloading fires.
PreloadStaleTime30 sHow long a preloaded result stays usable on routes that don't otherwise cache.
PersistLoaderStatefalseCarry prerender loader results into the interactive pass so they don't double-fetch.
LoaderStateTypeInfoResolvernullSource-generated JSON context that makes the above trimming/AOT-safe.
DefaultKeepAliveMax1Retained-instance budget for keep-alive routes that don't set their own.

Transitions & leaving the app

OptionDefaultEffect
ViewTransitionsfalseWrap each navigation's render in document.startViewTransition.
ViewTransitionDefaultAnimationstrueShip the direction-aware glide/fade set. Lives in the bit-brouter CSS layer, so your own rules override it without !important.
ViewTransitionRespectReducedMotiontrueSwap motion for opacity crossfades under prefers-reduced-motion. Keep it on in production.
ConfirmExternalNavigationfalseAlways-on beforeunload confirmation for tab close / reload / external links. For dynamic control use SetConfirmExternalNavigationAsync instead.

Context & value types

BrouterNavigationContext

The single argument to every guard, loader and hook. Cancel() and Redirect() are only honored in the decide phase - a loader's context is informational.

MemberMeaning
From / ToSource and destination BrouterLocation.
NavigationTypePush / Replace / Pop (Back/Forward).
CancellationTokenFires when a newer navigation supersedes this one. Thread it through your async calls.
IsRevalidation / IsPreload / IsReloadWhy this loader is running, when it isn't a plain navigation. IsReload is set while ReloadAsync() rebuilds the chain - the URL is unchanged and the components were disposed and recreated.
Route / ParametersThe matched route and its bound values (set once matching has run).
Cancel() / Redirect(url)Stop the navigation, or send it elsewhere.
IsCancelled / RedirectUrlWhat a previous step in the chain already decided.

BrouterLocation

MemberMeaning
FullUri / Path / SegmentsThe absolute URI, the path alone, and the path split into segments.
Query / QueryParamsThe raw query string, and it parsed into a multi-value dictionary.
GetQuery(key) / GetQueryAll(key)First value, or every value for repeated pairs (?tag=a&tag=b).
HashThe fragment, including its #.
HistoryStateState attached to this history entry; survives Back/Forward.

Parameters, data & metadata

TypeHow you get itMembers
BrouterRouteParameters [CascadingParameter(Name = "RouteParameters")], or the <Content Context="p"> argument this[key], Contains, Get<T>, TryGet<T>, GetOrDefault<T>. Keys are case-insensitive.
BrouterRouteData [CascadingParameter] - cascaded by type The Loader result: Value, HasValue, Get<T>, TryGet<T>, GetOrDefault<T>.
BrouterRouteMeta [CascadingParameter] The route's static Meta object, same accessors. No code runs to produce it.
RouteData (framework type) [CascadingParameter] The committed navigation's framework route data, or null on not-found. For breadcrumbs and telemetry.

Outcomes, errors & query building

TypeMembers
BrouterNavigationOutcome Status, Succeeded, RedirectedTo, Exception. Returned by NavigateAsync.
BrouterErrorContext Exception, Location, RetryAsync(). The argument to every ErrorContent.
BrouterQueryBuilder Set (null removes), SetAll (multi-value), Remove, Clear, Get, Contains, ToQueryString. The argument to NavigateWithQuery; calls chain.

Route lifecycle

IBrouterRoute

Implement it on a Component-rendered page and the router finds it automatically. Every member has a no-op default, so override only what you need. Derive from BrouterRouteBase instead to also get sync overloads, an IsActive property and an automatic re-render after activation. For components that aren't the route root, take the cascaded BrouterRouteContext and call Register(this) / Unregister(this).

MemberArgumentWhen
OnActivatedAsyncBrouterRouteActivationRoute became active. IsFirstActivation distinguishes a first visit from a keep-alive return.
OnRenavigatedAsyncBrouterRouteRenavigationSame route re-committed with different parameters or query. Carries both locations.
OnDeactivatedAsyncBrouterRouteDeactivationRoute left. Reason is Hidden (keep-alive) or Disposing.
OnDeactivatingAsyncBrouterRouteDeactivatingContextBefore being left - awaited and cancellable. The component-level navigation lock.
OnRenavigatingAsyncBrouterRouteRenavigatingContextBefore re-committing with new parameters - the case a LeaveGuard can't see.

Enums

Every enum, every value

EnumValues
BrouterNavigationStatusSucceeded, Cancelled, Redirected, NotFound, Failed, Superseded
BrouterNavigationTypePush, Replace, Pop
BrouterLinkMatchPrefix, All
BrouterLinkPreloadNone, Intent, Viewport, Render
BrouterScrollModeNone, ToTop
BrouterScrollPositionStorageMemory, SessionStorage, LocalStorage
BrouterStaleReloadModeBackground, Blocking
BrouterRouteDeactivationReasonHidden, Disposing

Built-in constraints

Type constraints - validate and convert

The parameter binds a real CLR value. In a chain, the last type constraint decides the bound type.

TokenBinds
int, longint / long, invariant culture.
float, double, decimalThe matching numeric type, invariant culture.
boolbool - true/false, case-insensitive.
guidGuid, any standard format.
datetimeDateTime, invariant culture.

Validation constraints - accept or reject

The value stays a string; these only gate the match.

TokenRule
alphaASCII letters only.
min(n) / max(n) / range(a,b)Numeric bounds.
minlength(n) / maxlength(n)Text-length bounds.
length(n) / length(a,b)Exact length, or a length range.
regex(pattern)Inline pattern, case-insensitive and invariant.
file / nonfileLooks / doesn't look like a file name. nonfile is the classic static-asset filter.