Control Coverage Reference

May 8, 2026 · View on GitHub

Can I migrate this control? This is the complete reference for all BWFC components and the Web Forms controls that are not covered.

For the full control translation rules (attribute mappings, code examples, before/after), see the Copilot migration skill.


Coverage Summary

MetricValue
Primary Web Forms controls58
Supporting components (field columns, styles, infrastructure, helpers)96
Total Razor components shipped154
Migration shims (compile-compatible APIs)14
Web Forms control categories covered9 (Editor, Data, Validation, Navigation, Login, AJAX, Infrastructure, Field Columns, Style Sub-Components)
Enums54
Utility/infrastructure C# classes197+
WingtipToys PoC coverage96.6% (28 of 29 control types used)
Controls with no BWFC equivalentSee Not Supported

Complexity Rating Guide

RatingMeaningTypical Effort
TrivialRemove asp: and runat="server". Done.< 1 minute
EasyRemove prefixes + add @bind or adjust one attribute.1–5 minutes
MediumData binding rewiring, template context variables, lifecycle method changes.5–30 minutes
ComplexArchitecture decisions required — data access, auth, state management.30+ minutes

Editor Controls (28 components)

ControlBWFC?ComplexityKey ChangesGotchas
AdRotatorEasyRemove asp:, runatConfigure ad data via component properties
BulletedListEasyRemove asp:, runat; bind ItemsDisplayMode and BulletStyle preserved
ButtonTrivialRemove asp:, runatOnClick is now EventCallback — no (sender, e) signature
CalendarEasyRemove asp:, runatSelectionMode is an enum — use CalendarSelectionMode.Day
ChartComplexRemove asp:, runatJS interop for rendering; use <ChartSeries>, <ChartArea>, <ChartLegend> children
CheckBoxEasyRemove asp:, runat; add @bind-CheckedTwo-way binding requires @bind-Checked
CheckBoxListEasyRemove asp:, runat; bind ItemsSame list binding pattern as DropDownList
DropDownListEasyRemove asp:, runat; bind Items + @bind-SelectedValueBind both the items collection and selected value
FileUploadEasyRemove asp:, runatUses Blazor InputFile internally — HasFile, SaveAs() work
HiddenFieldTrivialRemove asp:, runatValue property preserved
HyperLinkTrivialRemove asp:, runat; ~//URL prefix conversion is Layer 1 automated
ImageTrivialRemove asp:, runat; ~//ImageUrl preserved
ImageButtonTrivialRemove asp:, runat; ~//OnClick is EventCallback
ImageMapEasyRemove asp:, runatDefine hotspot regions via component properties
LabelTrivialRemove asp:, runatText, CssClass, AssociatedControlID preserved
LinkButtonTrivialRemove asp:, runatCommandName/CommandArgument preserved
ListBoxEasyRemove asp:, runat; bind ItemsSame binding pattern as DropDownList
LiteralTrivialRemove asp:, runatText and Mode preserved
LocalizeTrivialRemove asp:, runatResource-based text
MultiViewEasyRemove asp:, runatUse with <View> child components
PanelTrivialRemove asp:, runatRenders <div> — same as Web Forms
PlaceHolderTrivialRemove asp:, runatRenders no HTML — structural container only
RadioButtonEasyRemove asp:, runatGroupName preserved
RadioButtonListEasyRemove asp:, runat; bind ItemsSame list binding pattern
SubstitutionEasyRemove asp:, runatUses Func<HttpContext, string> callback; renders output directly
TableEasyRemove asp:, runatUse with <TableRow> and <TableCell> children
TextBoxEasyRemove asp:, runat; add @bind-TextTextMode preserved — note Multiline (not MultiLine)
ViewTrivialRemove asp:, runatUsed inside MultiView

Data Controls (8 components)

