Services, images, and caching
Service boundary
The web project references CODE Framework client libraries and Thessaly contract packages for magazine, blogs, events, consulting, people, files, subscriptions, financial data, credit cards, jobs, communication, and press releases. Most integration code uses ServiceClient.Call<TService> with typed request/response objects. Data loading appears in both controllers and models; inspect both before adding a call.
Preserve request flags, response success checks, failure information, and existing data reuse. A null response, unsuccessful business response, and thrown transport exception are different outcomes. Reuse already-loaded attachments for metadata and page images rather than adding a duplicate service request. Service implementations and databases are maintained outside this solution.
The consulting slug loader is an exception: GetServicesWithSlugsRaw performs a direct HTTP request to the configured-in-source consulting endpoint. It is used during route registration and sitemap construction. CODE Framework service overrides do not automatically redirect this direct request.
Attachments and images
Features select images from attachment categories/subcategories. For example, consulting prefers Header/Billboard, then Header/Thumbnail, then another Header; training sharing metadata prefers Header/Rectangle, then Header. Article/blog adapters choose responsive header variants. Keep selection appropriate to the use: a printed magazine cover, hero, thumbnail, and social preview are not interchangeable.
ArticleController.Image supports legacy figure names, remote redirects, binary images, and TIFF recovery. It can normalize .tif/.tiff requests to PNG names, retrieve the legacy image, convert it, add/update the PNG in the article's files, and call SaveArticle. Image delivery also has notification/logging behavior. Treat integration verification as potentially state-changing even when the browser makes a GET request.
ArticleController.AuthorPortrait has a GUID-constrained attribute route at Article/AuthorPortrait/{authorId:guid} and preserves the full rectangular portrait for the reader. AuthorPhotoSmall retains its older small-photo/fallback behavior. Missing portraits and legacy silhouettes have different presentation purposes; avoid changing one endpoint to satisfy every caller.
DynamicImageController handles service/person variants and caches URLs and bytes. DownloadController and article download actions handle file delivery and content types; article downloads can log the download through the file service.
Image processing
ImageHelper uses SkiaSharp for browser-oriented processing and managed LibTiff for the first TIFF page. ByteArrayToBitmap returns a caller-owned bitmap and does not retain the input stream. Dispose native bitmap/canvas/paint/data objects according to ownership. The default encoder returns PNG; JPEG encoding composites transparency on white. Resize modes preserve fit/fill/stretch semantics, padding, and background color. Preserve content-type/encoded-byte agreement.
The project includes Linux Skia native assets. Package presence does not prove a deployment's native runtime works: verify image endpoints in the intended runtime when changing image processing. The image regression tests exercise transparency, TIFF color/row order, resizing, encoding lifetime, fallbacks, and delivery.
Cache scopes and invalidation
Many features use static in-process dictionaries or cached models rather than one shared cache service. Lifetimes and locks vary by owner. Session uses distributed-memory storage, which is still local to this process. Do not assume cache clears or session values propagate across deployed instances.
| Owner | Examples | Invalidation consideration |
|---|---|---|
CodeHelper |
Parsed menu definitions, username/subscriber information | Menu JSON edits are easiest to validate after restart |
ConsultingServicesHelper |
Dynamic service menu data | Clear helper data to refresh menu snapshots; registered slug routes still require restart |
BlogControllerHelper |
Blog lists and index models | Cached models can be reused across requests |
ArticleController |
Image, author-image, and download URL data | Figure/portrait behavior has distinct caches |
DynamicImageController |
Service/person image URLs and bytes | Clear the owner, not just the browser cache |
IdentityHelper and account helpers |
Mapped identity and person information | Profile changes may require targeted invalidation |
IClearCache defines ClearCache(StringBuilder) and ShowCache(StringBuilder). CacheController reflects over implementing types, creates parameterless instances, and invokes these methods. Keep that activation requirement in mind before adding constructor dependencies to a cache owner.
/Cache displays diagnostic information; Clear, ClearData, and ClearImages perform different operations. ClearData invokes reflected owners and CodeHelper.ClearCache; ClearImages currently clears Vimeo thumbnails, with older disk-image-cache calls commented out. These are not universal purge operations. Cache-size reporting is an estimate rather than a memory profiler.
CacheController has no controller-level authorization attribute in current source. Do not assume operational endpoint protection from its name or menu visibility; review access controls before exposing or invoking it in a deployment. Use a local/test instance when experimenting with invalidation.
Cached model sharing also matters for metadata: SharableViewModel.GetMetaTags mutates the sharing URL. Avoid attaching request-specific host/identity state to a globally cached content model.