|
| 1 | +# Wingtip Run 28 CLI Root-Cause Analysis |
| 2 | + |
| 3 | +## Goal |
| 4 | + |
| 5 | +Capture why the fresh `samples\AfterWingtipToys` output was broken after the `run28` migration, what had to be rewritten during repair, and what the CLI should do differently so future runs need far less manual work. |
| 6 | + |
| 7 | +## Core Finding |
| 8 | + |
| 9 | +The generated output failed for three overlapping reasons: |
| 10 | + |
| 11 | +1. The CLI preserved too much **raw Web Forms behavior**. |
| 12 | +2. The CLI converted too little **page/runtime semantics**. |
| 13 | +3. The CLI copied too much **legacy code that was not runnable in the generated Blazor SSR shape**. |
| 14 | + |
| 15 | +This was not just a master-page problem. Master pages were one part of a larger issue where the output looked structurally familiar but still behaved like partially copied Web Forms. |
| 16 | + |
| 17 | +## What the CLI Emitted |
| 18 | + |
| 19 | +### Master pages |
| 20 | + |
| 21 | +`MasterPageTransform` already does useful structural cleanup: |
| 22 | + |
| 23 | +- strips outer document scaffolding |
| 24 | +- converts `<asp:ContentPlaceHolder>` to `<ContentPlaceHolder>` |
| 25 | +- wraps output in `<MasterPage>` |
| 26 | +- extracts some `<head>` content |
| 27 | + |
| 28 | +But that is still mostly a **markup wrapper transform**, not a **runnable shell transform**. |
| 29 | + |
| 30 | +Result: generated files such as `Site.razor` still needed real migration decisions around shell composition, head assets, script/bundle references, login/cart chrome, forms, and master/content wiring. |
| 31 | + |
| 32 | +### Content pages |
| 33 | + |
| 34 | +`ContentWrapperTransform` converts: |
| 35 | + |
| 36 | +- `<asp:Content ... ContentPlaceHolderID="X">` |
| 37 | +- to `<Content ContentPlaceHolderID="X">` |
| 38 | +- and wraps the page in the master component, e.g. `<Site>...</Site>` |
| 39 | + |
| 40 | +That preserves the **shape** of content-page relationships, but not the **behavior** of the page. |
| 41 | + |
| 42 | +Result: pages still needed semantic rewrites for: |
| 43 | + |
| 44 | +- query-string binding |
| 45 | +- cart actions |
| 46 | +- login/register form behavior |
| 47 | +- navigation/redirect flows |
| 48 | +- validation behavior |
| 49 | +- selector-compatible UI for Playwright |
| 50 | + |
| 51 | +### Code-behind |
| 52 | + |
| 53 | +Generated `.razor.cs` files were copied with TODO comments, but many still contained Web Forms assumptions such as: |
| 54 | + |
| 55 | +- `Page.PreLoad` |
| 56 | +- `ViewState` |
| 57 | +- `HttpContext.Current` |
| 58 | +- `Context.GetOwinContext()` |
| 59 | +- EF `ProductContext` access |
| 60 | +- `[QueryString]` / `[RouteData]`-style patterns |
| 61 | + |
| 62 | +That left many files in an awkward middle state: present in the build, partially annotated, but not genuinely migrated. |
| 63 | + |
| 64 | +## What Actually Needed Rewriting |
| 65 | + |
| 66 | +### 1. Master-page shell files |
| 67 | + |
| 68 | +These were the highest-value runtime fixes: |
| 69 | + |
| 70 | +- `Site.razor` |
| 71 | +- parts of `Site.razor.cs` |
| 72 | + |
| 73 | +Why they broke: |
| 74 | + |
| 75 | +- generated shell still expected Web Forms lifecycle and anti-XSRF patterns |
| 76 | +- still assumed OWIN logout/auth wiring |
| 77 | +- still assumed server-managed chrome composition instead of a runnable Blazor SSR shell |
| 78 | + |
| 79 | +What the CLI should have emitted: |
| 80 | + |
| 81 | +- a valid SSR shell component |
| 82 | +- proper `ChildContent` contract |
| 83 | +- normalized head/static asset handling |
| 84 | +- Blazor-compatible login/cart/nav rendering |
| 85 | + |
| 86 | +### 2. Acceptance-path pages |
| 87 | + |
| 88 | +These pages needed semantic repair: |
| 89 | + |
| 90 | +- `Default.razor` |
| 91 | +- `About.razor` |
| 92 | +- `Contact.razor` |
| 93 | +- `ProductList.razor` |
| 94 | +- `ProductDetails.razor` |
| 95 | +- `ShoppingCart.razor` |
| 96 | +- `Account\Register.razor` |
| 97 | +- `Account\Login.razor` |
| 98 | + |
| 99 | +Why they broke: |
| 100 | + |
| 101 | +- content wrappers were converted, but page semantics were not |
| 102 | +- product lookup/query handling was still Web Forms shaped |
| 103 | +- add-to-cart flow still behaved like a routed action page instead of a usable SSR interaction |
| 104 | +- login/register behavior still assumed validator/control patterns rather than working SSR forms |
| 105 | + |
| 106 | +### 3. Build-blocker pages |
| 107 | + |
| 108 | +These pages were not all core features, but they still blocked build or runtime: |
| 109 | + |
| 110 | +- `Account\*.razor` |
| 111 | +- `Checkout\*.razor` |
| 112 | +- `Admin\AdminPage.razor` |
| 113 | +- `AddToCart.razor` |
| 114 | +- `ErrorPage.razor` |
| 115 | +- `ViewSwitcher.razor` |
| 116 | + |
| 117 | +Why they broke: |
| 118 | + |
| 119 | +- invalid leftover Web Forms markup |
| 120 | +- unsupported identity/updatepanel-era patterns |
| 121 | +- copied code-behind that was still only partly transformed |
| 122 | + |
| 123 | +### 4. Project surface |
| 124 | + |
| 125 | +The generated project also needed non-page repair: |
| 126 | + |
| 127 | +- `Program.cs` |
| 128 | +- `WingtipToys.csproj` |
| 129 | + |
| 130 | +Why they broke: |
| 131 | + |
| 132 | +- the CLI copied a broad compile surface that did not belong in a runnable repaired SSR sample |
| 133 | +- App_Start, OWIN, EF initializer/context, and legacy code-behind should not have been compiled as-is |
| 134 | + |
| 135 | +## Why the Current CLI Stops Short |
| 136 | + |
| 137 | +The existing transforms are still mostly **syntactic**: |
| 138 | + |
| 139 | +- **MasterPageTransform**: make the master page look like BWFC markup |
| 140 | +- **ContentWrapperTransform**: make content sections look like BWFC content components |
| 141 | + |
| 142 | +Wingtip needed the next layer: **semantic transforms**. |
| 143 | + |
| 144 | +## What the CLI Should Do Next |
| 145 | + |
| 146 | +### 1. Make master-page migration a first-class runnable mode |
| 147 | + |
| 148 | +The CLI should emit master pages as real BWFC shell components, not just cleaned fragments. |
| 149 | + |
| 150 | +Needed behaviors: |
| 151 | + |
| 152 | +- generate valid `ChildContent` contracts |
| 153 | +- normalize `<head>` assets into app-level references |
| 154 | +- remove or rewrite `ScriptManager`, bundle references, and server form assumptions |
| 155 | +- migrate login/cart/user chrome into Blazor-compatible behavior |
| 156 | + |
| 157 | +### 2. Stop compiling copied legacy code-behind by default |
| 158 | + |
| 159 | +Copied `.razor.cs` should be one of two things: |
| 160 | + |
| 161 | +1. fully migrated and compile-ready, or |
| 162 | +2. clearly quarantined as manual migration material |
| 163 | + |
| 164 | +The current half-migrated middle state causes most of the friction. |
| 165 | + |
| 166 | +Recommended CLI behavior: |
| 167 | + |
| 168 | +- include migrated code-behind only when transforms make it compile |
| 169 | +- otherwise exclude it from compile or place it in a manual-migration area |
| 170 | +- apply the same rule to App_Start, OWIN, EF initializer, and identity bootstrap files |
| 171 | + |
| 172 | +### 3. Add semantic transforms for common Web Forms page patterns |
| 173 | + |
| 174 | +Wingtip exposed several recurring patterns the CLI should learn directly: |
| 175 | + |
| 176 | +1. **Query-driven details pages** |
| 177 | + Convert `SelectMethod` + query-string patterns into Blazor query-bound parameters and service-backed lookups. |
| 178 | + |
| 179 | +2. **Redirect/action pages** |
| 180 | + Convert pages like `AddToCart.aspx` into a usable action flow, not a routed content page that still behaves like a page. |
| 181 | + |
| 182 | +3. **Simple account pages** |
| 183 | + Convert login/register flows into SSR-safe forms rather than preserving validator-heavy control markup that does not compile or run well. |
| 184 | + |
| 185 | +4. **Master/content contracts** |
| 186 | + When a page is wrapped in `<Site>...</Site>`, ensure the generated component contract is valid and the target master component actually expects the child content being emitted. |
| 187 | + |
| 188 | +### 4. Add compile-surface filtering |
| 189 | + |
| 190 | +The CLI should automatically recognize files that are unlikely to survive direct migration into the generated SSR app shape. |
| 191 | + |
| 192 | +For Wingtip, likely filter or quarantine: |
| 193 | + |
| 194 | +- `App_Start\*` |
| 195 | +- `Startup.Auth.cs` |
| 196 | +- `IdentityConfig.cs` |
| 197 | +- EF initializer/context bootstrapping files |
| 198 | +- copied `.razor.cs` files with unresolved Web Forms runtime assumptions |
| 199 | + |
| 200 | +### 5. Turn the benchmark findings into CLI regression tests |
| 201 | + |
| 202 | +The specific failures from run28 should become tests for: |
| 203 | + |
| 204 | +- master-page `ChildContent` / content-section wiring |
| 205 | +- runnable `Site.Master` conversion |
| 206 | +- content-page wrapping that produces valid component contracts |
| 207 | +- add-to-cart conversion |
| 208 | +- account-page form conversion |
| 209 | +- exclusion or quarantine of non-runnable legacy compile surface |
| 210 | + |
| 211 | +## Bottom Line |
| 212 | + |
| 213 | +The broken output was not just "master page conversion failed." |
| 214 | + |
| 215 | +It was: |
| 216 | + |
| 217 | +1. **master-page conversion preserved structure but not a runnable shell** |
| 218 | +2. **content-page conversion preserved wrappers but not page semantics** |
| 219 | +3. **legacy code-behind/app-start/identity/EF surface was copied into the build when it should have been transformed or quarantined** |
| 220 | + |
| 221 | +The next CLI improvements should focus on **semantic migration output**, not just cleaner markup transforms. |
| 222 | + |
| 223 | +## Recommended Follow-Up Work |
| 224 | + |
| 225 | +1. Add a dedicated **runnable master-page shell transform** for `.master` files. |
| 226 | +2. Add **pattern-based page transforms** for details, cart, and account flows. |
| 227 | +3. Add **compile-surface filtering/quarantine rules** for copied legacy files. |
| 228 | +4. Add **Wingtip benchmark regression tests** that assert those behaviors. |
0 commit comments