Files
Plataforma-de-desarrolladores/AGENTS_WEBFORMS_ESTRUCTURA.md
Jorge Luis caudillo esparza e8160eefba --documentos
2026-09-27 14:44:12 -07:00

16 KiB

AGENTS_WEBFORMS_ESTRUCTURA.md

These rules complement AGENTS.md and are mandatory whenever the task changes WebForms pages, the master page, login, session behavior, bundles, assets, configuration, controls, or the application shell.

Asset folder rules

The following folders are legacy visual dependencies and must be copied as complete folders:

Styles/
Scripts/
Metronic/

Do not replace Metronic with Bootstrap-only layout. Do not upgrade Metronic unless the user explicitly asks. Do not remove old scripts just because they look unused; only remove references from bundles when they are not used by the master/login flow.


Bundle rules

The project must implement only the bundle methods needed by the current Site.master and login page.

Do not bring every old bundle method from the legacy project. Do not add unused bundle groups just because they existed before. Do not add duplicate bundle keys. Do not add empty bundle methods.

Allowed current bundle keys are the ones actually rendered by master/login, especially:

~/bundles/modernizr
~/bundles/scripts
~/bundles/highcharts
~/Metronic/assets/global/scripts/JSV1
~/Metronic/assets/global/css/cssV1

WebForms/AjaxControlToolkit support bundles are allowed only when referenced by ScriptManager or required by WebForms controls:

~/bundles/jquery
~/bundles/WebFormsJs
~/bundles/MsAjaxJs
~/Content/AjaxControlToolkit/Styles/Bundle

Rules:

  • If Site.master or Login.aspx does not render a bundle, do not add it.
  • If a bundle exists only for old pages not migrated yet, leave it out until the page needs it.
  • Prefer preserving original asset paths from Styles, Scripts, and Metronic.
  • Use CssRewriteUrlTransform for CSS bundles that reference fonts, images, or relative URLs.
  • Load CSS/JS files for server controls and UserControls globally from Styles/ and Scripts/ through BundleConfig and the master page, even when no instance is present; never inject these files from controls. Remove duplicate page references when moving a resource to a global bundle. This does not prohibit individual server-triggered calls through the existing RegistraScript.

WebForms page rules

All normal .aspx pages must use Site.master, except the login page.

Normal pages:

  • Must include MasterPageFile="~/Site.master".
  • Must not include <html>, <head>, <body>, or <form>.
  • Must use <asp:Content> controls.
  • Should inherit from ClsPaginaBase or the current C# page base class.
  • Must not connect directly to SQL classes.
  • Must call contracts/services for data, authentication, permissions, catalogs, menus, and user context.

Public registration exception:

  • Pages/Security/RegistroCliente.aspx, RegistroPendiente.aspx and VerificarCorreo.aspx may be standalone public pages with their own form runat="server".
  • RegistroCliente.aspx keeps its two-step draft in encrypted ViewState and persists only after all client/company validations pass.
  • All persistence continues through contracts/services/repositories and stored procedures.

Login page:

  • Is the only page allowed to have its own full HTML structure.
  • May inherit from System.Web.UI.Page or its own login base class.
  • Must not inherit from ClsPaginaBase if that base class requires an authenticated session.
  • Must use IAuthContract or the current auth contract.
  • Must create a dummy session until real authentication is implemented.
  • Must not hardcode real database login logic in Login.aspx.cs.

Important naming rule:

  • Do not create both Login.aspx and LogIn.aspx.
  • If the starter already uses LogIn.aspx, keep that name and keep Web.config consistent.
  • If creating from scratch, prefer Login.aspx, but update Web.config, redirects, and links consistently.

Master page rules

Site.master owns the main HTML structure.

Rules:

  • Site.master owns the only main <form runat="server">.
  • Site.master must keep the Metronic layout structure.
  • Keep the sidebar/header/page-content structure similar to the original Metronic project.
  • Do not restore the hidden search box from the old header.
  • Keep the actions button if it exists in the selected master layout.
  • Do not hardcode real user/menu database logic inside Site.master.cs.
  • User data must come from a contract/service.
  • Menu data must come from a contract/service.
  • Breadcrumb/title/layout data must come from a contract/service when dynamic.
  • Do not use <title id="Titulo" runat="server">.
  • Prefer <title><%: Page.Title %></title>.
  • If a generated starter currently uses a title literal, replace it with Page.Title unless there is a specific reason to keep the literal.

Current preferred contracts:

IAuthContract
IUserSessionContract
IMenuContract
IMasterPageContract

If old names such as IUserContextProvider or IMenuProvider exist, migrate them to the current contract naming or create adapters. Do not keep two competing naming systems.


ContentPlaceHolder rules

Site.master must use short placeholder IDs.

Preferred final placeholder IDs:

H = page-specific head/CSS content
C = main page content
J = page-specific JavaScript

Example in Site.master:

<asp:ContentPlaceHolder ID="H" runat="server" />
<asp:ContentPlaceHolder ID="C" runat="server" />
<asp:ContentPlaceHolder ID="J" runat="server" />

