Abstractions for Zonit.Extensions.Website library. Provides interfaces and models for navigation providers, breadcrumbs, toasts, cookies, and area definitions (Dashboard, Management, Manager, Diagnostic) for building modular web applications.
$ dotnet add package Zonit.Extensions.Website.Abstractionsdotnet add package Zonit.Extensions.Abstractions
dotnet add package Zonit.Extensions
What's included:
The Asset struct is a complete file container with embedded metadata. MIME type is always detected from binary signature (magic bytes) - never trust file extension alone.
using Zonit.Extensions;
// From file
using var fileStream = File.OpenRead("document.pdf");
Asset asset = fileStream; // Implicit conversion
// From bytes
byte[] data = await File.ReadAllBytesAsync("image.png");
Asset asset = data;
// Properties
Console.WriteLine(asset.Id); // GUID - unique identifier
Console.WriteLine(asset.OriginalName); // "document.pdf"
Console.WriteLine(asset.UniqueName); // "7a3b9c4d-1234-5678-90ab-cdef12345678.pdf"
Console.WriteLine(asset.MediaType); // "application/pdf" (detected from signature!)
Console.WriteLine(asset.Signature); // SignatureType.Pdf
Console.WriteLine(asset.Size); // "1.5 MB" (FileSize VO)
Console.WriteLine(asset.Size.Megabytes); // 1.5
Console.WriteLine(asset.CreatedAt); // 2026-01-21 12:34:56 UTC
Console.WriteLine(asset.Hash); // SHA256 base64
Console.WriteLine(asset.Md5); // MD5 base64
// Signature-based MIME detection (prevents extension spoofing)
// file.jpg that is actually WebP -> MediaType = "image/webp"
var uploaded = new Asset(bytes, "fake.jpg");
Console.WriteLine(uploaded.Signature); // SignatureType.WebP
Console.WriteLine(uploaded.MediaType); // "image/webp" (correct!)
// Implicit conversion back to Stream
Stream stream = asset;
await stream.CopyToAsync(outputStream);// Create
var size = FileSize.FromMegabytes(1.5);
var size = new FileSize(1_500_000); // bytes
// Convert
Console.WriteLine(size.Kilobytes); // 1464.84
Console.WriteLine(size.Megabytes); // 1.43
Console.WriteLine(size.Gigabytes); // 0.0014
Console.WriteLine(size); // "1.43 MB" (auto-formatted)
// Arithmetic
var total = size1 + size2;
var half = size / 2;
// Compare
if (fileSize > FileSize.FromMegabytes(10))
Console.WriteLine("File too large!");
// Constants
FileSize.OneMegabyte // 1 MB
FileSize.HundredMegabytes // 100 MB
FileSize.OneGigabyte // 1 GBSee Asset.Examples.md for complete documentation.
using Zonit.Extensions;
// Price - always non-negative (products, costs)
Price price = 99.99m;
Price discounted = price.ApplyPercentage(-10); // -10% discount
Console.WriteLine(price); // "99.99"
Console.WriteLine($"{price:C}"); // "$99.99" (culture-dependent)
// Money - can be negative (balances, transactions)
Money balance = 500.00m;
Money withdrawal = -150.00m;
Money newBalance = balance + withdrawal; // 350.00
Console.WriteLine(newBalance.IsPositive); // true
// High precision internally (8 decimal places)
Console.WriteLine(price.ToFullPrecisionString()); // "99.99000000"
// IFormattable support
Console.WriteLine($"{price:C}"); // Currency format
Console.WriteLine($"{money:N2}"); // Number with 2 decimalsThe Color struct stores colors in OKLCH format for maximum precision and perceptual uniformity, with easy conversion to other formats.
using Zonit.Extensions;
// Create from various formats
Color color = Color.FromHex("#3498db");
Color color = Color.FromRgb(52, 152, 219);
Color color = Color.FromHsl(204, 0.7, 0.53);
Color color = Color.FromOklch(0.65, 0.15, 250);
Color color = "#3498db"; // Implicit conversion
// Access in different formats
Console.WriteLine(color.Hex); // "#3498DB"
Console.WriteLine(color.CssRgb); // "rgb(52, 152, 219)"
Console.WriteLine(color.CssHsl); // "hsl(204, 70%, 53%)"
Console.WriteLine(color.CssOklch); // "oklch(65% 0.15 250)"
// RGB components
var (r, g, b) = color.Rgb; // (52, 152, 219)
var (r, g, b, a) = color.Rgba; // With alpha
// Color manipulation (OKLCH makes this perceptually uniform)
Color lighter = color.Lighten(0.1);
Color darker = color.Darken(0.1);
Color saturated = color.Saturate(0.05);
Color desaturated = color.Desaturate(0.05);
Color complement = color.Complementary; // 180° hue rotation
Color gray = color.Grayscale;
// Mix colors
Color mixed = color1.Mix(color2, 0.5); // 50% blend
// Alpha transparency
Color transparent = color.WithAlpha(0.5);
Console.WriteLine(transparent.HasAlpha); // true
// Formatting
Console.WriteLine($"{color:hex}"); // "#3498DB"
Console.WriteLine($"{color:rgb}"); // "rgb(52, 152, 219)"
Console.WriteLine($"{color:hsl}"); // "hsl(204, 70%, 53%)"
Console.WriteLine($"{color:oklch}"); // "oklch(65% 0.15 250)"Why OKLCH?
dotnet add package Zonit.Extensions.Website.Abstractions dotnet add package Zonit.Extensions.WebsiteWhat's included:
dotnet add package Zonit.Extensions.Website.MudBlazorWhat's included:
ZonitTextField<T> - MudTextField with automatic Value Object converterZonitTextArea<T> - Multiline version for longer contentSupported Value Objects: Title, Description, UrlSlug, Content, Url, Culture
Usage (type is inferred from @bind-Value):
@using Zonit.Extensions.MudBlazor
<ZonitTextField @bind-Value="Model.Title" Label="Title" />
<ZonitTextField @bind-Value="Model.Description" Label="Description" />
<ZonitTextField @bind-Value="Model.Slug" Label="URL Slug" />
@* For multiline content *@
<ZonitTextArea @bind-Value="Model.Content" Label="Content" />No need to specify T="Title" - the compiler infers the type automatically!
Add this in Routes.razor
@using Zonit.Extensions
<ZonitCookiesExtension />Services in Program.cs
builder.Services.AddCookiesExtension();App in Program.cs
app.UseCookiesExtension();@page "/"
@rendermode InteractiveServer
@using Zonit.Extensions.Website
@inject ICookieProvider Cookie
@foreach (var cookie in Cookie.GetCookies())
{
<p>@cookie.Name @cookie.Value</p>
}API
public CookieModel? Get(string key);
public CookieModel Set(string key, string value, int days = 12 * 30);
public CookieModel Set(CookieModel model);
public Task<CookieModel> SetAsync(string key, string value, int days = 12 * 30);
public Task<CookieModel> SetAsync(CookieModel model);
public List<CookieModel> GetCookies();We use SetAsync only in the Blazor circuit. It executes the JS code with the Cookies record.