103 lines
5.2 KiB
Markdown
103 lines
5.2 KiB
Markdown
# Reglas obligatorias para formularios y postbacks parciales WebForms
|
|
|
|
Estas reglas complementan `AGENTS.md` y `AGENTS_PAGE_STRUCTURE.md`.
|
|
|
|
## Formulario principal
|
|
|
|
- `Site.master` es el único archivo autorizado para declarar el formulario principal:
|
|
|
|
```aspx
|
|
<form id="form1" runat="server">
|
|
```
|
|
|
|
- Ninguna página normal `.aspx` que use `Site.master` debe declarar `<form>`, `<form runat="server">`, `<html>`, `<head>` ni `<body>`.
|
|
- No anidar formularios HTML dentro del formulario de `Site.master`.
|
|
- Los formularios visuales de captura se construyen con `<div>`, controles WebForms y validadores dentro del placeholder `C`.
|
|
- `Login.aspx` es la única excepción actual porque no usa `Site.master` y conserva su estructura HTML completa con su propio formulario de servidor.
|
|
- No agregar una segunda excepción sin solicitud explícita.
|
|
|
|
## ScriptManager
|
|
|
|
- `Site.master` es el único dueño del `asp:ScriptManager` principal, actualmente `TSM`.
|
|
- Las páginas de contenido no deben agregar otro `ScriptManager`.
|
|
- Usar `asp:ScriptManagerProxy` solamente cuando una página requiera registrar servicios o scripts específicos que no pertenezcan globalmente al master.
|
|
- El manejo global de `AsyncPostBackError` permanece en `Site.master`.
|
|
|
|
## UpdatePanel
|
|
|
|
- Usar `asp:UpdatePanel` cuando una interacción deba actualizar únicamente una sección sin refrescar visualmente toda la página.
|
|
- No envolver todo el placeholder `C` en un único `UpdatePanel` por comodidad.
|
|
- Crear paneles pequeños alrededor de la tabla, formulario, resumen o sección que realmente cambia.
|
|
- Preferir esta configuración:
|
|
|
|
```aspx
|
|
<asp:UpdatePanel ID="UpUsuarios" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="false">
|
|
<ContentTemplate>
|
|
<!-- Sección que se actualiza parcialmente -->
|
|
</ContentTemplate>
|
|
<Triggers>
|
|
<asp:AsyncPostBackTrigger ControlID="BtnBuscar" EventName="Click" />
|
|
</Triggers>
|
|
</asp:UpdatePanel>
|
|
```
|
|
|
|
- Usar `UpdateMode="Conditional"` de manera predeterminada.
|
|
- Preferir `ChildrenAsTriggers="false"` y declarar triggers explícitos para que el comportamiento sea fácil de revisar.
|
|
- Llamar `Update()` únicamente en paneles condicionales y sólo cuando el servidor haya modificado su contenido.
|
|
- Evitar `UpdatePanel` anidados. Si son necesarios, documentar qué evento actualiza cada panel.
|
|
- No actualizar varios paneles si sólo cambió una sección.
|
|
- Los controles externos que disparen actualización parcial deben declararse como `AsyncPostBackTrigger` o registrarse mediante `ScriptManager.RegisterAsyncPostBackControl`.
|
|
|
|
## Operaciones que requieren postback completo
|
|
|
|
- Usar `PostBackTrigger` para cargas de archivos, descargas que escriben directamente en `Response`, exportaciones y otras operaciones incompatibles con postback asíncrono.
|
|
- No intentar procesar `FileUpload` dentro de un postback parcial sin `PostBackTrigger`.
|
|
- No iniciar una descarga binaria desde una respuesta parcial de `UpdatePanel`.
|
|
|
|
## Ciclo de vida y rendimiento
|
|
|
|
- Un postback parcial ejecuta el ciclo de vida de servidor de la página; no significa que el servidor procese únicamente el `UpdatePanel`.
|
|
- Proteger cargas iniciales con `if (!IsPostBack)`.
|
|
- No repetir consultas, catálogos o construcción del menú en cada evento si no son necesarios.
|
|
- Toda consulta continúa ejecutándose mediante contratos, servicios, repositorios y procedimientos almacenados.
|
|
- Preferir operaciones asíncronas de extremo a extremo para consultas lentas cuando la página esté configurada correctamente para async.
|
|
- Configurar timeouts razonables y no dejar indicadores de carga activos indefinidamente.
|
|
|
|
## Experiencia de usuario
|
|
|
|
- Usar `asp:UpdateProgress` cuando la operación pueda tardar lo suficiente para que el usuario necesite retroalimentación.
|
|
- Asociar el indicador al `UpdatePanel` correspondiente cuando sea posible.
|
|
- Deshabilitar temporalmente botones que puedan generar envíos duplicados.
|
|
- Mostrar mensajes amigables dentro de la sección actualizada o mediante el sistema global de mensajes.
|
|
- Los detalles técnicos permanecen exclusivamente en el log.
|
|
|
|
## JavaScript después de un postback parcial
|
|
|
|
- Los scripts registrados globalmente no deben duplicarse dentro de un `UpdatePanel`.
|
|
- Los componentes JavaScript que pierdan inicialización después de reemplazar HTML deben reinicializarse mediante `Sys.WebForms.PageRequestManager.endRequest`.
|
|
- Evitar registrar múltiples veces el mismo handler en cada postback parcial.
|
|
- Usar `ScriptManager.RegisterStartupScript` cuando un script de servidor deba ejecutarse después de una actualización parcial.
|
|
|
|
## Plantilla de página normal
|
|
|
|
```aspx
|
|
<%@ Page Title="Página" Language="C#" MasterPageFile="~/Site.master"
|
|
AutoEventWireup="true" CodeBehind="Pagina.aspx.cs"
|
|
Inherits="SIG.Web.Pages.Modulo.Pagina" %>
|
|
|
|
<asp:Content ID="ContentHead" ContentPlaceHolderID="H" runat="server">
|
|
</asp:Content>
|
|
|
|
<asp:Content ID="ContentMain" ContentPlaceHolderID="C" runat="server">
|
|
<asp:UpdatePanel ID="UpContenido" runat="server"
|
|
UpdateMode="Conditional" ChildrenAsTriggers="false">
|
|
<ContentTemplate>
|
|
<!-- No agregar otro form ni otro ScriptManager. -->
|
|
</ContentTemplate>
|
|
</asp:UpdatePanel>
|
|
</asp:Content>
|
|
|
|
<asp:Content ID="ContentScripts" ContentPlaceHolderID="J" runat="server">
|
|
</asp:Content>
|
|
```
|