Zonit.Extensions.Website 10.0.0-preview.13

This is a prerelease version of Zonit.Extensions.Website.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package Zonit.Extensions.Website --version 10.0.0-preview.13
                    
NuGet\Install-Package Zonit.Extensions.Website -Version 10.0.0-preview.13
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Zonit.Extensions.Website" Version="10.0.0-preview.13" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Zonit.Extensions.Website" Version="10.0.0-preview.13" />
                    
Directory.Packages.props
<PackageReference Include="Zonit.Extensions.Website" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Zonit.Extensions.Website --version 10.0.0-preview.13
                    
#r "nuget: Zonit.Extensions.Website, 10.0.0-preview.13"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Zonit.Extensions.Website@10.0.0-preview.13
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Zonit.Extensions.Website&version=10.0.0-preview.13&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Zonit.Extensions.Website&version=10.0.0-preview.13&prerelease
                    
Install as a Cake Tool

Zonit.Extensions.Website

The Blazor / ASP.NET Core host for the Zonit stack. It owns the request pipeline, the Razor base components, and the plumbing that carries per-request state into an interactive circuit.

NuGet Downloads

dotnet add package Zonit.Extensions.Website

Targets net10.0. Version documented here: 10.0.0-preview.10.

Two calls, two phases

AddWebsite() configures the container. UseWebsite<TApp>() mounts a Site — a URL prefix with its own middleware branch, its own MapRazorComponents<TApp>(), and its own subset of registered areas. A host can mount as many Sites as it likes.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddWebsite(o =>
{
    o.Url = "https://example.com";
    o.AddArea<HomeArea>();
    o.AddArea<AuthArea>();
});

var app = builder.Build();

// Non-root mounts FIRST — see the ordering rule below.
app.UseWebsite<App>("/admin", o =>
{
    o.Permission = "admin";
    o.AddArea<AuthArea>();
});

app.UseWebsite<App>("/", o =>
{
    o.AddArea<HomeArea>();
    o.AddArea<AuthArea>();
});

app.Run();

AddWebsite() already registers the five domain coresAddCulturesExtension(), AddAuthExtension(), AddOrganizationsExtension(), AddProjectsExtension(), AddTenantsExtension() — plus navigation, breadcrumbs, toasts, cookies and layouts. Calling any of them yourself is a double registration, not a requirement.

UseWebsite needs no companion Use* calls. Each Site branch installs its own UseRouting / UseAuthentication / UseAuthorization / UseAntiforgery and the whole Zonit middleware chain (cookies → session → workspace → project → tenant → culture). There is no app.UseAuthExtension() and no manual UseMiddleware<CultureMiddleware>() — those middlewares are internal and are wired for you.

Declare non-root mounts before the root mount. The root branch ends in a terminal UseEndpoints, so any MapWhen branch registered after it is unreachable. Getting this backwards used to fail silently with a 405 on /<sub>/_blazor/negotiate; it now throws at startup with a message telling you to reorder.

One tag in App.razor

@using Zonit.Extensions.Website.Hydration

<body>
    <WebsiteHydrator @rendermode="@RenderMode.InteractiveServer" />
    <Routes @rendermode="@RenderMode.InteractiveServer" />
    <script src="_framework/blazor.web.js"></script>
</body>

The HTTP-request scope that runs the middleware is not the SignalR circuit scope that owns interactive components, so without this the circuit starts anonymous, with default culture and no workspace — after a perfectly authenticated SSR pass. <WebsiteHydrator /> aggregates every registered IPersistentStateProvider and round-trips their snapshots through PersistentComponentState. It needs a render mode, or it only ever runs on the SSR half.

A page

@page "/orders"
@inherits PageViewBase<List<OrderRow>>
@attribute [RequirePermission("orders.read")]

<h1>@T("Orders for {0}", Workspace.Organization.Name)</h1>

@if (IsLoading)
{
    <p>@T("Loading…")</p>
}
else
{
    @foreach (var row in Model ?? [])
    {
        <p>@row.Customer</p>
    }
}

<button @onclick="@(() => Toast.AddSuccess(T("Saved")))">@T("Save")</button>

@code {
    protected override Task<List<OrderRow>?> LoadAsync(CancellationToken cancellationToken)
        => _orders.ListAsync(cancellationToken);
}

Put the usings in _Imports.razor once — Zonit.Extensions (the value objects: UrlPath, Title, Permission), Zonit.Extensions.Website (the base classes and UI providers) and Zonit.Extensions.Website.Authentication ([RequirePermission], [RequireRole]).

PageViewBase<T> gives you Model, IsLoading, a LoadAsync that re-runs when the workspace / catalog / tenant changes, and prerender→circuit model persistence. PageEditBase<T> adds an EditContext, DataAnnotations validation translated through ICultureProvider, change tracking, duplicate-submit protection and per-field [AutoSave]. Both inherit the injected provider surface (Culture, Workspace, Catalog, Tenant, Authenticated, Toast, Cookie, BreadcrumbsProvider) and T() / TM() for translation.

Every overridable lifecycle method takes a CancellationToken, and that token is genuinely cancelled when the component is disposed — override the token overload, not the framework's parameterless one.