ControlBWFC?ComplexityKey ChangesGotchas
DataGridMediumItemTypeTItem; SelectMethod → delegate or ItemsBuilt-in numeric pager — does not use PagerSettings
DataListMediumItemTypeTItem; SelectMethod → delegate or ItemsTemplate Context="Item" required
DataPagerMediumRemove asp:, runatWorks with PageableData controls
DetailsViewMediumItemTypeTItem; SelectMethodDataItemSingle-record control — uses DataItem, not Items
FormViewMediumItemTypeTItem; SelectMethodDataItemRenderOuterTable="false" supported; single-record control
GridViewMediumItemTypeTItem; SelectMethod → delegate or ItemsAdd Context="Item" to templates; BoundField/TemplateField preserved
ListViewMediumItemTypeTItem; SelectMethod → delegate or ItemsLayoutTemplate, GroupTemplate, GroupItemCount all supported
RepeaterMediumItemTypeTItem; SelectMethod → delegate or ItemsSeparatorTemplate supported

Data Control Migration Pattern

All data controls follow the same pattern. When the original Web Forms markup uses SelectMethod, preserve it as a delegate reference (preferred). When it uses DataSource/DataBind(), use Items.

Option A — SelectMethod preserved as delegate (preferred when original used SelectMethod):

<!-- Web Forms -->
<asp:GridView ItemType="MyApp.Models.Product" SelectMethod="GetProducts" runat="server">
<!-- Blazor — SelectMethod as delegate -->
<GridView TItem="Product" SelectMethod="@productService.GetProducts">

Option B — Items binding (when original used DataSource/DataBind):

<!-- Web Forms -->
<asp:GridView ItemType="MyApp.Models.Product" runat="server">
<!-- Blazor -->
<GridView TItem="Product" Items="products">

Load data in the code-behind:

protected override async Task OnInitializedAsync()
{
    products = await ProductService.GetProductsAsync();
}

⚠️ DO NOT convert SelectMethod to Items= binding when the original Web Forms markup used SelectMethod. BWFC's DataBoundComponent<ItemType> has a native SelectMethod parameter of type SelectHandler<ItemType> that mirrors how Web Forms worked.

  • Collection controls (GridView, ListView, Repeater, DataList, DataGrid): use SelectMethod delegate or Items parameter
  • Single-record controls (FormView, DetailsView): use SelectMethod delegate or DataItem parameter

Validation Controls (7 components)

ControlBWFC?ComplexityKey ChangesGotchas
CompareValidatorTrivialRemove asp:, runatControlToCompare, ControlToValidate preserved
CustomValidatorEasyRemove asp:, runatOnServerValidate is EventCallback
ModelErrorMessageTrivialRemove asp:, runatModelStateKey preserved
RangeValidatorTrivialRemove asp:, runatMinimumValue, MaximumValue, Type preserved
RegularExpressionValidatorTrivialRemove asp:, runatValidationExpression preserved
RequiredFieldValidatorTrivialRemove asp:, runatControlToValidate, ErrorMessage preserved
ValidationSummaryTrivialRemove asp:, runatDisplayMode preserved

Validation controls are the easiest migration — nearly 1:1 attribute compatibility. Wrap validated forms in <EditForm> for full integration.


ControlBWFC?ComplexityKey ChangesGotchas
MenuMediumRemove asp:, runatMenuItem structure preserved; dual rendering modes (horizontal/vertical)
SiteMapPathMediumRemove asp:, runatProvide SiteMapNode data programmatically
TreeViewMediumRemove asp:, runatNode expansion state managed by component

Login Controls (7 components)

ControlBWFC?ComplexityKey ChangesGotchas
ChangePasswordComplexRemove asp:, runatWire auth provider via service; Orientation/TextLayout enums
CreateUserWizardComplexRemove asp:, runatMulti-step wizard; requires Identity service wiring
LoginComplexRemove asp:, runatWire auth provider via service
LoginNameEasyRemove asp:, runatUses AuthenticationState
LoginStatusEasyRemove asp:, runatUses AuthenticationState
LoginViewEasyRemove asp:, runatUses AuthenticationState for template switching
PasswordRecoveryComplexRemove asp:, runat3-step wizard; requires Identity service wiring

