Skip to content

CLI: Parse namespace-level tag prefix registrations from Web.config #550

Description

@csharpfritz

Context

DepartmentPortal's Web.config registers tag prefixes at the namespace level, not via src= file paths:

<pages>
  <controls>
    <add tagPrefix="uc" namespace="DepartmentPortal.Controls" assembly="DepartmentPortal" />
    <add tagPrefix="local" namespace="DepartmentPortal.Controls" assembly="DepartmentPortal" />
    <add tagPrefix="uc" src="~/Controls/QuickStats.ascx" tagName="QuickStats" />
  </controls>
</pages>

The first two entries use namespace= + assembly= to resolve any type in the DepartmentPortal.Controls namespace as a tag under the given prefix. This means <local:SectionPanel>, <local:EmployeeDataGrid>, <uc:EmployeeCard>, etc. all resolve to code-only C# server control classes — there is no .ascx file involved.

The CLI currently only handles src=-based control registrations (the third entry above, which points to an .ascx file). Namespace-level registrations are silently ignored, leaving all local:TypeName and uc:TypeName references in page markup unresolved during migration.

Impact

Every page in DepartmentPortal that uses a local: or uc: prefixed code-only control will have those tags pass through the pipeline untransformed — resulting in invalid Blazor markup that references non-existent components.

Affected pages include: Announcements.aspx, Resources.aspx, Employees.aspx, EmployeeDetail.aspx, Training.aspx, Admin/ManageEmployees.aspx.

Proposed Fix

Part 1 — Extend WebConfigTransformer

Parse <add tagPrefix namespace=... assembly=...> entries and build a prefix → namespace map in the migration context. This map should be passed into the markup transform pipeline alongside the existing src=-based control map.

Part 2 — New LocalTagNamespaceResolutionTransform (markup transform)

Create a new IMarkupTransform that:

  1. Receives the prefix → namespace map from Part 1
  2. Scans markup for <prefix:TypeName ...> elements where prefix is a registered namespace prefix
  3. Resolves the type by looking up TypeName in the discovered code-only control stubs (emitted by CodeOnlyControlScaffolder)
  4. Rewrites <local:SectionPanel ...> → <SectionPanel ...> (or the correct Blazor component reference)
  5. Handles both self-closing and block-level forms

Web.config Pattern Being Addressed

<!-- Namespace-level (NEW — not currently handled) -->
<add tagPrefix="local" namespace="DepartmentPortal.Controls" assembly="DepartmentPortal" />

<!-- Src-level (existing — already handled) -->
<add tagPrefix="uc" src="~/Controls/QuickStats.ascx" tagName="QuickStats" />

Registration

Per project conventions, the new transform must be registered in both:

  • src/BlazorWebFormsComponents.Cli/Program.cs (DI registration)
  • tests/BlazorWebFormsComponents.Cli.Tests/TestHelpers.cs (CreateDefaultPipeline())

Acceptance Criteria

  • WebConfigTransformer parses <add tagPrefix namespace=... assembly=...> entries and builds a prefix→namespace map
  • LocalTagNamespaceResolutionTransform is implemented and registered in both Program.cs and TestHelpers.cs
  • <local:SectionPanel>, <local:EmployeeDataGrid>, <uc:EmployeeCard> etc. are correctly rewritten to Blazor component references
  • Self-closing and block-level element forms are both handled
  • Transform integrates with CodeOnlyControlScaffolder output (see companion issue)
  • Tests added to tests/BlazorWebFormsComponents.Cli.Tests/

Notes

This is Tier 1 Critical Blocker P2 from the DepartmentPortal gap analysis. Without this, every local: prefixed markup tag on 6 DepartmentPortal pages passes through untransformed, producing invalid Blazor markup.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestmigration-toolkitCLI migration pipeline and toolkit enhancements

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions