From 41bbd8326328a3bb4505c0d1012dd14df2ca1055 Mon Sep 17 00:00:00 2001 From: Justin Sjouw Date: Fri, 2 Oct 2026 09:00:08 +0000 Subject: [PATCH] fix(dw-render-viewmodels): the no-picture fallback hides a null DefaultImage (5.8.7) A crash reproduction or a sweep proof must blank Ecom/Picture/NoPicture for the run; the fallback also covers unguarded templates until they are fixed. --- .claude-plugin/marketplace.json | 2 +- CHANGELOG.md | 7 +++++++ manifest.json | 2 +- .../references/viewmodel-traps.md | 16 ++++++++++++++++ 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index e442b03b..645930c2 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -6,7 +6,7 @@ }, "metadata": { "description": "Claude skills for Dynamicweb 10 — organized by task domain, bundled by role.", - "version": "5.8.6" + "version": "5.8.7" }, "plugins": [ { diff --git a/CHANGELOG.md b/CHANGELOG.md index 47727fdb..59c926db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,13 @@ All notable changes to the Dynamicweb Skills plugin are recorded here. The `version` field in `.claude-plugin/marketplace.json` tracks these entries. +## [5.8.7] + +- **`dw-render-viewmodels` `viewmodel-traps.md`: the "no picture" fallback hides a null + `DefaultImage`.** With `Ecom/Picture/NoPicture` set, an image-less product renders the fallback image + and an unguarded template never fails, so a crash reproduction or a sweep proof must blank the + fallback for the run. The fallback also covers unguarded templates until they are fixed. + ## [5.8.6] - **`dw-demo-fo` `Get-FoErrorText` is safe under strict mode.** A 404 with no response body (no diff --git a/manifest.json b/manifest.json index d5a32e89..a1e73b66 100644 --- a/manifest.json +++ b/manifest.json @@ -1,6 +1,6 @@ { "version": 2, - "generatedAt": "2026-10-02T08:59:15.942Z", + "generatedAt": "2026-10-02T09:00:35.927Z", "worksOn": { "dw": { "ring": "R1", diff --git a/skills/dw-render-viewmodels/references/viewmodel-traps.md b/skills/dw-render-viewmodels/references/viewmodel-traps.md index b37b94d4..4e47f85e 100644 --- a/skills/dw-render-viewmodels/references/viewmodel-traps.md +++ b/skills/dw-render-viewmodels/references/viewmodel-traps.md @@ -32,6 +32,22 @@ string imagePath = product?.DefaultImage?.Value ?? string.Empty; | `product.ReplacementProduct` | no replacement is configured on a discontinued product | `p?.ReplacementProduct?.…` | | `Model.Item` | the paragraph has no item attached | `Model.Item?.GetString("Field")` | +**`DefaultImage` is null only when the ecommerce "no picture" fallback is empty too.** When the +`Ecom/Picture/NoPicture` setting in `GlobalSettings.Ecom.config` (`Large` and `Large_path`) names an +image, DW fills `product.DefaultImage` with it for a product with no image and no assets. The page then +renders that fallback image, and an unguarded template never meets the null. That cuts both ways: + +- **Reproducing a crash, or proving a sweep catches one:** an image-less product is not enough. Blank + `NoPicture` `Large` and `Large_path` for the run, recycle the app pool, and restore both afterwards. + With the fallback set, an unguarded `Swift-v2_ProductMedia.cshtml` rendered a clean PDP for + a zero-asset product; with it blank, the same PDP rendered a `NullReferenceException` block at HTTP 200 + [dw 10.28.12 · swift 2.4]. +- **Running templates that still lack the guard:** setting the global fallback image keeps image-less + products from crashing them until the templates are fixed. It hides the data gap, so it does not + replace the guard. + +Not measured: whether a `Medium` or `Small` fallback alone has the same effect. + Two shipped Swift 2.2 templates dereference `product.DefaultImage.Value` with no guard and are worth auditing on any solution running them, because each turns one image-less product into a whole dead surface: