|
| 1 | +# Forge — Cycle 1 Prioritized Fix List |
| 2 | + |
| 3 | +**Date:** 2026-03-06 |
| 4 | +**By:** Forge (Lead / Web Forms Reviewer) |
| 5 | +**Input:** Run 9 WingtipToys Benchmark Report, Run 9 migrated output, bwfc-migrate.ps1, BWFC component library |
| 6 | +**Purpose:** Define exactly what gets fixed in Cycle 1 to maximize the quality of the next migration run (Run 10). |
| 7 | + |
| 8 | +--- |
| 9 | + |
| 10 | +## Context |
| 11 | + |
| 12 | +Run 9 achieved 8 functional pages, 173 BWFC control instances, 0 build errors (after 7 iterations), and 667 Layer 1 transforms. The core shopping flow works. However, the report identifies recurring build failures, wasted Layer 2 effort, and missed automation opportunities. This analysis drills into the actual code to produce actionable fix items. |
| 13 | + |
| 14 | +--- |
| 15 | + |
| 16 | +## P0 — Must Fix in Cycle 1 (Build Failures Every Run) |
| 17 | + |
| 18 | +### P0-1: ItemType→TItem conversion is backwards for most data controls |
| 19 | + |
| 20 | +**What:** `bwfc-migrate.ps1` line 862–867 blindly converts ALL `ItemType="X"` attributes to `TItem="X"`. Only `DropDownList` uses the `TItem` type parameter. GridView, ListView, FormView, and DetailsView all use `ItemType`. This causes CS0246/CS0535 build errors every run that Layer 2 must manually revert. |
| 21 | + |
| 22 | +**Evidence:** In the Run 9 output, ShoppingCart.razor line 9 uses `ItemType="CartItem"` on GridView (correct), ProductList.razor line 11 uses `ItemType="Product"` on ListView (correct), but AdminPage.razor lines 9 and 55 use `TItem="Category"` / `TItem="Product"` on DropDownList (also correct). Layer 2 had to fix every GridView/ListView/FormView/DetailsView instance. |
| 23 | + |
| 24 | +**Where:** `migration-toolkit/scripts/bwfc-migrate.ps1` lines 862–867 |
| 25 | + |
| 26 | +**Fix:** Change the regex to ONLY convert `ItemType→TItem` when the enclosing tag is `<DropDownList`, `<ListBox`, `<CheckBoxList`, `<RadioButtonList`, or `<BulletedList`. For all other BWFC data controls, KEEP `ItemType` as-is. |
| 27 | + |
| 28 | +**Who:** Bishop (script owner) |
| 29 | + |
| 30 | +**Expected impact:** Eliminates the #1 recurring build failure. Saves 1-2 build-fix iterations per run. |
| 31 | + |
| 32 | +--- |
| 33 | + |
| 34 | +### P0-2: Stub mechanism discards convertible BWFC markup |
| 35 | + |
| 36 | +**What:** `Test-UnconvertiblePage` (lines 1063–1094) stubs ALL files under `Account/` and `Checkout/` paths, replacing them with empty `@page` + `<h3>not yet migrated</h3>` placeholders. But many of these pages contain valid BWFC controls that Layer 1 CAN mechanically convert. Layer 2 then has to redo ALL markup transforms from scratch. |
| 37 | + |
| 38 | +**Evidence in Run 9 output:** |
| 39 | +- `Account/Login.razor` — full BWFC markup (TextBox, CheckBox, Button, RequiredFieldValidator, Label, HyperLink, PlaceHolder, Literal) with empty code-behind. Layer 2 recreated all of this. |
| 40 | +- `Account/Register.razor` — full BWFC markup (TextBox, RequiredFieldValidator, CompareValidator, ValidationSummary, Button, Label) with empty code-behind. |
| 41 | +- `Account/Confirm.razor` — BWFC markup (PlaceHolder, HyperLink) with empty code-behind. |
| 42 | +- `Account/Manage.razor` — BWFC markup (HyperLink, PlaceHolder) with empty code-behind. |
| 43 | +- `Checkout/CheckoutReview.razor` — full BWFC markup (GridView, DetailsView, BoundField, TemplateField, Label, Button) with empty code-behind. |
| 44 | + |
| 45 | +All of this markup was converted by Layer 2 from scratch because Layer 1 stubbed it. |
| 46 | + |
| 47 | +**Where:** `migration-toolkit/scripts/bwfc-migrate.ps1` lines 1063–1094, 1176–1186 |
| 48 | + |
| 49 | +**Fix:** Change the stub mechanism to a two-part approach: |
| 50 | +1. **Always run markup transforms** on ALL .aspx files (including Account/*, Checkout/*). |
| 51 | +2. For pages matching unconvertible patterns, **stub only the code-behind** (create a minimal `partial class` with a TODO banner noting Identity/Payment work needed) instead of copying the raw Web Forms code-behind. |
| 52 | +3. Remove the `return` at line 1185 that short-circuits the entire transform pipeline. |
| 53 | + |
| 54 | +**Who:** Bishop (script owner) |
| 55 | + |
| 56 | +**Expected impact:** Recovers ~20 pages of mechanical transforms that are currently wasted. Reduces Layer 2 work by ~30 minutes per run for Account/Checkout pages since markup arrives pre-converted. |
| 57 | + |
| 58 | +--- |
| 59 | + |
| 60 | +### P0-3: Code-behind `: ComponentBase` base class not stripped |
| 61 | + |
| 62 | +**What:** When code-behinds are copied (lines 1015–1057), the original Web Forms base class (`: Page`, `: System.Web.UI.Page`, or any `: ComponentBase` that Layer 2 adds) can conflict with `@inherits WebFormsPageBase` set globally in `_Imports.razor`. This causes CS0263 "partial declarations must not specify different base classes" every run. |
| 63 | + |
| 64 | +**Where:** `migration-toolkit/scripts/bwfc-migrate.ps1` function `Copy-CodeBehind` (lines 1015–1057) |
| 65 | + |
| 66 | +**Fix:** In `Copy-CodeBehind`, add a regex to strip `: Page`, `: System.Web.UI.Page`, `: System.Web.UI.UserControl`, and `: System.Web.UI.MasterPage` base class declarations from the copied code-behind. Replace with just `: partial class ClassName`. Also strip `using System.Web.*` directives. |
| 67 | + |
| 68 | +**Who:** Bishop (script owner) |
| 69 | + |
| 70 | +**Expected impact:** Eliminates CS0263 build failures. Saves 1 build-fix iteration per run. |
| 71 | + |
| 72 | +--- |
| 73 | + |
| 74 | +## P1 — Should Fix in Cycle 1 (Reduces Build Iterations) |
| 75 | + |
| 76 | +### P1-1: Auto-inject validator type parameters |
| 77 | + |
| 78 | +**What:** RequiredFieldValidator and RegularExpressionValidator always need `Type="string"`, CompareValidator always needs `InputType="string"`, RangeValidator always needs `Type="string"`. These are deterministic — the BWFC components require explicit type parameters. Run 9 required adding these to 26 validators during build-fix iteration. |
| 79 | + |
| 80 | +**Evidence:** AdminPage.razor shows validators with `Type="string"` already injected — this was done by Layer 2. Login.razor and Register.razor also show `Type="string"` on validators. |
| 81 | + |
| 82 | +**Where:** `migration-toolkit/scripts/bwfc-migrate.ps1` — new transform step needed after `Remove-WebFormsAttributes` |
| 83 | + |
| 84 | +**Fix:** Add a `Add-ValidatorTypeParameters` function that: |
| 85 | +- Injects `Type="string"` into `<RequiredFieldValidator`, `<RegularExpressionValidator`, `<RangeValidator` tags that don't already have a `Type=` attribute. |
| 86 | +- Injects `InputType="string"` into `<CompareValidator` tags that don't already have an `InputType=` attribute. |
| 87 | + |
| 88 | +**Who:** Bishop (script owner) |
| 89 | + |
| 90 | +**Expected impact:** Eliminates ~26 build errors per WingtipToys run. Saves 1 build-fix iteration. |
| 91 | + |
| 92 | +--- |
| 93 | + |
| 94 | +### P1-2: Strip remaining `<% %>` code blocks in markup |
| 95 | + |
| 96 | +**What:** `ConvertFrom-Expressions` (lines 581–650) handles `<%# %>`, `<%: %>`, `<%= %>`, and `<%-- --%>` expressions, but `<% %>` code blocks (inline C# statements) are only flagged as manual items, not converted or stripped. These cause Razor compilation errors. |
| 97 | + |
| 98 | +**Where:** `migration-toolkit/scripts/bwfc-migrate.ps1` lines 648–655 |
| 99 | + |
| 100 | +**Fix:** Convert `<% %>` blocks to `@{ }` Razor code blocks where possible (simple single-line statements), or wrap in `@* TODO: Convert this server-side code block *@` comment for multi-line blocks. At minimum, ensure they don't cause build failures. |
| 101 | + |
| 102 | +**Who:** Bishop (script owner) |
| 103 | + |
| 104 | +**Expected impact:** Reduces build errors in pages with inline code blocks. Run 9 had 0 remaining `<% %>` in output (good), but this is a safety net for other projects. |
| 105 | + |
| 106 | +--- |
| 107 | + |
| 108 | +### P1-3: Scaffold `@using BlazorWebFormsComponents.Validations` conditionally |
| 109 | + |
| 110 | +**What:** The report notes this was a build fix item. The current scaffold (`_Imports.razor`) in Run 9 DOES include `@using BlazorWebFormsComponents.Validations` — confirming this was already fixed. However, the script should explicitly check for validators in the source scan and include this namespace automatically rather than always including it. |
| 111 | + |
| 112 | +**Where:** `migration-toolkit/scripts/bwfc-migrate.ps1` — scaffold generation (lines ~100–240) |
| 113 | + |
| 114 | +**Fix:** Already fixed in Run 9's output. Verify the scaffold template includes this namespace. If it's hardcoded, mark as done. |
| 115 | + |
| 116 | +**Who:** Bishop (verify only) |
| 117 | + |
| 118 | +**Expected impact:** Already resolved — verification confirms no regression. |
| 119 | + |
| 120 | +--- |
| 121 | + |
| 122 | +### P1-4: Add `ImageButton` to BWFC preservation watchlist |
| 123 | + |
| 124 | +**What:** History notes Run 9 had 2 lost controls, including "ImageButton to img in ShoppingCart (CRITICAL, OnClick lost)". `ImageButton` is described as "a blind spot in Test-BwfcControlPreservation." If Layer 1 or Layer 2 flattens an ImageButton to `<img>`, the `OnClick` event is silently lost. |
| 125 | + |
| 126 | +**Where:** `migration-toolkit/scripts/bwfc-migrate.ps1` — `Test-BwfcControlPreservation` function and `$BwfcComponents` list (line 914–928) |
| 127 | + |
| 128 | +**Fix:** Confirm `ImageButton` IS in the `$BwfcComponents` list (it is, at line 916). The preservation check should already catch this. The real issue may be that Layer 2 agents are flattening it. Add a specific warning in the manual review items: "ImageButton→img flattening loses OnClick event handler." |
| 129 | + |
| 130 | +**Who:** Bishop (script), Cyclops (verify ImageButton component works) |
| 131 | + |
| 132 | +**Expected impact:** Prevents silent loss of click handlers on image buttons. |
| 133 | + |
| 134 | +--- |
| 135 | + |
| 136 | +## P2 — Defer to Cycle 2 (BWFC Component Gaps) |
| 137 | + |
| 138 | +### P2-1: GridView editing mode for AdminPage CRUD |
| 139 | + |
| 140 | +**What:** The AdminPage needs full CRUD: add product (form + DropDownList), remove product (DropDownList selection). The current GridView component HAS `EditIndex`, `OnRowEditing`, `OnRowUpdating`, `OnRowDeleting`, `OnRowCancelingEdit` support (confirmed in `GridView.razor.cs` lines 37, 424, 551–620). But the AdminPage doesn't use GridView for editing — it uses standalone form controls. The BWFC components needed are already present; the gap is in Layer 2's implementation of the code-behind. |
| 141 | + |
| 142 | +**Where:** `samples/Run9WingtipToys/Admin/AdminPage.razor` (markup present, code-behind empty), `src/BlazorWebFormsComponents/GridView.razor.cs` |
| 143 | + |
| 144 | +**Fix:** No BWFC component work needed. Layer 2 needs to implement the AdminPage code-behind with EF Core CRUD operations. The DropDownList `SelectMethod` TODO pattern is correct. |
| 145 | + |
| 146 | +**Who:** Bishop (Layer 2 skill improvement for CRUD pages) |
| 147 | + |
| 148 | +**Expected impact:** Promotes AdminPage from stub → functional. Adds 1 functional page. |
| 149 | + |
| 150 | +--- |
| 151 | + |
| 152 | +### P2-2: DropDownList data binding for `SelectMethod` / `AppendDataBoundItems` |
| 153 | + |
| 154 | +**What:** AdminPage.razor uses `<DropDownList AppendDataBoundItems="true" DataTextField="CategoryName" DataValueField="CategoryID">` — the BWFC DropDownList supports `Items`, `DataTextField`, `DataValueField`, but `AppendDataBoundItems` behavior (appending to a pre-populated list) may not be implemented. |
| 155 | + |
| 156 | +**Where:** `src/BlazorWebFormsComponents/DropDownList.razor.cs` |
| 157 | + |
| 158 | +**Who:** Cyclops (verify and implement if missing) |
| 159 | + |
| 160 | +**Expected impact:** Enables correct dropdown behavior on AdminPage. |
| 161 | + |
| 162 | +--- |
| 163 | + |
| 164 | +### P2-3: `OpenAuthProviders` is not a BWFC component |
| 165 | + |
| 166 | +**What:** `Account/Login.razor` line 57 references `<OpenAuthProviders ID="OpenAuthLogin" />`. This is a WingtipToys user control (`.ascx`), not an ASP.NET built-in control. It was converted as a component with an empty code-behind. It compiles (partial class exists) but does nothing. |
| 167 | + |
| 168 | +**Where:** `samples/Run9WingtipToys/Account/OpenAuthProviders.razor.cs` |
| 169 | + |
| 170 | +**Fix:** This is expected — user controls become empty Blazor components until implemented. No BWFC work needed. Layer 2 could implement OAuth providers using ASP.NET Core's `ExternalLogins` pattern, but that's an Identity concern. |
| 171 | + |
| 172 | +**Who:** N/A (deferred to Identity implementation) |
| 173 | + |
| 174 | +**Expected impact:** None until Identity work is done. |
| 175 | + |
| 176 | +--- |
| 177 | + |
| 178 | +### P2-4: `Manage.razor` HyperLink dropped warning from Run 9 |
| 179 | + |
| 180 | +**What:** History mentions "HyperLink dropped in Manage (MINOR)". Looking at the actual `Account/Manage.razor`, it has `<HyperLink NavigateUrl="..." Text="[Change]">` etc. — these are present as BWFC components. The "dropped" warning may be stale or was a Layer 2 regression that was subsequently fixed. |
| 181 | + |
| 182 | +**Where:** `samples/Run9WingtipToys/Account/Manage.razor` |
| 183 | + |
| 184 | +**Fix:** Verify during next run. No action needed if HyperLinks are present. |
| 185 | + |
| 186 | +**Who:** Forge (verify in Run 10) |
| 187 | + |
| 188 | +--- |
| 189 | + |
| 190 | +## P3 — Defer to Cycle 3 (Larger Scope) |
| 191 | + |
| 192 | +### P3-1: ASP.NET Identity scaffolding for 15 Account pages |
| 193 | + |
| 194 | +**What:** 15 Account pages (Login, Register, Manage, Forgot, ResetPassword, Confirm, etc.) have correct BWFC markup but empty code-behinds. They need ASP.NET Core Identity wired up: `UserManager<T>`, `SignInManager<T>`, cookie auth, email confirmation flow. |
| 195 | + |
| 196 | +**Who:** Bishop (Layer 2 skill for Identity scaffold template) |
| 197 | + |
| 198 | +**Expected impact:** Promotes 15 pages from stub → functional. |
| 199 | + |
| 200 | +--- |
| 201 | + |
| 202 | +### P3-2: PayPal checkout integration for 5 Checkout pages |
| 203 | + |
| 204 | +**What:** CheckoutStart, CheckoutReview, CheckoutComplete, CheckoutCancel, CheckoutError. CheckoutReview has full BWFC markup (GridView, DetailsView) but needs a checkout service. |
| 205 | + |
| 206 | +**Who:** Out of scope for BWFC — application-level concern. |
| 207 | + |
| 208 | +--- |
| 209 | + |
| 210 | +### P3-3: DB-backed cart persistence |
| 211 | + |
| 212 | +**What:** `CartStateService` is scoped in-memory. Web Forms WingtipToys uses database-backed cart via `UsersShoppingCart` table. For production migrations, cart should survive page refreshes. |
| 213 | + |
| 214 | +**Who:** Bishop (service template improvement) |
| 215 | + |
| 216 | +--- |
| 217 | + |
| 218 | +## Summary: Cycle 1 Assignments |
| 219 | + |
| 220 | +| ID | Priority | Assignee | Item | Expected Impact | |
| 221 | +|----|----------|----------|------|-----------------| |
| 222 | +| P0-1 | **P0** | Bishop | Fix ItemType→TItem (only DropDownList uses TItem) | Eliminates #1 build failure | |
| 223 | +| P0-2 | **P0** | Bishop | Smart stub: convert markup, stub code-behind only | Recovers ~20 pages of transforms | |
| 224 | +| P0-3 | **P0** | Bishop | Strip Web Forms base classes from code-behinds | Eliminates CS0263 errors | |
| 225 | +| P1-1 | **P1** | Bishop | Auto-inject validator Type="string" / InputType="string" | Eliminates ~26 build errors | |
| 226 | +| P1-2 | **P1** | Bishop | Convert/strip remaining `<% %>` code blocks | Safety net for non-WingtipToys projects | |
| 227 | +| P1-3 | **P1** | Bishop | Verify Validations namespace in scaffold (likely done) | Verify only | |
| 228 | +| P1-4 | **P1** | Bishop+Cyclops | ImageButton preservation warning | Prevents silent OnClick loss | |
| 229 | +| P2-1 | P2 | Bishop | AdminPage CRUD code-behind | +1 functional page | |
| 230 | +| P2-2 | P2 | Cyclops | DropDownList AppendDataBoundItems | Admin dropdown behavior | |
| 231 | +| P2-3 | P2 | N/A | OpenAuthProviders (user control) | Deferred to Identity | |
| 232 | +| P2-4 | P2 | Forge | Verify Manage.razor HyperLink | Verify in Run 10 | |
| 233 | +| P3-1 | P3 | Bishop | Identity scaffolding (15 pages) | +15 functional pages | |
| 234 | +| P3-2 | P3 | N/A | PayPal checkout | Out of BWFC scope | |
| 235 | +| P3-3 | P3 | Bishop | DB-backed cart | Production readiness | |
| 236 | + |
| 237 | +**Cycle 1 target: Fix P0-1, P0-2, P0-3, P1-1, P1-4. Verify P1-3. Re-migrate. Expect: 0 build errors on first attempt, ~20 more pages with mechanical markup, 2-3 fewer build-fix iterations.** |
0 commit comments