Example in a normal page:

<asp:Content ID="ContentHead" ContentPlaceHolderID="H" runat="server">
</asp:Content>

<asp:Content ID="ContentMain" ContentPlaceHolderID="C" runat="server">
</asp:Content>

<asp:Content ID="ContentScripts" ContentPlaceHolderID="J" runat="server">
</asp:Content>

If the generated starter currently has HeadContent, MainContent, or ScriptsContent, rename them to H, C, and J before adding more pages.

Do not mix placeholder naming systems in the same project.


WebForms tab and page-state rules

  • Register AjaxControlToolkit once in Web.config under system.web/pages/controls with the exact prefix ajax; do not add <%@ Register ... %> directives for it in individual pages.
  • AjaxControlToolkit controls must use the ajax: prefix, for example ajax:TabContainer and ajax:TabPanel; do not use ajaxToolkit: or another page-specific prefix.
  • Tabs in WebForms pages must use ajax:TabContainer and ajax:TabPanel; do not build page tabs with Bootstrap nav-tabs, custom hidden panels, or JavaScript-only tab switching.
  • Use the ScriptManager owned by Site.master and the existing AjaxControlToolkit resources. Do not add another ScriptManager or duplicate Toolkit scripts/styles.
  • Server-side page state such as current entity keys, selected child keys, editing mode, flags, and the active tab must be stored in typed ViewState properties when it must survive postback.
  • Do not add asp:HiddenField merely to preserve server-side state across postbacks. A hidden field is allowed only when client-side JavaScript must read or change the value.
  • Hidden-field values are client-controlled and must never be trusted for authorization or sensitive decisions; validate them again on the server when their use is unavoidable.
  • Keep ViewState values small and serializable. Do not store database connections, commands, readers, services, repositories, or unnecessarily large result sets in ViewState.
  • ViewState property and key names must identify the entity and purpose, for example CveFraccionamientoActual and CveFraccionamientoEtapaActual.
  • When a postback needs to recover related values from an already loaded catalog, store the typed serializable object list in a typed ViewState property and locate the selected object by its key.
  • Do not copy server-owned catalog or model values into HTML data-* attributes, CSS classes, hidden fields, or other client-controlled markup merely to recover them during a postback. Read them from the typed object list stored in ViewState.

Server-control visibility rules

  • Never use the effective Visible property of an ASP.NET server control as business or page state, as an if condition, or as the input used to mutate another control or object. An invisible ancestor causes every descendant to report Visible == false, regardless of the value assigned directly to that descendant.
  • Calculate visibility in independent, clearly named Boolean variables or a typed state model. Use those values both for decisions and for assigning each control's Visible property.
  • When configuring children of a server container that starts hidden, make the parent container visible before assigning child visibility. After assigning the children, hide the parent again only when the independent visibility values indicate that none of its children should be rendered.

Login and session rules

Authentication must go through a contract.

Required flow:

Login.aspx.cs
  ↓
IAuthContract
  ↓
DummyAuthContract now, real AuthService later
  ↓
IUserSessionContract
  ↓
Session user

Initial login may be dummy.

Dummy session user should be safe and clearly fake, for example:

UserId: 15
CompanyId: 1
RoleId: 1
RoleName: Administrador
CompanyName: Empresa Demo
DisplayName: Usuario Demo

Rules:

  • Dummy login may accept any non-empty username and password during starter setup.
  • Mark dummy authentication clearly in code comments.
  • Do not mix real SQL authentication with dummy authentication in the same class.
  • When real login is implemented, create a new service such as SqlAuthContract or AuthService.
  • Do not store passwords in session.
  • Do not log raw passwords.
  • Use Forms Authentication if staying with classic WebForms auth.

Global.asax rules

Global.asax / Global.asax.cs should:

  • Register bundles through BundleConfig.RegisterBundles(BundleTable.Bundles).
  • Configure basic application startup.
  • Avoid business logic.
  • Avoid direct database startup queries unless absolutely required.

If OWIN is not used, prevent startup errors by adding this to Web.config:

<add key="owin:AutomaticAppStartup" value="false" />

Do not add OWIN packages unless the project actually needs OWIN.


Web.config rules

Web.config must stay compatible with ASP.NET WebForms on .NET Framework 4.8/4.8.1.

Rules:

  • Use Forms Authentication unless a different auth system is explicitly requested.
  • Allow anonymous access only to the login page and required static assets.
  • Do not add ASP.NET Core middleware settings.
  • Do not add unsupported .NET Core config sections.
  • Do not add CodeDom provider entries unless the matching NuGet package is installed.
  • If this error appears: No se pudo ubicar el tipo de proveedor CodeDom Microsoft.CodeDom.Providers.DotNetCompilerPlatform..., either install the exact package version or remove/fix the system.codedom section.
  • Keep MIME mappings for fonts such as .woff and .woff2 when Metronic requires them.

OWIN rule

