You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Merge the page runtime shim, emit compile-safe page code-behind into the generated app, and add explicit BWFC global usings for local project-reference scaffolds. Include focused test updates plus Wingtip run29-run31 reports documenting the benchmark progression.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| Build result |`Failed: 183 errors, 54 warnings`|
20
+
| Acceptance tests |`Not run; blocked by build failure`|
21
+
| Final status |`FAILED`|
22
+
23
+
## Executive Summary
24
+
25
+
Run 29 was a valid fresh benchmark run from `samples\WingtipToys\WingtipToys` through the toolkit wrapper into a cleared `samples\AfterWingtipToys`, but it did not reach the acceptance bar. The toolkit correctly resolved the nested Wingtip source root, produced a full scaffold with static assets and quarantined legacy compile-surface artifacts, then stopped at a large compile break where several routed pages still depended on quarantined code-behind members and unresolved Web Forms constructs.
1. The toolkit correctly **resolved the nested effective app root**: `samples\WingtipToys\WingtipToys`.
55
+
2. Layer 1 produced a **complete scaffold plus migrated page set**: `32` files processed and `176` files written.
56
+
3. Static assets and legacy infrastructure handling improved materially: `80` static files copied, `6` compile-surface artifacts quarantined, and `4` App_Start files quarantined instead of poisoning the build immediately.
57
+
58
+
## What Didn't Work Well
59
+
60
+
1. Several routed pages still render markup that depends on **quarantined code-behind members** rather than a compiled partial class or a completed semantic rewrite.
61
+
2. The generated master shell still contains unresolved **Web Forms runtime constructs** such as `Scripts.Render`, `webopt:bundlereference`, `HttpContext.Current`, `GetUserName()`, and undeclared chrome elements like `adminLink` / `cartCount`.
62
+
3. Validator-heavy account pages still hit **generic inference / markup normalization failures** (`RZ10001`) instead of producing acceptance-ready SSR forms.
63
+
64
+
## Build Result
65
+
66
+
The first build of the freshly generated app failed:
67
+
68
+
-**Result:**`FAILED`
69
+
-**Errors:**`183`
70
+
-**Warnings:**`54`
71
+
72
+
The dominant error classes were:
73
+
74
+
1.**Missing code-behind members in compiled pages** (`CS0103`)
75
+
Examples: `Site.razor`, `ProductDetails.razor`, `ShoppingCart.razor`, and `Admin\AdminPage.razor` still reference methods, refs, or fields that only exist in `migration-artifacts\codebehind\*.txt`.
76
+
2.**Unnormalized Web Forms data-binding constructs** (`CS0103`, `CS1061`, `CS1662`)
77
+
Examples: `ShoppingCart.razor` still contains `Item`-style template expressions and object-typed fields that no longer line up with the generated templated controls.
Account pages such as `Account\AddPhoneNumber.razor` and `Account\Forgot.razor` still emit validators that Razor cannot infer cleanly.
80
+
4.**Master-shell runtime drift**
81
+
`Site.razor` still mixes preserved shell markup with APIs and members that were not normalized into runnable Blazor/BWFC equivalents.
82
+
83
+
## Acceptance Test Result
84
+
85
+
| Metric | Value |
86
+
|--------|-------|
87
+
| Total |`0`|
88
+
| Passed |`0`|
89
+
| Failed |`0`|
90
+
| Skipped |`0`|
91
+
92
+
Acceptance tests were **not run** because `samples\AfterWingtipToys\WingtipToys.csproj` did not build. This run does not meet the benchmark success criteria.
93
+
94
+
## Toolkit Gaps Exposed by This Run
95
+
96
+
1.**Code-behind recovery is still incomplete for benchmark-critical pages.**
97
+
The toolkit quarantines code-behind correctly, but it still leaves generated markup in `Site`, `ProductDetails`, `ShoppingCart`, and `AdminPage` depending on members that never get reintroduced as runnable Blazor code.
98
+
2.**Master-page shell migration still needs a Wingtip-specific hardening pass.**
99
+
The shell contract is present, but the generated `Site.razor` still preserves unresolved bundles, OWIN/auth hooks, and HTML elements whose behavior was previously supplied by master-page code-behind.
100
+
3.**Data-bound action/detail pages still need deeper semantic normalization.**
101
+
`FormView`, `GridView`, and template output still carry Web Forms expressions, row-oriented control lookup, and event wiring that are not yet converted into acceptance-ready SSR patterns.
102
+
4.**Account-form migration still needs validator and event normalization.**
103
+
The toolkit now recognizes account pages better, but validator-heavy forms still stop at compile-time rather than migrating into a buildable SSR shape.
104
+
105
+
## Screenshot Gallery
106
+
107
+
No screenshots were captured for this run because the migrated app never reached a runnable state.
108
+
109
+
## Notes
110
+
111
+
- Layer 1 evidence is captured in `migrate-output.md`.
112
+
- Build failure evidence is captured in `build-output.md`.
- This run is still useful: it confirms the toolkit is substantially better at scaffolding and compile-surface isolation, but the next feature work should focus on the remaining **runnable page semantics** rather than more scaffolding changes.
Run 30 validated the new **compiled page code-behind path** and the merged page runtime shim. The migration still does not build cleanly, but the generated WingtipToys app dropped from **183 build errors in run29 to 60 build errors in run30**.
6
+
7
+
The important behavior change is that the CLI no longer quarantines every page code-behind file. In this run it emitted **20 compiled `.razor.cs` files** and quarantined only **12 page/user-control/master-page code-behind artifacts** that still contain unsupported patterns.
1. Shim-compatible pages now emit real compiled code-behind files instead of always landing in `migration-artifacts\codebehind\`.
28
+
2. The merged `Page` / `WebFormsPageBase` runtime keeps head rendering on the shared page shim surface without forcing layout wrappers to duplicate page-service logic.
29
+
3. The fresh Wingtip run now compiles far enough that the dominant failures are narrower and more actionable than the run29 “missing page members everywhere” failure wall.
30
+
31
+
## Remaining Top Gaps
32
+
33
+
1.**Missing generated usings/type imports in emitted `.razor.cs` files**
34
+
Several compiled page partials now fail on BWFC control types such as `Button`, `Label`, `Panel`, `GridView<>`, `FormView<>`, and `RequiredFieldValidator<>`. The compiled-codebehind path needs companion using/import normalization.
35
+
36
+
2.**Legacy page-model attributes still leak into compiled code-behind**
37
+
`ProductDetails.razor.cs` still contains Web Forms model-binding attributes like `[QueryString]` and ambiguous `RouteData` references. Those need transform-time normalization before emission.
38
+
39
+
3.**Validator inference and templated markup normalization are still incomplete**
40
+
Account pages still fail with `RZ10001` for `RequiredFieldValidator`, and pages like `CheckoutReview.razor` / `ProductList.razor` still contain invalid templated markup shapes.
41
+
42
+
4.**Unresolved server-block markup still escapes into generated pages**
43
+
`Manage.razor`, `ProductList.razor`, and `ShoppingCart.razor` still contain `%`/`<%#:` fragments or malformed HTML. Those pages were correctly quarantined or left uncompiled, but the markup transforms still need stronger cleanup.
44
+
45
+
5.**Master-page shell still leaves unresolved script-manager style markup**
46
+
`Site.razor` now avoids compile-surface code-behind failure, but it still carries unresolved `Scripts` / `ScriptReference` markup that blocks the generated app build.
47
+
48
+
## Conclusion
49
+
50
+
Run 30 confirms that the new page-codebehind architecture is worth keeping: it materially reduces the Wingtip compile surface failure count and exposes the next concentrated gaps. The next follow-up should focus on **compiled code-behind import normalization** plus the existing **validator/template/server-block markup** cleanup work.
Run 31 validated the **compiled page imports fix**. The generated scaffold now writes BWFC global usings into `GlobalUsings.cs`, which means emitted page `.razor.cs` files no longer depend on NuGet-only package targets to resolve BWFC component types.
6
+
7
+
That fix worked for the original target bucket: the deduplicated `CS0246` failures dropped from **41 in run30 to 7 in run31**. The remaining `CS0246` errors are no longer the broad page-control import problem; they are now limited to deeper support-code issues such as `HttpException` and copied identity/application types in `Logic\RoleActions.cs`.
-`global using BlazorWebFormsComponents.LoginControls;`
28
+
-`global using BlazorWebFormsComponents.Validations;`
29
+
2. Emitted page code-behind no longer fails en masse on missing `Button`, `Label`, `TextBox`, `GridView<T>`, `FormView<T>`, `RequiredFieldValidator<T>`, and similar BWFC types.
30
+
3. The prior “compiled page imports” bucket is now effectively cleared, exposing the next true blockers.
31
+
32
+
## New Dominant Failure Classes
33
+
34
+
Deduplicated run31 errors are now dominated by:
35
+
36
+
1.**Missing members / semantic migration gaps (`CS0103`)** — 71 errors
37
+
Generated markup and code-behind still disagree on members/events in pages like `CheckoutReview`, `CheckoutComplete`, `ShoppingCart`, `Site`, and account flows.
38
+
39
+
2.**Analyzer/style noise promoted to errors (`IDE0007`)** — 70 errors
40
+
Copied support files such as `Logic\PayPalFunctions.cs` now enter the build and fail on style analyzers, which should not be a migration blocker.
These now stand out more clearly in copied support code and identity-related logic.
44
+
45
+
4.**Validator inference and markup cleanup remain**
46
+
The existing `RZ10001`, `RZ9980`, `RZ9981`, and `RZ9996` buckets are still present and unchanged from run30.
47
+
48
+
## Conclusion
49
+
50
+
Run 31 confirms the imports fix should be kept. It solved the specific page-codebehind namespace problem and moved the benchmark forward to the next layers:
51
+
52
+
1. semantic member alignment between generated markup and emitted code-behind,
53
+
2. compile-surface filtering or warning suppression for copied support code,
|**`WebFormsPageBase`**| Abstract base class for converted pages. Provides `Title`, `MetaDescription`, `MetaKeywords`, `IsPostBack`, and `Page` (self-reference). This is the **code-behind API** your pages inherit. |`@inherits` in `_Imports.razor`|
49
+
|**`WebFormsPageBase`**| Abstract base class for converted pages and the shared runtime shim behind `<Page />`. Provides `Title`, `MetaDescription`, `MetaKeywords`, `IsPostBack`, `Page`, `Request`, `Response`, `Session`, `Server`, `Cache`, `ClientScript`, and `ViewState`. |`@inherits` in `_Imports.razor`, inherited by `<Page />`|
50
50
|**`IPageService` / `PageService`**| Scoped service that bridges the base class and the renderer. Property setters fire change events. | Registered by `AddBlazorWebFormsComponents()`|
51
-
|**`WebFormsPage`**| Unified layout wrapper that provides NamingContainer (ID mangling), ThemeProvider (skin cascading), AND page head rendering (`<PageTitle>` + `<meta>` tags). Subscribes to `IPageService` events. |`<WebFormsPage>` wrapping `@Body` in layout |
51
+
|**`Page`**| Head renderer that inherits `WebFormsPageBase`, reads the current title/meta values, and disables postback interop because it only renders `<PageTitle>` and `<meta>` tags. |`<Page />`|
52
+
|**`WebFormsPage`**| Unified layout wrapper that provides NamingContainer (ID mangling), ThemeProvider (skin cascading), and optionally composes `<Page />` for head rendering. |`<WebFormsPage>` wrapping `@Body` in layout |
52
53
53
-
**Key point:**`WebFormsPageBase`and `WebFormsPage` are complementary, not redundant. `WebFormsPageBase`*writes* data to `IPageService`; `WebFormsPage`*reads* from `IPageService` and renders HTML. Both are needed.
54
+
**Key point:**`WebFormsPageBase`is now the shared page shim. Converted pages inherit it directly, `<Page />` reuses it for head rendering, and `<WebFormsPage>` composes `<Page />` instead of duplicating page-service subscription logic.
54
55
55
-
!!! tip "All-in-one layout component"
56
-
`<WebFormsPage>`combines naming, theming, and head rendering into a single component. You no longer need a separate `<Page />`component — `<WebFormsPage>` handles everything.
56
+
!!! tip "Default layout pattern"
57
+
`<WebFormsPage>`is still the simplest layout wrapper. It now renders `<Page />`internally by default, so you get naming, theming, and page-head rendering from one component.
57
58
58
59
## One-Time Setup
59
60
@@ -86,10 +87,7 @@ This registers `IPageService` as a scoped service.
86
87
-**Page head rendering** — Subscribes to `IPageService` and renders `<PageTitle>` + `<meta>` tags
87
88
88
89
!!! note "RenderPageHead parameter"
89
-
If you need to handle head rendering separately (e.g., with a standalone `<Page />` component), set `RenderPageHead="false"` on `<WebFormsPage>` to disable head rendering.
90
-
91
-
!!! note "Standalone Page.razor"
92
-
The `<BlazorWebFormsComponents.Page />` component is still available as a standalone head renderer for apps that don't use `<WebFormsPage>`. However, when using `<WebFormsPage>`, the standalone `<Page />` is unnecessary — don't use both, or you'll get duplicate head content.
90
+
If you need to handle head rendering separately, set `RenderPageHead="false"` on `<WebFormsPage>` and place `<Page />` yourself. Otherwise, let `<WebFormsPage>` own that composition to avoid duplicate head tags.
93
91
94
92
## Primary Approach: WebFormsPageBase
95
93
@@ -131,7 +129,7 @@ With `WebFormsPageBase` as your base class, Web Forms code-behind patterns work
131
129
This works because:
132
130
133
131
-**`Page`** returns `this` (a self-reference), so `Page.Title` resolves to `this.Title`
134
-
-**`Title`**, **`MetaDescription`**, and **`MetaKeywords`** delegate to the injected`IPageService`
132
+
-**`Title`**, **`MetaDescription`**, and **`MetaKeywords`** delegate to the scoped`IPageService` when available
Code guarded by `if (IsPostBack)` (without `!`) will **never execute** because `IsPostBack` is always `false`. During migration, search for `if (IsPostBack)` (without the negation) and flag those blocks for review — they likely contain logic that needs to be reimplemented as Blazor event handlers.
0 commit comments