Important: BWFC provides the UI components, but the underlying authentication system must be migrated separately. ASP.NET Membership → ASP.NET Core Identity is an architecture decision (Layer 3).


AJAX Controls (5 components)

ControlBWFC?ComplexityKey ChangesGotchas
ScriptManagerTrivialRemove asp:, runatMigration stub — renders nothing. Include during migration, remove when stable.
ScriptManagerProxyTrivialRemove asp:, runatMigration stub — renders nothing. Use IJSRuntime for script registration.
TimerEasyRemove asp:, runatInterval-based tick events; no ScriptManager dependency in Blazor
UpdatePanelTrivialRemove asp:, runatRenders <div> or <span> — Blazor already does partial rendering
UpdateProgressEasyRemove asp:, runatReplace automatic UpdatePanel association with explicit bool IsLoading state

Note: ScriptManager and ScriptManagerProxy are intentional no-op stubs. They accept Web Forms attributes silently so your markup compiles, but they don't do anything. Blazor's rendering model replaces the need for AJAX partial postback infrastructure.


Infrastructure Controls (7 components)

These components support Master Page migration, page metadata, naming scopes, and layout infrastructure.

ControlBWFC?ComplexityKey ChangesGotchas
ContentEasy<asp:Content><Content>Provides content to ContentPlaceHolder slots in MasterPage
ContentPlaceHolderEasy<asp:ContentPlaceHolder><ContentPlaceHolder>Defines replaceable content regions; renders ChildContent when no Content matches
MasterPageMedium.master → MasterPage.razor layoutUses @layout EmptyLayout; supports Head render fragment for <HeadContent>
WebFormsPageEasyWrap page body in <WebFormsPage>Provides cascading values; renders <PageTitle> and <HeadContent> from IPageService
PageEasyAdd <Page /> to layoutRenders page title and meta tags from IPageService
NamingContainerEasyWrap controls that need naming scopeClientID prefixing with UseCtl00Prefix option for full Web Forms compat
EmptyLayoutTrivialUsed internally by MasterPageMinimal @Body-only layout

Master Page Migration Pattern

@* MasterPage becomes a Blazor layout *@
@inherits LayoutComponentBase
@layout MasterPage

<ContentPlaceHolder ID="MainContent">
    @Body
</ContentPlaceHolder>

Field Column Components (4 components)

Used inside GridView, DetailsView, and DataGrid for column definitions.

ControlBWFC?ComplexityKey ChangesGotchas
BoundFieldEasyRemove asp:, runatDataField, HeaderText, DataFormatString preserved
ButtonFieldEasyRemove asp:, runatCommandName, ButtonType preserved
HyperLinkFieldEasyRemove asp:, runatDataNavigateUrlFields, DataTextField preserved
TemplateFieldMediumRemove asp:, runatHeaderTemplate, ItemTemplate, EditItemTemplate all supported

Style Sub-Components (66 components)

BWFC provides declarative style sub-components matching Web Forms' pattern for applying styles to control sub-elements. Use these as child elements inside their parent control.

Pattern

<GridView TItem="Product" Items="products">
    <HeaderStyle CssClass="grid-header" BackColor="#336699" ForeColor="White" />
    <RowStyle CssClass="grid-row" />
    <AlternatingRowStyle BackColor="#F7F7F7" />
</GridView>

Style Components by Parent Control

