Milestone 6: Feature Gap Closure — 54 work items closing ~345 audit gaps#5
Conversation
…I-17) Image and Label now inherit BaseStyledComponent instead of BaseWebFormsComponent, matching the Web Forms hierarchy where both controls extend WebControl. Changes: - Image.razor.cs: BaseWebFormsComponent -> BaseStyledComponent - Image.razor: Rewritten from StringBuilder/MarkupString to proper Blazor attribute rendering with null-returning helpers (following ImageMap pattern) - Label.razor.cs: BaseWebFormsComponent -> BaseStyledComponent - Label.razor: Added class and style attribute rendering on <span> Both components gain 11 style properties: BackColor, BorderColor, BorderStyle, BorderWidth, CssClass, Font, ForeColor, Height, Width, Style, Enabled(style). No properties needed removal - both had only component-specific properties. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ay (WI-03, WI-06, WI-09, WI-12) - Button sample: Add AccessKey="b" and ToolTip="Click to submit" with usage note - GridView Default: Add CssClass="table table-striped" to demonstrate style inheritance - RequiredFieldValidator: Add Display="ValidatorDisplay.Dynamic" to second validator - Updated code display sections to match live demos Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add AccessKey and ToolTip parameters to BaseWebFormsComponent (all 53 controls) - Change BaseDataBoundComponent to inherit BaseStyledComponent (CssClass/Style for all data controls) - Remove duplicate ToolTip from 8 controls, duplicate CssClass/IStyle from 11 controls - Add ValidatorDisplay enum (Static/Dynamic/None) and Display parameter to BaseValidator - Add SetFocusOnError parameter to BaseValidator with JS interop - Change Image and Label to inherit BaseStyledComponent - Rewrite Image.razor to proper Blazor attribute rendering - Fix ValidationGroup.razor sample to use fully qualified ValidatorDisplay.Dynamic - Add 44 new bUnit tests (993 total, 0 failures) - Update sample pages for Button, GridView, and Validators - Create MILESTONE6-PLAN.md with 54 prioritized work items Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Rename the HyperLink parameter from NavigationUrl to NavigateUrl to match the ASP.NET Web Forms HyperLink control property name. Add backward-compatible [Obsolete] NavigationUrl property that forwards to NavigateUrl. Update all tests, samples, and documentation to use the new name. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add HeaderText parameter: renders bold text above the error list - Add ShowSummary parameter (default true): hides summary when false - Add ValidationGroup parameter: filters errors by matching group - Encode ValidationGroup in validator messages using unit separator - Update message parsing to strip group suffix before display Implements WI-38 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add HeaderText, HeaderTemplate, FooterText, FooterTemplate, EmptyDataText, and EmptyDataTemplate parameters to the FormView component. HeaderTemplate and FooterTemplate take precedence over their text counterparts. EmptyDataTemplate takes precedence over EmptyDataText. When no data is available, the empty data content is shown instead of the main item/pager. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ents and enums WI-31: Convert DayNameFormat and TitleFormat from string to enum types - Add DayNameFormat enum (Full, Short, FirstLetter, FirstTwoLetters, Shortest) - Add TitleFormat enum (Month, MonthYear) - Update Calendar to use enum parameters with proper defaults WI-28: Add TableItemStyle sub-components for Calendar styles - Add ICalendarStyleContainer interface with 9 TableItemStyle properties - Add 9 Calendar style sub-components (CalendarDayStyle, CalendarTitleStyle, CalendarDayHeaderStyle, CalendarTodayDayStyle, CalendarSelectedDayStyle, CalendarOtherMonthDayStyle, CalendarWeekendDayStyle, CalendarNextPrevStyle, CalendarSelectorStyle) following the existing DataList pattern - Calendar implements ICalendarStyleContainer and cascades itself - Mark legacy CSS string parameters as [Obsolete] for backward compatibility - Update razor template to render style attributes from TableItemStyle objects - Update tests and samples to use new enum types Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add SortDirection enum (Ascending/Descending) - Add GridViewSortEventArgs with SortExpression, SortDirection, and Cancel - Add SortExpression property to IColumn<T> interface and BaseColumn<T> - BoundField<T> defaults SortExpression to DataField if not explicitly set - Add AllowSorting, SortDirection, SortExpression parameters to GridView - Add Sorting/Sorted EventCallback events and Sort method to GridView - Render header cells as clickable links when AllowSorting is enabled Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add ValidationSummaryTests.razor with 4 tests: HeaderText renders in bold, no bold tag when HeaderText empty, ShowSummary=false hides summary, ShowSummary=true renders summary with errors - Add HeaderText example to ValidationSummarySample.razor - Verified HyperLink tests already use NavigateUrl (rename complete) - Verified HyperLink sample already uses NavigateUrl - NavigationUrl obsolete property is not a [Parameter], not testable via markup Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add GridViewEditEventArgs, GridViewUpdateEventArgs, GridViewDeleteEventArgs, and GridViewCancelEditEventArgs event args classes - Add EditIndex, EditRowStyle parameters to GridView - Add RowEditing, RowUpdating, RowDeleting, RowCancelingEdit event callbacks - Add EditRow, UpdateRow, DeleteRow, CancelEdit methods to GridView - Add RenderEdit method to IColumn interface and BaseColumn (virtual default) - Override RenderEdit in BoundField to render <input> elements in edit mode - Add ReadOnly parameter to BoundField - Add EditItemTemplate parameter to TemplateField - Update GridViewRow to render edit/command UI when editing is active - Auto-generate command column with Edit/Delete and Update/Cancel links Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
PasswordRecovery now exists on the current branch. Re-audited against the actual implementation in LoginControls/PasswordRecovery.razor(.cs). Results: - 36 properties match, 6 events match (42 total) - 3 properties need work (RenderOuterTable, SubmitButtonImageUrl, SubmitButtonType) - 12 properties missing (AnswerLabelText + 11 WebControl style properties) - 2 properties N/A (MailDefinition, MembershipProvider) - Health: 73.7% (up from 0%) Updated SUMMARY.md: - Login Controls category: 75.1% (up from 62.6%) - Overall health: 68.5% (up from 66.3%) - Updated unmerged branch references (only DetailsView remains) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…34/35) - GridView paging: 9 bUnit tests + Paging.razor sample - GridView sorting: 5 bUnit tests + Sorting.razor sample - GridView editing: 5 bUnit tests + InlineEditing.razor sample - Calendar: 6 style tests + 6 enum tests + TableItemStyle sample - FormView: 5 feature tests + HeaderText/EmptyDataText sample - Fix SortDirection ambiguity in sorting tests (vs Shouldly.SortDirection) - 1033 total bUnit tests, 0 failures Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…lineEditing pages (WI-45, WI-46) WI-45: Add page load tests for the 3 new GridView sample pages (Paging, Sorting, InlineEditing) to ControlSampleTests.cs. Add 3 interactive tests to InteractiveComponentTests.cs: - GridView_Paging_ClickNextPage: verifies 10 rows, clicks page 2, checks page indicator - GridView_Sorting_ClickColumnHeader: clicks Name header, verifies sort state text - GridView_InlineEditing_ClickEdit: clicks Edit link, verifies input fields and Update/Cancel WI-46: Verified existing page load tests for Calendar, FormView/Simple, FormView/Edit, and ValidationSummary are already present and covered. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…I-43, WI-44) - GridView: document paging (AllowPaging, PageSize, PageIndex, PageIndexChanged), sorting (AllowSorting, SortExpression, SortDirection, Sorting/Sorted events), and row editing (EditIndex, RowEditing, RowUpdating, RowDeleting, RowCancelingEdit) with code examples - Calendar: document TableItemStyle sub-components (CalendarDayStyle, CalendarTitleStyle, etc.), DayNameFormat/TitleFormat enums, and migration path from deprecated CSS string properties - FormView: document HeaderText/HeaderTemplate, FooterText/FooterTemplate, EmptyDataText/EmptyDataTemplate with migration examples Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…TextBox and Orientation to Menu (WI-49, WI-50) WI-49: Add CausesValidation (bool, default true) and ValidationGroup (string) parameters to CheckBox, RadioButton, and TextBox. Follows ButtonBaseComponent pattern with ValidationGroupCoordinator cascading parameter integration. WI-50: Add Orientation enum (Horizontal/Vertical) and parameter to Menu. Default is Vertical. Horizontal orientation renders list items inline via CSS class. JS interop orientation string is now dynamic. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
WI-47: Add DataTextFormatString to BaseListControl applies string.Format
to item display text for all 5 list controls
WI-48: Add AppendDataBoundItems to BaseListControl when true, data-bound
items append to static items instead of replacing them
WI-51: Add AssociatedControlID to Label renders <label for=...> instead
of <span> for accessibility
WI-52: Change Login, ChangePassword, CreateUserWizard base class to
BaseStyledComponent adds BackColor, CssClass, Font, etc. on outer
container (~30 gaps closed)
WI-53: Add 32 bUnit tests covering all P2 features
WI-54: Add sample pages for DataTextFormatString, Menu Orientation, and
Label AssociatedControlID
Also fixes 5 existing Menu test files and 3 sample pages that broke when
the Orientation parameter was added (removed redundant orientation=Vertical
attribute since Vertical is the default). Fixed 3 existing combined static +
data-bound item tests to use AppendDataBoundItems=true.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Session: 2026-02-23-p2-features Requested by: Jeffrey T. Fritz Changes: - Logged session to .ai-team/log/2026-02-23-p2-features.md - Merged 9 decision(s) from inbox into decisions.md - Consolidated Login controls decisions (Rogue gap + Cyclops fix) - Propagated updates to all 6 agent history files - Summarized older entries in cyclops, rogue, forge, colossus, jubilee history files Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| @code { | ||
| bool _validSubmit = false; | ||
| bool _invalidSubmit = false; | ||
| ForwardRef<InputBase<string>> NameRef = new ForwardRef<InputBase<string>>(); |
Check notice
Code scanning / CodeQL
Missed 'readonly' opportunity Note test
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 months ago
To fix the problem, the field NameRef should be marked readonly so it cannot be reassigned after object initialization. This preserves current behavior because the instance of ForwardRef<InputBase<string>> is created once at declaration and is not reassigned anywhere else in the snippet; the tests only modify or access its internal state via NameRef.Current, which is unaffected by the readonly modifier on the containing field.
Concretely, in src/BlazorWebFormsComponents.Test/Validations/SetFocusOnErrorTests.razor, update the field declaration on line 6 from ForwardRef<InputBase<string>> NameRef = ... to readonly ForwardRef<InputBase<string>> NameRef = .... No additional imports, methods, or other code changes are required because readonly is a simple modifier on the existing field and does not alter how it is used elsewhere.
| @@ -3,7 +3,7 @@ | ||
| @code { | ||
| bool _validSubmit = false; | ||
| bool _invalidSubmit = false; | ||
| ForwardRef<InputBase<string>> NameRef = new ForwardRef<InputBase<string>>(); | ||
| readonly ForwardRef<InputBase<string>> NameRef = new ForwardRef<InputBase<string>>(); | ||
|
|
||
| [Fact] | ||
| public void Validator_SetFocusOnError_DefaultIsFalse() |
|
|
||
| @code { | ||
| bool _invalidSubmit = false; | ||
| ForwardRef<InputBase<string>> Name = new ForwardRef<InputBase<string>>(); |
Check notice
Code scanning / CodeQL
Missed 'readonly' opportunity Note test
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 months ago
In general, to fix a "Missed 'readonly' opportunity" issue, you add the readonly modifier to the field declaration, provided the field is only assigned at declaration or in constructors of the same class. This prevents accidental reassignment later in the object’s lifetime.
For this specific file, we should modify the declaration of Name on line 4 to include the readonly keyword. No other behavior changes are required, and no additional methods or imports are needed. The change is local to src/BlazorWebFormsComponents.Test/Validations/ValidationSummary/ValidationSummaryTests.razor, within the @code block, and will not affect how Name is used (Name.Current and @Name remain valid). Only that single field needs to be updated per the reported diagnostic.
| @@ -1,7 +1,7 @@ | ||
|
|
||
| @code { | ||
| bool _invalidSubmit = false; | ||
| ForwardRef<InputBase<string>> Name = new ForwardRef<InputBase<string>>(); | ||
| readonly ForwardRef<InputBase<string>> Name = new ForwardRef<InputBase<string>>(); | ||
|
|
||
| [Fact] | ||
| public void ValidationSummary_HeaderText_RendersInBoldTag() |
| } | ||
|
|
||
| // Separate model/handler instances per test to avoid shared state | ||
| private ExampleModel exampleModel = new ExampleModel(); |
Check notice
Code scanning / CodeQL
Missed 'readonly' opportunity Note test
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 months ago
To fix the issue, we should add the readonly modifier to the exampleModel field so that its reference cannot be reassigned after initialization. This preserves existing behavior because the field is only assigned once at declaration, and the tests simply use it as the Model of the EditForm. The Name property inside ExampleModel remains mutable, so no change is needed there.
Concretely, in src/BlazorWebFormsComponents.Test/Validations/ValidationSummary/ValidationSummaryTests.razor, within the @code block near the bottom, change the declaration:
private ExampleModel exampleModel = new ExampleModel();to:
private readonly ExampleModel exampleModel = new ExampleModel();No additional methods, imports, or definitions are required, and no other fields are mentioned by CodeQL in the prompt, so they are left unchanged.
| @@ -90,7 +90,7 @@ | ||
| } | ||
|
|
||
| // Separate model/handler instances per test to avoid shared state | ||
| private ExampleModel exampleModel = new ExampleModel(); | ||
| private readonly ExampleModel exampleModel = new ExampleModel(); | ||
| private void HandleInvalidSubmit() { _invalidSubmit = true; } | ||
|
|
||
| private bool _invalidSubmit2 = false; |
| private void HandleInvalidSubmit() { _invalidSubmit = true; } | ||
|
|
||
| private bool _invalidSubmit2 = false; | ||
| ForwardRef<InputBase<string>> Name2 = new ForwardRef<InputBase<string>>(); |
Check notice
Code scanning / CodeQL
Missed 'readonly' opportunity Note test
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 months ago
To fix the problem, we should add the readonly modifier to the Name2 field declaration so that its reference cannot be reassigned after initialization. This enforces the intended immutability of the field reference while still allowing the ForwardRef<InputBase<string>> instance itself to function normally.
Concretely, in src/BlazorWebFormsComponents.Test/Validations/ValidationSummary/ValidationSummaryTests.razor, update the declaration at line 97 from ForwardRef<InputBase<string>> Name2 = new ForwardRef<InputBase<string>>(); to readonly ForwardRef<InputBase<string>> Name2 = new ForwardRef<InputBase<string>>();. No other code changes, imports, or method definitions are needed, since we are only tightening the mutability of the field reference and not changing its type or initialization.
| @@ -94,7 +94,7 @@ | ||
| private void HandleInvalidSubmit() { _invalidSubmit = true; } | ||
|
|
||
| private bool _invalidSubmit2 = false; | ||
| ForwardRef<InputBase<string>> Name2 = new ForwardRef<InputBase<string>>(); | ||
| readonly ForwardRef<InputBase<string>> Name2 = new ForwardRef<InputBase<string>>(); | ||
| private ExampleModel exampleModel2 = new ExampleModel(); | ||
| private void HandleInvalidSubmit2() { _invalidSubmit2 = true; } | ||
|
|
|
|
||
| private bool _invalidSubmit2 = false; | ||
| ForwardRef<InputBase<string>> Name2 = new ForwardRef<InputBase<string>>(); | ||
| private ExampleModel exampleModel2 = new ExampleModel(); |
Check notice
Code scanning / CodeQL
Missed 'readonly' opportunity Note test
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 months ago
To fix the issue, the exampleModel2 field should be marked readonly because it is only assigned at declaration and never reassigned. This communicates that the reference to the ExampleModel instance will not change after initialization and prevents accidental reassignment in the future.
Concretely, in src/BlazorWebFormsComponents.Test/Validations/ValidationSummary/ValidationSummaryTests.razor, locate the declaration:
private ExampleModel exampleModel2 = new ExampleModel();and change it to:
private readonly ExampleModel exampleModel2 = new ExampleModel();No additional methods, imports, or definitions are needed, and this change does not alter existing behavior: the object instance remains mutable (its Name property can still be changed), only the field reference itself becomes immutable.
| @@ -95,7 +95,7 @@ | ||
|
|
||
| private bool _invalidSubmit2 = false; | ||
| ForwardRef<InputBase<string>> Name2 = new ForwardRef<InputBase<string>>(); | ||
| private ExampleModel exampleModel2 = new ExampleModel(); | ||
| private readonly ExampleModel exampleModel2 = new ExampleModel(); | ||
| private void HandleInvalidSubmit2() { _invalidSubmit2 = true; } | ||
|
|
||
| private bool _invalidSubmit3 = false; |
| private void HandleInvalidSubmit2() { _invalidSubmit2 = true; } | ||
|
|
||
| private bool _invalidSubmit3 = false; | ||
| ForwardRef<InputBase<string>> Name3 = new ForwardRef<InputBase<string>>(); |
Check notice
Code scanning / CodeQL
Missed 'readonly' opportunity Note test
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 months ago
In general, to fix a "Field can be readonly" issue, you add the readonly modifier to the field declaration, provided the field is only assigned at its declaration or in constructors of the same class and is not intended to be reassigned later.
Here, the field in question is ForwardRef<InputBase<string>> Name3 = new ForwardRef<InputBase<string>>(); on line 102. To fix the issue without changing behavior, we should mark this field as private readonly (or just readonly, which defaults to private in this context, but matching the other fields’ style with private is clearer). No other code changes are required since uses of Name3 do not reassign the field, they only use its members (Name3.Current). The file to edit is src/BlazorWebFormsComponents.Test/Validations/ValidationSummary/ValidationSummaryTests.razor, and the only needed change is to add the readonly modifier to Name3’s declaration.
| @@ -99,7 +99,7 @@ | ||
| private void HandleInvalidSubmit2() { _invalidSubmit2 = true; } | ||
|
|
||
| private bool _invalidSubmit3 = false; | ||
| ForwardRef<InputBase<string>> Name3 = new ForwardRef<InputBase<string>>(); | ||
| private readonly ForwardRef<InputBase<string>> Name3 = new ForwardRef<InputBase<string>>(); | ||
| private ExampleModel exampleModel3 = new ExampleModel(); | ||
| private void HandleInvalidSubmit3() { _invalidSubmit3 = true; } | ||
|
|
|
|
||
| private bool _invalidSubmit3 = false; | ||
| ForwardRef<InputBase<string>> Name3 = new ForwardRef<InputBase<string>>(); | ||
| private ExampleModel exampleModel3 = new ExampleModel(); |
Check notice
Code scanning / CodeQL
Missed 'readonly' opportunity Note test
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 months ago
In general, to fix a "Missed 'readonly' opportunity" for a field, you add the readonly modifier to the field declaration when the field is only assigned at its declaration or in the class constructor. This prevents later unintended reassignments of the field reference while leaving the mutability of the object it points to unchanged.
For this specific case, in src/BlazorWebFormsComponents.Test/Validations/ValidationSummary/ValidationSummaryTests.razor, the field exampleModel3 at line 103 is initialized once and never reassigned. The best fix is to add the readonly modifier to its declaration: change private ExampleModel exampleModel3 = new ExampleModel(); to private readonly ExampleModel exampleModel3 = new ExampleModel();. No other lines, methods, or imports are required, and runtime behavior remains the same because the ExampleModel instance is still mutable; only the field reference cannot be changed after initialization.
| @@ -100,7 +100,7 @@ | ||
|
|
||
| private bool _invalidSubmit3 = false; | ||
| ForwardRef<InputBase<string>> Name3 = new ForwardRef<InputBase<string>>(); | ||
| private ExampleModel exampleModel3 = new ExampleModel(); | ||
| private readonly ExampleModel exampleModel3 = new ExampleModel(); | ||
| private void HandleInvalidSubmit3() { _invalidSubmit3 = true; } | ||
|
|
||
| private bool _invalidSubmit4 = false; |
| private void HandleInvalidSubmit3() { _invalidSubmit3 = true; } | ||
|
|
||
| private bool _invalidSubmit4 = false; | ||
| ForwardRef<InputBase<string>> Name4 = new ForwardRef<InputBase<string>>(); |
Check notice
Code scanning / CodeQL
Missed 'readonly' opportunity Note test
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 months ago
In general, to fix a "field can be readonly" issue, you add the readonly modifier to the field declaration if the field is only ever assigned in its declaration or constructors of the same class. This guarantees it cannot be accidentally modified after initialization.
For this specific case, the best fix is to add the readonly modifier to the Name4 field declaration in src/BlazorWebFormsComponents.Test/Validations/ValidationSummary/ValidationSummaryTests.razor. The declaration currently is:
ForwardRef<InputBase<string>> Name4 = new ForwardRef<InputBase<string>>();Change it to:
readonly ForwardRef<InputBase<string>> Name4 = new ForwardRef<InputBase<string>>();This leaves the initialization and all usages in the Razor tests unchanged, preserves existing functionality, and simply enforces immutability of the field reference after construction. No additional methods, imports, or definitions are needed.
| @@ -104,7 +104,7 @@ | ||
| private void HandleInvalidSubmit3() { _invalidSubmit3 = true; } | ||
|
|
||
| private bool _invalidSubmit4 = false; | ||
| ForwardRef<InputBase<string>> Name4 = new ForwardRef<InputBase<string>>(); | ||
| readonly ForwardRef<InputBase<string>> Name4 = new ForwardRef<InputBase<string>>(); | ||
| private ExampleModel exampleModel4 = new ExampleModel(); | ||
| private void HandleInvalidSubmit4() { _invalidSubmit4 = true; } | ||
|
|
|
|
||
| private bool _invalidSubmit4 = false; | ||
| ForwardRef<InputBase<string>> Name4 = new ForwardRef<InputBase<string>>(); | ||
| private ExampleModel exampleModel4 = new ExampleModel(); |
Check notice
Code scanning / CodeQL
Missed 'readonly' opportunity Note test
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 months ago
In general, to fix a "missed 'readonly' opportunity" warning, you add the readonly modifier to a field that is only assigned at its declaration or within constructors of the same class, ensuring the field reference cannot be reassigned after initialization while leaving mutations of the object it references unaffected.
For this specific case, the best fix is to add the readonly modifier to the exampleModel4 field in ValidationSummaryTests.razor. The field is declared near the bottom of the @code block as private ExampleModel exampleModel4 = new ExampleModel();. We should change this to private readonly ExampleModel exampleModel4 = new ExampleModel();. This keeps the current behavior: the ExampleModel instance itself can still have its Name property set via data binding, but the exampleModel4 reference cannot be reassigned to a different ExampleModel instance. No additional methods, imports, or definitions are needed; we only change the field declaration modifier.
| @@ -105,7 +105,7 @@ | ||
|
|
||
| private bool _invalidSubmit4 = false; | ||
| ForwardRef<InputBase<string>> Name4 = new ForwardRef<InputBase<string>>(); | ||
| private ExampleModel exampleModel4 = new ExampleModel(); | ||
| private readonly ExampleModel exampleModel4 = new ExampleModel(); | ||
| private void HandleInvalidSubmit4() { _invalidSubmit4 = true; } | ||
|
|
||
| public class ExampleModel |
| @code { | ||
| bool _validSubmit = false; | ||
| bool _invalidSubmit = false; | ||
| ForwardRef<InputBase<string>> NameRef = new ForwardRef<InputBase<string>>(); |
Check notice
Code scanning / CodeQL
Missed 'readonly' opportunity Note test
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 months ago
To fix the issue, make the _NameRef_ field immutable by adding the readonly modifier to its declaration. In general, any private field that is only ever assigned at the declaration site or within constructors can be marked readonly to prevent accidental reassignment later in the object’s lifetime.
Concretely, in src/BlazorWebFormsComponents.Test/Validations/ValidatorDisplayTests.razor, within the @code block near the top of the file, update the field declaration on line 6 from ForwardRef<InputBase<string>> NameRef = new ForwardRef<InputBase<string>>(); to readonly ForwardRef<InputBase<string>> NameRef = new ForwardRef<InputBase<string>>();. No additional usings, methods, or definitions are needed because readonly is a standard C# modifier and does not change how the existing code uses NameRef (all uses are reads, not writes).
| @@ -3,7 +3,7 @@ | ||
| @code { | ||
| bool _validSubmit = false; | ||
| bool _invalidSubmit = false; | ||
| ForwardRef<InputBase<string>> NameRef = new ForwardRef<InputBase<string>>(); | ||
| readonly ForwardRef<InputBase<string>> NameRef = new ForwardRef<InputBase<string>>(); | ||
|
|
||
| [Fact] | ||
| public void Validator_Display_DefaultIsStatic() |
…ntsTransform - ServerCodeBlockTransform (Order 510): converts <% if/else/foreach %> statement blocks to Razor @if/@foreach syntax; sanitizes raw <% %> inside @* *@ comments - TemplateFieldChildComponentsTransform (Order 620): wraps ItemStyle/HeaderStyle/ FooterStyle inside TemplateField with <ChildComponents> wrapper for BWFC compat - Both registered in Program.cs DI and TestHelpers.CreateDefaultPipeline() - 46 new tests (39 transform + 7 integration), 545 total CLI tests passing Closes Run 33 gaps #3 and #5. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(cli): compile page code-behind safely 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> * feat(cli): port NuGet asset extraction and EDMX conversion to native C# - Add NuGetStaticAssetExtractor service (replaces Migrate-NugetStaticAssets.ps1 shell-out) - Add EdmxToEfCoreConverter service (replaces Convert-EdmxToEfCore.ps1 shell-out) - Add MarkupReferencedMemberStubTransform and ValidatorGenericTypeTransform - Add deprecation warnings to all 4 PS1 scripts - Update CLI docs for direct adoption - CLI now has zero runtime PowerShell dependencies - 506 tests passing Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore: WingtipToys Run 32 benchmark output and sample improvements - Run 32 report and screenshots (25/25 tests passing) - AfterWingtipToys markup and code-behind fixes from gap analysis - Migration artifacts for WingtipToys Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(cli): add ServerCodeBlockTransform and TemplateFieldChildComponentsTransform - ServerCodeBlockTransform (Order 510): converts <% if/else/foreach %> statement blocks to Razor @if/@foreach syntax; sanitizes raw <% %> inside @* *@ comments - TemplateFieldChildComponentsTransform (Order 620): wraps ItemStyle/HeaderStyle/ FooterStyle inside TemplateField with <ChildComponents> wrapper for BWFC compat - Both registered in Program.cs DI and TestHelpers.CreateDefaultPipeline() - 46 new tests (39 transform + 7 integration), 545 total CLI tests passing Closes Run 33 gaps #3 and #5. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore: Run 33 benchmark report and gap analysis Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore: WingtipToys migration Run 34 — 25/25 tests passing - L1 migration toolkit run with ServerCodeBlockTransform (Order 510) and TemplateFieldChildComponentsTransform (Order 620) — both confirmed working - Full repair cycle: 266 → 0 build errors - Implemented CartSessionStore (singleton) + CartService (scoped) with ASP.NET Core session-key architecture so cart state survives SSR→circuit transition - Added Minimal API endpoints /AddToCart and /RemoveFromCart as HTTP 302 round-trips, making cart mutations testable with Playwright NetworkIdle - Removed @page directive from AddToCart.razor to resolve ambiguous route conflict - Run report and 5 screenshots at dev-docs/migration-tests/wingtiptoys/run34/ - Bishop history.md updated with architectural learnings Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix Run 34 shim and transform gaps Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add Run 35 gap transforms Implement CLI fixes for G1, G3, G8, and G10 by normalizing display expressions, rewriting EF6 DbContext constructors, extending ServerShim compatibility, and rewriting HttpUtility calls to WebUtility. Include transform registration updates, source-copy coverage, docs, and regression tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix DisplayExpressionTransform to emit idiomatic @expr for simple expressions Simple dotted identifiers (Item.ProductName) now emit @Item.ProductName Complex expressions (method calls, operators) still emit @(expr) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix Run 37 gaps: G1 display-expr, G2 ScriptManager strip, G4 compile-surface stubs G1: Remove String.Format from DisplayExpressionTransform negative lookahead so format expressions become @(String.Format(...)) instead of leaking as raw <%#: G2: Add ScriptManagerStripTransform (Order 255) that removes asp:ScriptManager, webopt:bundlereference, and Scripts.Render PlaceHolder blocks from master pages G4: Add CompileSurfaceStubTransform that detects pages with Identity/external API references and emits build-safe stubs, preserving originals in migration-artifacts Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Protect BWFC data control migrations Add explicit migration skill rules that forbid replacing BWFC data controls with manual HTML, and update the CLI migration pipeline to keep ListView, FormView, GridView, Repeater, and related templates on BWFC components. Preserve ItemType, add template Context="Item" normalization, and keep query-bound pages on SelectMethod wrappers so generated markup stays valid for BWFC controls. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix FormView SSR first-render and SessionShim string round-trip - FormView: establish CurrentItem during OnParametersSet() so SSR renders item content on first request - SessionShim: handle raw string session values consistently for cross-request persistence Discovered during WingtipToys migration benchmark Run 39. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add WingtipToys migration benchmark Run 39 25/25 acceptance tests passing. BWFC data controls preserved: - ProductList uses ListView (not manual HTML) - ProductDetails uses FormView (not manual HTML) - ShoppingCart uses GridView (not manual HTML) Total time: 38:34. Gaps found: FormView SSR first-render, SessionShim string round-trip, acceptance-path runtime wiring. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add WingtipToys migration benchmark reports Run 35-38 Run 35: 25/25 tests, 17:34 total Run 36: 25/25 tests, 10:12 total (best time) Run 37: 25/25 tests, 18:39 total Run 38: 25/25 tests, 21:22 total Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add regression tests for FormView SSR and SessionShim round-trip - FormView: verify CurrentItem set during OnParametersSet for SSR - SessionShim: verify string and object values round-trip correctly Prevents regression of bugs discovered in WingtipToys Run 39. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add runtime scaffold detection for benchmark migrations RuntimeDetector scans source for EF contexts, session usage, and Identity pages. ProgramCsEmitter generates matching Program.cs service registrations and middleware. Reusable across all Web Forms migrations, not WingtipToys-specific. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Run Wingtip benchmark 40 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore: log Run 40 benchmark results and merge decisions Session: Scribe memory consolidation (2026-05-07T12:43) Decisions merged: 19 inbox files (14026 bytes total) Orchestration log: bishop-run40 entry Session log: run40-benchmark entry Bishop history: summarized from 23915 → 2833 bytes Changes: - Created .squad/decisions/decisions.md (17503 bytes, all decisions consolidated) - Created .squad/orchestration-log/2026-05-07T12-43-bishop-run40.md (2125 bytes) - Created .squad/log/2026-05-07T12-43-run40-benchmark.md (1399 bytes) - Updated .squad/agents/bishop/history.md (summarized, 2833 bytes) - Updated .squad/agents/colossus/history.md (Run 40 team update appended) - Deleted .squad/decisions/inbox/* (19 files) - No deduplication conflicts found Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix BWFC data control template emission for ListView, FormView, GridView Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore: log template emission fix session Session: 2026-05-07-template-emission-fix Requested by: Bishop (via Scribe) Changes: - Merged 1 inbox decision: GridView ItemType propagation + ListView context normalization - Created orchestration log: bishop-template-emission-fix - Created session log: template-emission-fix - Updated Bishop history with transform learnings - Updated Colossus history with cross-agent notification - CLI tests: 598 → 603 passing (+5 for template emission fixes) - Commit 1bdbb1f validated in orchestration log * Add CartSessionKeyTransform for stable cart persistence Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add compile-surface quarantine for non-migratable pages Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * WingtipToys migration benchmark Run 41 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix quarantine allowlist, static files, and antiforgery gaps from Run 41 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs(ai-team): Scribe memory consolidation Session: 2026-05-07-scribe-memory-consolidation Requested by: Copilot CLI Changes: - Merged 4 inbox files to decisions.md - Deleted merged inbox files - Deduplicated team decisions - Created 4 orchestration log entries (bishop-23, bishop-22, bishop-21, rogue-1) - Updated 6 agent history files with team update - No history summarization needed (all < 15KB) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * WingtipToys migration benchmark Run 42 — 25/25, 22:00, 96% first-pass Run 42 validates quarantine allowlist, static file middleware, and SSR antiforgery fixes from Run 41. Key results: - 25/25 acceptance tests passing - 96% first-pass rate (24/25, only auth redirect needed repair) - 22:00 total time (54% faster than Run 41's 47:54) - Build: 87 initial errors → 0 in single repair round - Quarantine correctly scoped to Admin, Checkout, PayPal pages only Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Update copilot-instructions.md with CLI, migration toolkit, and migration rules Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add migration benchmark progression and sample complexity ordering - Reorder samples/ in project structure by increasing complexity - Mark WingtipToys as current benchmark focus - Add Migration Benchmark Progression table (WingtipToys → ContosoUniversity → DepartmentPortal) - Note that DepartmentPortal is the most sophisticated future target Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs(ai-team): Merge Bishop spawn decisions and logs Session: 2026-05-08-g3-g4-fixes Requested by: Jeff Changes: - Merged inbox decision: Update Copilot migration instructions with CLI and toolkit guidance - Created orchestration log for Bishop spawn (G3/G4 CLI fixes) - Created session log for memory tracking - Cleared decisions/inbox/ * Fix G3 auth redirect scaffold and G4 validator type inference Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Run 43: 25/25 acceptance tests — G3+G4 validated, runtime fixes - G3: Auth redirect scaffold with POST-based LoginHandler/RegisterHandler - G4: RequiredFieldValidator type inference (TextBox→string) - Build repair: 86→0 errors in 2 rounds - Runtime fixes: SQL Server→SQLite, seed data, route aliasing, cart page - New gaps identified: G5 (db provider), G6 (route aliasing), G7 (redirect page quarantine) - 6 screenshots captured, full report at dev-docs/migration-tests/wingtiptoys/run43/ Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix G6 route aliasing and G7 quarantine bypass Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: add FormView DataItem parameter + Content SSR fallback + Run 44 (23/25) - FormView: added DataItem parameter that wraps single item into Items collection, fixing empty rendering for single-record data binding - Content: added ShouldRenderInline fallback for SSR mode (no MasterPage) - Run 44 benchmark: 23/25 acceptance tests passing (92%) - All 2904 BWFC unit tests pass across net8.0/net9.0/net10.0 - Updated AfterWingtipToys sample with latest migration output Remaining failures: - UpdateCartQuantity: BoundField renders read-only (needs TemplateField) - RegisterAndLogin: Auth flow timeout (not BWFC-related) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs(ai-team): Merge bishop TemplateField fix decisions; orchestration & session log Session: 2026-05-08-templatefield-fix Requested by: Copilot Changes: - Merged bishop-g3-g4-fixes.md, bishop-g6-g7-fixes.md into decisions.md (2 files) - Wrote orchestration log for CLI TemplateField transform fix (Run 44 regression) - Wrote brief session log for decision merge - decisions.md now 51,720 bytes (scheduled archival next session) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: WingtipToys Run 45 — 25/25 acceptance tests, TemplateField preserved - CLI correctly preserves TemplateField columns (verified: not a CLI bug) - L2 repair maintains TemplateField with editable inputs in ShoppingCart - All 3 TemplateField columns (Quantity/TextBox, Item Total/calc, Remove/CheckBox) intact - Added CLI TemplateField preservation tests (627 CLI tests passing) - 25/25 Playwright acceptance tests pass including cart quantity update - Total runtime: ~14 minutes Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(ci): remove WingtipToys tests from CI integration tests WingtipToys acceptance tests require SQL Server and are benchmark tests, not CI tests. They should only run locally via src/WingtipToys.AcceptanceTests. - Remove ProjectReference to AfterWingtipToys from AfterBlazorServerSide.Tests.csproj - Remove WingtipToysAcceptanceTests.cs and WingtipToysPlaywrightFixture.cs - Keep standalone src/WingtipToys.AcceptanceTests/ for local benchmarks Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * ci: disable CodeQL on PRs/push, keep manual dispatch only Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * ci: disable Squad workflows, keep manual dispatch only All 11 Squad workflows (squad-ci, squad-docs, squad-heartbeat, squad-insider-release, squad-issue-assign, squad-label-enforce, squad-preview, squad-promote, squad-release, squad-triage, sync-squad-labels) now only trigger via workflow_dispatch. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Milestone 6 — Feature Gap Closure
Summary
Closes the highest-impact feature gaps identified in the 53-control audit. This milestone delivers 54 work items across 3 priority tiers, closing an estimated ~345 audit gaps and raising overall project health from ~68% to ~85%.
Branch:
milestone6/feature-implementationCommits: 18 (excluding .ai-team housekeeping)
Files changed: 168 | +5,712 / -1,775 lines
Tests: 1,065 passing (0 failures)
P0 — Base Class Fixes (~180 gaps closed)
AccessKeyonBaseWebFormsComponentToolTiponBaseWebFormsComponentDataBoundComponent<T>inheritsBaseStyledComponentValidatorDisplayenum +DisplayonBaseValidatorSetFocusOnErroronBaseValidatorImagebase class →BaseStyledComponentLabelbase class →BaseStyledComponentP1 — Individual Control Improvements (~120 gaps closed)
GridView Overhaul
Other Controls
NavigationUrl→NavigateUrl(with backward compat)Docs, Audit & Integration Tests
P2 — Nice-to-Have (~45 gaps closed)
DataTextFormatStringon newBaseListControl<T>(all 5 list controls)AppendDataBoundItemsonBaseListControl<T>CausesValidation+ValidationGroupon CheckBox, RadioButton, TextBoxOrientationenum (Horizontal/Vertical)AssociatedControlID(renders<label for>for accessibility)BaseStyledComponent(~30 gaps)Testing
Breaking Changes
HyperLink.NavigationUrlrenamed toNavigateUrl(old property forwarded via[Obsolete])DayStyleCss) marked[Obsolete]in favor of<DayStyle>sub-componentsAppendDataBoundItemsdefaults tofalse— data-binding now replaces static items unlessAppendDataBoundItems="true"(matches Web Forms behavior)