What else is in the box

  • AreasIWebsiteArea plug-ins that contribute Razor components, navigation, middleware hooks and minimal-API endpoints, mountable on any number of Sites.
  • Layouts — string-keyed layout registry with [LayoutKey("…")], [NoLayout] and a runtime LayoutKey override.
  • Permissions[RequirePermission] / [RequireRole] with a synthetic policy provider, the "Zonit" cookie authentication scheme, and a Blazor AuthenticationStateProvider.
  • UI services — navigation, breadcrumbs, toasts (<ZonitToasts />) and cookies, plus UrlPath.ToHref(), which is mandatory for links under a non-root mount.
  • A source generator that emits AOT-safe view-model metadata for every T you use with PageViewBase<T> / PageEditBase<T>.

Upgrading from 10.0.0-preview.9

  • Five components were deleted in commit 1cfc6d8: <ZonitCulturesExtension />, <ZonitIdentityExtension />, <ZonitOrganizationsExtension />, <ZonitProjectsExtension />, <ZonitCookiesExtension />. Replace all of them with one <WebsiteHydrator />.
  • The source generator no longer emits a JsonSerializerContext. In preview.9 it did, and because Roslyn does not chain generators the emitted partial was never completed — every consumer build failed with CS0534. ViewModelMetadata<T>.JsonTypeInfo is gone with it.
  • INavigationProvider is now scoped, not singleton. Injecting it into a singleton IHostedService throws at startup; take IServiceScopeFactory and create a scope. Additions still land in the process-wide store.
  • Component cancellation tokens now really cancel on dispose. Fire-and-forget work riding on a page's token will abort when the user navigates away — pass CancellationToken.None or move it to a service.
  • PageViewBase<T> no longer overrides OnRefreshChangeAsync, which removes a duplicate LoadAsync on every provider change.
  • Model persistence and all hydration bridges no-op instead of throwing when JsonSerializer.IsReflectionEnabledByDefault is false — which the SDK sets for any PublishTrimmed publish. Read the AOT notes before publishing trimmed.

Trimming and Native AOT

The assembly ships IsTrimmable / IsAotCompatible. Two members warn at your call site: AddWebsite and ExtensionsBase.Options<T>(). Deriving from the page base classes warns about nothing.

Under PublishTrimmed (and therefore PublishAot) prerender→circuit hydration and PageViewBase model persistence silently switch themselves off — the app keeps working, but circuits start anonymous with default culture. Set <JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault> to keep them, or publish untrimmed. The full, honest account is in the aot document below.

Documentation

Installing the package writes these into your repository at build time (.zonit/extensions/website/, plus editor-specific copies under .cursor/rules/, .github/instructions/ and .claude/skills/):

Document Covers
hosting.md AddWebsite, UseWebsite<TApp>, several Sites in one app, SiteOptions, mount ordering
areas.md IWebsiteArea, IWebsiteServices, navigation contributions, the three pipeline hooks
pages.md PageBase / PageViewBase<T> / PageEditBase<T>, cancellation, EditForm wiring, auto-save
layouts.md AddWebsiteLayout, [LayoutKey], [NoLayout], ZonitRouteView, precedence
hydration.md WebsiteHydrator, the built-in bridges, writing your own IPersistentStateProvider
permissions.md [RequirePermission], [RequireRole], the claim contract, the session cookie
ui-services.md Navigation, breadcrumbs, toasts, cookies, UrlPath.ToHref()
aot.md What is genuinely trim/AOT-safe, what is annotated, what turns off

License

MIT.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (5)

Showing the top 5 NuGet packages that depend on Zonit.Extensions.Website:

Package Downloads
Zonit.Services.Dashboard

Package Description

Zonit.Services.Manager

Package Description

Zonit.SDK.Website

Package Description

Zonit.Dashboard

Zonit dashboard — single-project admin UI built on Zonit.Extensions.Website. Provides drawer/toolbar extension slots, dynamic theme switching, and a MudBlazor-based main layout registered into the website layout registry as "Dashboard.Main".

Zonit.Extensions.Website.Sitemaps

Sitemap generation for Zonit Website hosts. Plug-ins declare an ISitemapSource returning records; the package owns paging, the 50 000-URL and 50 MB limits, the sitemap index, hreflang alternates and the XML.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
10.0.0-preview.17 0 8/9/2026
10.0.0-preview.16 0 8/9/2026
10.0.0-preview.15 32 8/7/2026
10.0.0-preview.14 42 8/6/2026
10.0.0-preview.13 38 8/6/2026
10.0.0-preview.12 35 8/6/2026
10.0.0-preview.11 63 8/4/2026
10.0.0-preview.10 57 8/3/2026
10.0.0-preview.9 69 5/16/2026
10.0.0-preview.6 60 5/15/2026
10.0.0-preview.2 65 5/12/2026
10.0.0-preview.1 70 5/8/2026
0.2.12 130 5/8/2026
0.2.11 125 4/19/2026
0.2.10 140 1/22/2026
0.2.9 130 1/21/2026
0.2.8 126 1/21/2026
0.2.7 138 1/16/2026
0.2.6 130 1/15/2026
0.2.4 128 1/15/2026
Loading failed