If the application shows this error:

No assembly found containing an OwinStartupAttribute

And the project does not use OWIN, add this in appSettings:

<add key="owin:AutomaticAppStartup" value="false" />

Do not create an empty OWIN startup class just to silence the error unless OWIN is actually required.


Site.master rendering rules

The master page should render bundles and scripts in this general order:

Inside <head>:

<%: Scripts.Render("~/bundles/modernizr") %>
<%: Styles.Render("~/Content/AjaxControlToolkit/Styles/Bundle") %>
<%: Styles.Render("~/Metronic/assets/global/css/cssV1") %>
<asp:ContentPlaceHolder ID="H" runat="server" />

Inside <form> near the top:

<asp:ScriptManager ID="TSM" runat="server" />
<%: Scripts.Render("~/bundles/scripts") %>

Before closing </form>:

<%: Scripts.Render("~/Metronic/assets/global/scripts/JSV1") %>
<%: Scripts.Render("~/bundles/highcharts") %>
<asp:ContentPlaceHolder ID="J" runat="server" />

Rules:

  • Do not render the same script twice.
  • Do not render JQuery twice.
  • Keep ScriptManager if AjaxControlToolkit, UpdatePanel, or WebForms AJAX is used.
  • Keep TSM_AsyncPostBackError only if implemented in code-behind.
  • Remove or implement any event handler referenced by markup.

Header/menu rules

The master header must preserve the selected Metronic layout.

Rules:

  • Keep user dropdown.
  • Keep logout option.
  • Keep actions button when present.
  • Do not restore the hidden/old search box from legacy header.
  • Sidebar menu must be built from IMenuContract.
  • Do not build the menu from SQL inside Site.master.cs.
  • Menu items should use MenuItemModel or an equivalent model.
  • Encode text output when generating HTML menu strings.
  • Module visibility and page access are separate concerns: Sis_Modulos.Visible controls whether an item is shown in the menu, but it must not deny direct page access.
  • PA_Sis_PaginaAccessCheck must validate role assignment, PuedeVer, active state, and URL. It must not require Sis_Modulos.Visible = 1.

Page title and breadcrumb rules

Page title and breadcrumb should be handled consistently.

Rules:

  • Use Page.Title for the browser title.
  • Use a master/layout model for visible page title and breadcrumb.
  • Do not hardcode global breadcrumb logic in every page.
  • Normal pages may set page title in Page_Load or via properties.

Preferred model:

MasterLayoutModel
  PageTitle
  Breadcrumbs
  CurrentUser
  MenuItems

JavaScript and CSS rules

  • Global scripts/styles must be registered in BundleConfig and rendered by master.
  • El JavaScript específico de una página debe quedar dentro del mismo .aspx, en un bloque <script> del placeholder J.
  • El CSS específico de una página debe quedar dentro del mismo .aspx, en un bloque <style> del placeholder H.
  • No crear archivos .js o .css separados para una página ni mover su código a bundles globales, independientemente de su tamaño, salvo petición explícita del usuario. Los recursos compartidos y de UserControls conservan su carga global.
  • Do not remove existing custom legacy files unless the user asks.
  • Fix null addEventListener errors by checking that the element exists before attaching events.
  • Avoid blocking Ctrl+V unless a specific feature requires it.

User control rules

If server controls are migrated:

  • Prefer C# classes under App_Code/SigControls when creating reusable server controls.
  • Do not mix WebForms .ascx user controls with App_Code server-control classes unless there is a clear reason.
  • Never use Page.Header.Controls.Add or dynamic HtmlLink/style/script insertion to load resources or define CSS/JS from a control. Keep implementations in global files; use the existing RegistraScript (PageScriptRegistrar.RegistraScript in UserControls) for individual server-triggered calls. Do not replace it with action queues or serialized commands. Keep the existing centralized alert service and open lateral panels on the client click through data-sig-panel-abrir.
  • Business UserControls belong in UserControl/ as .ascx and .ascx.cs; a request for a UserControl must not be implemented as an App_Code CompositeControl.
  • Verify the complete page lifecycle, including PreRender with the master header containing <% ... %> blocks, multiple instances and partial postbacks. Compilation alone does not verify this behavior.
  • Controls should expose properties/events and avoid direct SQL access.
  • Controls should call contracts/services when they need data.

Home page rules

Use only one active home page convention.

For local development, the canonical home URL is:

http://localhost:52706/Inicio.aspx

The application root must be equivalent and redirect explicitly to that page:

http://localhost:52706/  ->  http://localhost:52706/Inicio.aspx

Keep the root redirect and the Inicio.aspx default document consistent. Do not introduce another startup page.

Allowed options:

Default.aspx
Inicio.aspx

Rules:

  • Do not keep both as competing entry pages.
  • If using Inicio.aspx, redirect Default.aspx to Inicio.aspx or update Forms Authentication default URL.
  • If using Default.aspx, keep Web.config and menu links pointing to Default.aspx.
  • The home page must use Site.master.