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

6.2 KiB

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:
<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:
<asp:UpdatePanel ID="UpUsuarios" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="true">
    <ContentTemplate>
        <!-- Sección que se actualiza parcialmente -->
    </ContentTemplate>
</asp:UpdatePanel>
  • Usar UpdateMode="Conditional" de manera predeterminada.
  • Preferir ChildrenAsTriggers="true" y aprovechar los eventos de los controles hijos; no declarar AsyncPostBackTrigger para controles que ya están dentro del mismo panel.
  • 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 colocarse dentro del panel correspondiente cuando sea apropiado; en caso contrario, registrarlos mediante ScriptManager.RegisterAsyncPostBackControl y actualizar explícitamente los paneles afectados.
  • Conservar <Triggers> únicamente cuando exista una necesidad técnica. Evitar referencias declarativas a controles de otros contenedores de nombres o secciones que puedan no estar disponibles; usar la referencia del control al registrarlo mediante ScriptManager.
  • En cada modal, colocar un solo UpdatePanel inmediatamente dentro del segundo div (modal-dialog), con todo el modal-content dentro de su ContentTemplate. No dividir el contenido del mismo modal en varios paneles.
  • Las operaciones normales de guardar, seleccionar valores, ejecutar RowCommand y abrir o modificar modales deben usar postbacks parciales y conservar sus eventos existentes.

Operaciones que requieren postback completo

  • Conservar postbacks completos únicamente para una necesidad técnica real: cargas mediante FileUpload, descargas que escriben directamente en Response, exportaciones y otras respuestas incompatibles con AJAX. Usar PostBackTrigger o ScriptManager.RegisterPostBackControl según el contenedor del control; no usarlos para botones que únicamente guardan información o actualizan la interfaz.
  • No intentar recibir archivos mediante FileUpload en un postback parcial; su botón de envío debe estar registrado para postback completo.
  • 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

<%@ 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="true">
        <ContentTemplate>
            <!-- No agregar otro form ni otro ScriptManager. -->
        </ContentTemplate>
    </asp:UpdatePanel>
</asp:Content>

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