ParentStyle Sub-Components
Calendar (9)CalendarDayHeaderStyle, CalendarDayStyle, CalendarNextPrevStyle, CalendarOtherMonthDayStyle, CalendarSelectedDayStyle, CalendarSelectorStyle, CalendarTitleStyle, CalendarTodayDayStyle, CalendarWeekendDayStyle
DataGrid (7)DataGridAlternatingItemStyle, DataGridEditItemStyle, DataGridFooterStyle, DataGridHeaderStyle, DataGridItemStyle, DataGridPagerStyle, DataGridSelectedItemStyle
DetailsView (10)DetailsViewAlternatingRowStyle, DetailsViewCommandRowStyle, DetailsViewEditRowStyle, DetailsViewEmptyDataRowStyle, DetailsViewFieldHeaderStyle, DetailsViewFooterStyle, DetailsViewHeaderStyle, DetailsViewInsertRowStyle, DetailsViewPagerStyle, DetailsViewRowStyle
FormView (7)FormViewEditRowStyle, FormViewEmptyDataRowStyle, FormViewFooterStyle, FormViewHeaderStyle, FormViewInsertRowStyle, FormViewPagerStyle, FormViewRowStyle
GridView (8)GridViewAlternatingRowStyle, GridViewEditRowStyle, GridViewEmptyDataRowStyle, GridViewFooterStyle, GridViewHeaderStyle, GridViewPagerStyle, GridViewRowStyle, GridViewSelectedRowStyle
TreeView (6)TreeViewHoverNodeStyle, TreeViewLeafNodeStyle, TreeViewNodeStyle, TreeViewParentNodeStyle, TreeViewRootNodeStyle, TreeViewSelectedNodeStyle
Login Controls (10)CheckBoxStyle, FailureTextStyle, HyperLinkStyle, InstructionTextStyle, LabelStyle, LoginButtonStyle, SuccessTextStyle, TextBoxStyle, TitleTextStyle, ValidatorTextStyle
Shared (6)AlternatingItemStyle, FooterStyle, HeaderStyle, ItemStyle, MenuItemStyle, SeparatorStyle
PagerSettings (3)DetailsViewPagerSettings, FormViewPagerSettings, GridViewPagerSettings

Utilities & Infrastructure (not Razor components)

These C# classes, base classes, and services support the component library. Migration developers should be aware of them.

Setup Requirements

// Program.cs — REQUIRED for BWFC services
builder.Services.AddBlazorWebFormsComponents();
@* _Imports.razor — RECOMMENDED for converted pages *@
@inherits WebFormsPageBase

Key Classes

ClassPurpose
WebFormsPageBaseBase class for converted pages — provides Page.Title, IsPostBack, Request, Response, Server, Session, Cache, ViewState, ClientScript, PostBack event, ResolveUrl(), GetRouteUrl()
ServiceCollectionExtensionsAddBlazorWebFormsComponents() — registers all BWFC services (SessionShim, CacheShim, ServerShim, ClientScriptShim, ScriptManagerShim, IPageService, JS interop)
BaseWebFormsComponentRoot base class — ID, ClientID, Visible, ViewState, lifecycle events (OnInit, OnLoad, OnPreRender, OnUnload), FindControl, theming, CaptureUnmatchedValues
BaseStyledComponentAdds CssClass, BackColor, ForeColor, BorderColor, BorderStyle, Font, Width, Height, ToolTip
DataBinder[Obsolete] Transitional DataBinder.Eval() support — use direct property access instead
ThemeProviderCascades ThemeConfiguration to child components for Web Forms Themes/Skins emulation
ThemeConfigurationRegisters ControlSkin entries by control type + SkinID

Helper Components

ComponentPurpose
BlazorWebFormsScriptsAuto-loads BWFC JavaScript module via dynamic import
BlazorWebFormsHeadAdds BWFC script tag to <head> via HeadContent
EvalData-binding helper for DataBinder.Eval() expressions
WebFormsFormInteractive form component — captures form data via JS interop and feeds FormShim

Infrastructure & Shim Components

BWFC provides a comprehensive shim layer that enables Web Forms API calls to compile and function in Blazor without code changes. All shims are auto-registered by AddBlazorWebFormsComponents() and auto-wired on WebFormsPageBase.

