Migrating from the built-in Router
Drop-in by design: @page pages keep working, authorization stays
Microsoft's code, and the built-in <Found> template ports over verbatim.
Migrate first, adopt features incrementally.
The parameter mapping
The built-in Router's companion components - RouteView,
AuthorizeRouteView, FocusOnNavigate - consume a
RouteData, not the Router itself. Brouter builds that RouteData
for every matched page and hands it to those framework components for you.
| Built-in Router stack | Brouter |
|---|---|
| <Found> + AuthorizeRouteView + fragments | Flat Authorizing/NotAuthorized fragments on <Brouter>, or an unchanged <Found Context="routeData"> for full control |
| RouteView / AuthorizeRouteView DefaultLayout | DefaultLayout on <Brouter> |
| AuthorizeRouteView Resource | Resource on <Brouter> |
| <NotFound> | <NotFound> unchanged, or a NotFoundUrl redirect |
| <Navigating> | <Navigating> unchanged |
| AppAssembly / AdditionalAssemblies / OnNavigateAsync | Same-named parameters |
Zero-template authorization
For the common case - [Authorize] on pages, a layout, fallback UI - no routing
template is needed at all. Setting any of NotAuthorized /
Authorizing / Resource routes every component-rendering route
through the framework's own AuthorizeRouteView: policy evaluation, per-page
@layout resolution and live authentication-state changes are all
Microsoft's implementation. With nothing configured, Brouter's native rendering
fails closed - instantiating an [Authorize] component throws
with guidance rather than silently skipping the check.
<Brouter AppAssembly="@typeof(App).Assembly" DefaultLayout="@typeof(MainLayout)"> <Authorizing>Checking credentials…</Authorizing> <NotAuthorized><RedirectToLogin /></NotAuthorized> <NotFound>Sorry, there's nothing here.</NotFound> <Navigating>Loading…</Navigating> </Brouter>
As with the built-in stack, the app still provides
AddCascadingAuthenticationState() and AddAuthorizationCore().
Full control: the Found template
Need arbitrary per-navigation markup around the page - telemetry publishers, a custom
AuthorizeRouteView subclass, FocusOnNavigate? The built-in
Router's <Found Context="routeData"> block ports over verbatim.
Found applies to every route that renders a Component; routes
rendering a Content fragment and outlet-hosted children deliberately ignore it
(nested outlets are Brouter's own layout model).
<Brouter AppAssembly="@typeof(App).Assembly"> <Found Context="routeData"> <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"> <NotAuthorized><RedirectToLogin /></NotAuthorized> </AuthorizeRouteView> <FocusOnNavigate RouteData="@routeData" Selector="h1" /> </Found> </Brouter>
Observing RouteData from anywhere
The committed navigation's framework RouteData (or null on not-found) is
cascaded unnamed-by-type to every descendant - breadcrumbs, telemetry and route-data
publishers can observe it with a plain [CascadingParameter], no template
plumbing.
@code { [CascadingParameter] public RouteData? RouteData { get; set; } protected override void OnParametersSet() { // fires on every committed navigation } }
A practical migration path
- Swap
<Router>for<Brouter>, keepingAppAssembly,<Found>,<NotFound>and<Navigating>as they are - or drop<Found>for the flat authorization parameters. - Register
AddBitBrouterServices()and verify the app behaves identically - templates, layouts and authorization should be unchanged. - Adopt features where they earn their keep: a guard on an admin area, a loader on a data-heavy page, view transitions app-wide.
- Hand-declare a
<Broute>shadow over a discovered@pagewhen a page needs route-level behavior without being rewritten (see @page discovery).