Sylin.Koan.Media.Web
Recipe-driven HTTP rendering and Entity-backed media serving for Koan.
Install
| Product | Versions |
|---|---|
| .NET |
README
Sylin.Koan.Media.Web
Serve an application's MediaEntity<T> originals and named recipes through controller-owned HTTP routes. The
reference supplies discovery, conditional/cache headers, bounded request parsing, format negotiation, and optional
persisted derivatives.
dotnet add package Sylin.Koan.Media.Web
Smallest meaningful result
using Koan.Core;
using Koan.Media;
using Koan.Media.Abstractions.Recipes;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddKoan();
var app = builder.Build();
await app.RunAsync();
public sealed class Photo : MediaEntity<Photo>;
public static class PhotoRecipes
{
[MediaRecipe("card", Description = "320px JPEG card")]
public static MediaRecipe Card() => MediaRecipe.New()
.Resize(width: 320)
.EncodeAs("jpeg", Quality.Web)
.Build();
}
One concrete MediaEntity<T> is selected automatically. The application still needs Data and Storage providers for
its Photo Entity; no registration helper or application rendering controller is required.
When the application has several media Entity types, select the one that owns the bare route deliberately:
builder.Services.AddMediaSource<Photo>();
builder.Services.AddKoan();
A custom IMediaSource is the equivalent override for a non-Entity source. Several candidates without an override
reject host startup with that correction. No candidates at all is not one: Media Web composes inertly and the routes
simply have no source until a MediaEntity<T> exists.
Routes
GET /media/{id}β original bytes;HEAD /media/{id}β original validators, content type, and length without a body;GET /media/{id}/{recipe}β named recipe or supported format shortcut;HEAD /media/{id}/{recipe}β recipe-result metadata without a body;GET /media/{id}/{recipe}?w=...&q=...β allowlisted overrides;GET /media/recipesβ materialized catalog and shortcuts; andGET /media/recipes/{name}?as=appsettingsβ canonical recipe configuration.
MediaEntitySource<TEntity> resolves the source through the Entity data path before consulting a derivative,
so active tenancy and access axes gate both cold and warm requests.
Originals and recipe results backed by seekable streams support standard byte ranges, including 206,
Content-Range, Accept-Ranges: bytes, and length-bearing 416 responses. A non-seekable custom source remains
valid for complete GET/HEAD delivery, advertises Accept-Ranges: none, and rejects a requested range correctively
rather than silently returning the full body.
Current limits
- one bare
/media/{id}route has oneIMediaSource; applications with multiple media Entity types must choose one source or own a discriminating custom source; - the default source buffers a completed render before persisting its derivative;
- derivative writes are best-effort and source deletion does not automatically reclaim derivative storage;
- there is no upload-time prewarm, signed route, or content-addressed route shape; and
- routes are currently fixed under
/media.
See the Media reference and technical companion.
Changes from Previous Version
Adoption Assessment
Assess this package against its supported frameworks, license, maintenance signals and dependency graph before making it a project standard.
Related Guides & Workflows
Learn how to evaluate, integrate, or audit this package in your .NET project.