ComponentWeb Forms API PreservedHow It Works
WebFormsPageBasePage.Title, Page.MetaDescription, Page.MetaKeywords, IsPostBackBase class for all pages via @inherits in _Imports.razor
ResponseShimResponse.Redirect("~/path")Auto-strips ~/ prefix and .aspx extension; uses NavigationManager internally
RequestShimRequest.Url, Request.QueryString["key"], Request.QueryString.Get("key"), Request.CookiesReads current URL and query parameters from NavigationManager
FormShimRequest.Form["key"], Request.Form.AllKeys, Request.Form.CountDual-mode SSR+Interactive; requires <WebFormsForm> wrapper
SessionShimSession["key"], Session.Clear(), Session.Remove()Scoped in-memory dictionary — per-circuit lifetime
CacheShimCache["key"], Cache.Insert(), Cache.Remove()Singleton in-memory cache
ServerShimServer.MapPath("~/path"), Server.HtmlEncode(), Server.UrlEncode(), Server.Transfer(), Server.GetLastError(), Server.ClearError()Maps virtual paths; delegates encoding to WebUtility; routes Transfer() through NavigationManager; provides compatibility stubs for error methods
HttpUtility rewriteHttpUtility.UrlEncode(), HttpUtility.UrlDecode(), HttpUtility.HtmlEncode(), HttpUtility.HtmlDecode()CLI rewrites calls inline to WebUtility during Layer 1 migration to avoid legacy package collisions
ClientScriptShimPage.ClientScript.RegisterStartupScript(), RegisterClientScriptBlock()Registers scripts via JS interop
ScriptManagerShimScriptManager.GetCurrent(Page), RegisterStartupScript()Compatibility shim for ScriptManager API
ViewStateDictionaryViewState["key"] dictionary accessIn-memory dictionary (not serialized to page)
PostBack support__doPostBack(), IPostBackEventHandler, PostBackEventArgsPostBack event support with JS interop
ConfigurationManagerConfigurationManager.AppSettings["key"], ConnectionStrings["name"]Bridges to ASP.NET Core IConfiguration; call app.UseConfigurationManagerShim()
BundleConfigBundleTable.Bundles.Add(), ScriptBundle, StyleBundleNo-op compile shim — compiles but does nothing
RouteConfigRouteTable.Routes.MapPageRoute(), Routes.Ignore()No-op compile shim — compiles but does nothing
WebFormsForm<form> POST data captureBlazor component — wraps forms to feed FormShim

Key insight: With AddBlazorWebFormsComponents() + @inherits WebFormsPageBase, code-behind files using Response.Redirect, Session, Request, Request.QueryString.Get(), IsPostBack, Page.Title, Cache, Server.*, or ClientScript compile and run without modification. For HttpUtility, the CLI now rewrites calls inline to WebUtility during Layer 1 so the migrated app avoids legacy package collisions. This shifts ~20% of previously-manual Layer 2 work into automatic Layer 1 coverage.

Migration Shims (15)

These drop-in shims allow Web Forms API calls to compile and function in Blazor. On WebFormsPageBase, most are auto-wired — no code changes needed.

ShimWeb Forms APIUsage on WebFormsPageBase
RequestShimRequest.Cookies, Request.Form, Request.QueryString, Request.QueryString.Get(), Request.UrlRequest.* — auto-wired
FormShimRequest.Form["key"], Request.Form.AllKeys, Request.Form.CountRequest.Form["key"] — auto-wired via RequestShim
ResponseShimResponse.Redirect(), Response.CookiesResponse.Redirect() — auto-wired
SessionShimSession["key"], Session.Clear(), Session.Remove()Session["key"] — auto-wired
CacheShimCache["key"], Cache.Insert(), Cache.Remove()Cache["key"] — auto-wired
ServerShimServer.MapPath(), Server.HtmlEncode(), Server.UrlEncode(), Server.Transfer(), Server.GetLastError(), Server.ClearError()Server.* — auto-wired
HttpUtility rewriteHttpUtility.UrlEncode(), HttpUtility.UrlDecode(), HttpUtility.HtmlEncode(), HttpUtility.HtmlDecode()Let the CLI rewrite calls to WebUtility during migration
ClientScriptShimPage.ClientScript.RegisterStartupScript(), RegisterClientScriptBlock(), RegisterClientScriptInclude(), GetPostBackEventReference()ClientScript.* — auto-wired
ScriptManagerShimScriptManager.GetCurrent(Page), ScriptManager.RegisterStartupScript()Via ScriptManager.GetCurrent(this)
ConfigurationManagerConfigurationManager.AppSettings["key"], ConfigurationManager.ConnectionStrings["name"]Call app.UseConfigurationManagerShim() in Program.cs
ViewStateDictionaryViewState["key"] dictionary-style accessViewState["key"] — auto-wired
PostBack support__doPostBack(), IPostBackEventHandler, PostBackEventArgsPostBack event — auto-wired with JS interop
BundleConfigBundleTable.Bundles.Add(), ScriptBundle, StyleBundleNo-op shim — compiles but does nothing
RouteConfigRouteTable.Routes.MapPageRoute(), RouteTable.Routes.Ignore()No-op shim — compiles but does nothing
FormSubmitEventArgsN/A (new for Blazor)Used with <WebFormsForm OnSubmit="SetRequestFormData">

Custom Control Shims

These exist so Web Forms code-behind that references these types can compile:

ShimPurpose
WebControlMinimal compatibility shim for System.Web.UI.WebControls.WebControl
HtmlTextWriterMinimal compatibility shim for System.Web.UI.HtmlTextWriter
CompositeControlMinimal compatibility shim for System.Web.UI.WebControls.CompositeControl

Enums (54)

All Web Forms enums are faithfully reproduced in Enums/. Key examples: CalendarSelectionMode, TextBoxMode, GridLines, RepeatDirection, ValidationCompareOperator, FormViewMode, DetailsViewMode, ListViewItemType, ButtonType, BorderStyle, HorizontalAlign, VerticalAlign.


Controls NOT Supported by BWFC

These Web Forms controls have no BWFC equivalent. Each requires a different migration approach:

DataSource Controls — Replace with Service Injection

ControlMigration Approach
SqlDataSourceReplace with an injected service using EF Core or Dapper
ObjectDataSourceReplace with an injected service calling your business layer
EntityDataSourceReplace with an injected DbContext via DI
LinqDataSourceReplace with LINQ queries in an injected service
SiteMapDataSourceBuild navigation data programmatically or from config
XmlDataSourceLoad XML in a service; bind to component properties

Pattern:

// Instead of <asp:SqlDataSource SelectCommand="SELECT * FROM Products">
// Inject a service:
@inject IProductService ProductService

@code {
    private List<Product> products = new();

    protected override async Task OnInitializedAsync()
    {
        products = await ProductService.GetProductsAsync();
    }
}

Other Unsupported Controls

ControlMigration Approach
WizardImplement as a multi-step Blazor component with state tracking
DynamicData controlsRedesign — Blazor has no DynamicData equivalent
Web Parts (WebPartManager, WebPartZone, etc.)Redesign as Blazor components with drag-and-drop libraries
AJAX Control Toolkit extendersFind Blazor-native replacements (e.g., Radzen, MudBlazor) or build custom components
ContentPlaceHolderSupported — BWFC provides <ContentPlaceHolder>, <Content>, and <MasterPage> components. See Infrastructure Controls.

Coverage by Category — Visual Summary

Editor Controls (28)          ████████████████████████████████████████ 100% covered
Data Controls (8)             ████████████████████████████████████████ 100% covered
Validation Controls (7)       ████████████████████████████████████████ 100% covered
Navigation Controls (3)       ████████████████████████████████████████ 100% covered
Login Controls (7)            ████████████████████████████████████████ 100% covered
AJAX Controls (5)             ████████████████████████████████████████ 100% covered
Infrastructure Controls (7)   ████████████████████████████████████████ 100% covered
Field Column Components (4)   ████████████████████████████████████████ 100% covered
Style Sub-Components (66)     ████████████████████████████████████████ 100% covered
Utilities & Infrastructure    ████████████████████████████████████████ Shipped
DataSource Controls (6)       ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░   0% (by design)

DataSource controls are deliberately not covered. They represent a Web Forms-specific pattern (declarative data access in markup) that has no place in Blazor's service-injection architecture.


Cross-References