Postbacks entre páginas diferentes en ASP.Net (Cross page postbacks)

Las primeras versiones de la plataforma .Net introdujeron el PostBack como el mecanismo de recarga de una página gracias al cual era posible la persistencia del estado de controles y la interacción con ellos de forma muy sencilla y potente en el lado del servidor, modificando la filosofía de programación de webs que habíamos usado hasta entonces (ASP clásico, CGIs…).

Sin embargo, si querías usar los controles de servidor en todo su esplendor te veías obligado a meter tareas completas dentro de una misma página; así, aquellas que presentaban funcionalidades relativamente complejas se convertían en batiburrillos donde se incluían formularios de entrada de datos, código de validaciones, formularios de salida de información, etc. Por ejemplo, podíamos tener en un mismo Webform paneles de introducción de criterios de búsqueda, paneles de información o errores, paneles con un grid para mostrar los resultados e incluso otro panel para mostrar una vista ampliada de un registro concreto, y jugar con las visibilidades para mostrar unos u otros en función de los pasos dados por el usuario.

Desde ASP.Net 2.0 es posible realizar los llamados «Cross Page PostBacks», o PostBacks hacia páginas distintas de la inicial, permitiéndonos separar funciones y hacer nuestro código un poco más legible, estructurado y reutilizable. El ejemplo anterior podría ser diseñado en tres páginas independientes, separando las distintas vistas, una solución mucho más limpia:


  • en la primera estaría el formulario de introducción de criterios.
  • en la segunda podríamos simplemente tomar los parámetros de la anterior y mostrar un listado con los resultados obtenidos, o bien un mensaje de información si no hay coincidencias.
  • en la tercera podríamos montar una ficha con los datos detallados de un elemento, que habría sido seleccionado por el usuario en la página anterior.

¿Y cómo se hace? Sencillo.

En primer lugar, hay que modificar el comportamiento de los botones de acción (o similar, de hecho también podría ser ImageButtons o LinkButtons) para que realicen el envío a otra página, indicándole su URL en la propiedad PostBackUrl. Eso hará que, tras su pulsación, el control sea enviado inmediatamente al archivo .aspx que se defina en la misma.

Un aspecto muy a tener en cuenta es el término «inmediatamente»: el control es transferido a la nueva página sin ejecutar posibles validaciones en servidor, por lo que podrían llegar gazapos a la segunda. Sin embargo, si los validadores son en cliente, se ejecutarán con normalidad (si el usuario no tiene desactivado Javascript, of course!).

Ya en la página destino, hay varias opciones para recuperar el valor de los controles de la página invocadora. La primera de ellas, la más sencilla, consiste en usar la propiedad PreviousPage de la clase Page para obtener una referencia hacia la página de origen y obtener sus controles de la siguiente forma:

if (PreviousPage != null)
{
TextBox txt =
(TextBox)PreviousPage.FindControl(«TextBox1»);
Label1.Text = txt.Text; // Por ejemplo
}

Sin embargo, no es una solución aconsejable, puesto que un simple cambio de nombre del control en la página origen provocaría un error en tiempo de ejecución, puesto que FindControl no sería capaz de encontrarlo con el nombre «TextBox1».

Hay otra forma mucho más potente, que consiste en especificar en la página destino un tipado fuerte para la de origen usando en su archivo .aspx la siguiente directiva:

<%@ PreviousPageType VirtualPath=»~/PaginaOrigen.aspx» %>

De esta forma, cualquier referencia a PreviousPage en la página destino se considerará automáticamente del tipo de la página de origen, pudiendo acceder a sus propiedades de forma directa, sin necesidad de castings ni nada parecido. Sin embargo, todo sea dicho, debido a que el nivel de visibilidad de los controles de un Webform son protected, no podemos acceder directamente a su contenido, debemos usar accesores o propiedades públicas para ello.

Por ejemplo, podríamos definir en la clase (codebehind) de la página de origen una propiedad como la siguiente como accesor al contenido de un control TextBox llamado txtTexto:

public string Texto
{
get {return txtTexto.Text; }
}

Y en la página destino, una vez introducida la directiva descrita anteriormente especificando la URL de la página de origen, podríamos hacer lo siguiente:

if (PreviousPage != null)
{
Label1.Text = PreviousPage.Texto; // Por ejemplo
}

En resumen, esta técnica permite estructurar mucho mejor nuestras aplicaciones web, aunque sea a cambio de realizar un sobreesfuerzo en el desarrollo. En mi opinión puede valer la pena su uso en páginas que generen demasiadas vistas diferentes para ser introducidas en un único Webform sin comprometer la mantenibilidad, o cuando resulte interesante de cara a la reutilización de páginas.

No es conveniente, a mi entender, su utilización indiscriminada en formularios simples, pues precisamente los PostBacks fueron introducidos en ASP.Net para evitar la proliferación innecesaria de páginas sueltas (.aspx) y facilitar el mantenimiento del estado en la inherentemente desconectada tecnología Web. 


Publicado originalmente en: Variable not found

14 comentarios sobre “Postbacks entre páginas diferentes en ASP.Net (Cross page postbacks)”

  1. Hola José:
    Está bien la solucion, pero como podría hacerse, si queremos trabajar un tercer nivel de navegación. Es decir Origen, Origen-Destino1, Destino1-Destino2.
    Y realizar la siguiente navegaciín
    1.- Origen Destino1 (En destino1 uno veo Origen)
    2.- Destino1 – Destino2 (En Destino2 Veo Destino1)
    3.- Volver de Destino2 a Destino1 y ver los parametros iniciales que habia enviado Origen..

    Se me ocurre pasar los datos de Origen a Destino1 y luego a Destino2 .
    Pero habría algo más corto… y Menos engorroso?

    Gracias!!
    Saludos
    Atte Pablo

  2. Hola, Pablo. Ante todo, gracias por comentar.

    Aunque suponía que el modelo comentado en este post no iría bien, he creado un proyecto con tres páginas para comprobarlo y, efectivamente, desde la página Destino2 sólo podemos acceder a la instancia de Destino1.

    Por tanto, me temo que la solución engorrosa es la única vía que recomendarte. Consistiría en ir propagando parámetros (o valores de controles que quieras hacer persistentes a lo largo de la navegación del usuario) de una llamada a otra, almacenándolos en viewstate o controles ocultos.

    Un saludo.

  3. No me funciona tomar el valor de una propiedad publica de una página origen a una destino, intenté poniendo la propiedad postback de un botón ni haciendo referencia al previouspagetype… se tiene que dar alguna instrucción adicional?
    Estoy utilizando Visual Studio 2005 y Framework 2.0

    Gracias!

  4. Hola, Lydia.

    Ten en cuenta que con PreviousPage puedes acceder desde la página destino a una propiedad de la de origen en un cross page postback, pero no al revés…

    Prueba el ejemplo que se describe en el post, y verás cómo lo consigues sin problema. La verdad es que tenía que haber incluido en su momento y proyecto de demostración, pero bueno, qué se le va a hacer. O:-)

    Saludos y gracias por comentar.

  5. ¿Y como se haría el Cross page postbacks entre dos páginas, por ejemplo tx.aspx y rx.aspx si amabas en vez de ser web forms independientes son hijas de un master page? En este caso solo hay un formulario y aunque el postback en el button de tx.aspx me carga la pagina rx.aspx si envio el valor de un textbox supongo que tendría que acceder al cargar rx al contenplaceholder de previous page,,,

  6. Hola, Fernando.

    No he comprendido bien el escenario de tu consulta.

    ¿El problema viene cuando tienes controles en la master cuyos valores quieres capturar tras realizar un crosspage postback?

    Si el textbox se encuentra en la master, deberías poder obtener su valor buscándolo en la colección de controles de la misma, algo así: PreviousPage.Master.FindControl(«textbox» ).

    Saludos.

  7. Si la página origen xx.aspx tiene una master page. dentro de xx.aspx.cs y tengo un método público DeveolverValor, quisiera saber cómo hacer para acceder a ese método desde la página a la cual se enlaza el Postbacks? A los contenedores puedo acceder con el siguiente código, pero a los métodos no puedo acceder. De qué forma puedo acceder?
    Código:
    Control placeHolder =
    (ContentPlaceHolder)Page.PreviousPage.Controls[0].FindControl(«ContentPlaceHolder1»);
    TextBox SourceTextBox =
    (TextBox)placeHolder.FindControl(«caja1»);

    Muchas gracias. Muy bueno tu artículo.
    Saludos
    José Luis

  8. Hola, @José Luis,

    en principio podrías definir el tipo de la página de origen con la directiva «PreviousPageType», tal y como se describe más arriba. Esto debería darte acceso a las propiedades o métodos de la misma, tal y como comentaba en el ejemplo accediendo a la propiedad «Texto».

    Saludos!

  9. Te comento más detalladamente el problema:
    Tengo una Pagina1.aspx que esta dentro de una master page (encabezado.master).En esta página tengo un TexBox llamado «caja1». Dentro de Pagina1.aspx.cs tengo un método:
    public string obtenerNombre
    {
    get
    {
    return Nombre;
    }
    }
    Pagina1.aspx hace un Postback a Pagina2.aspx.
    En el código de la pagina2.aspx agrego:
    < %@ PreviousPageType VirtualPath="~/Pagina1.aspx" %>
    Si trato de acceder a los TextBox o métodos «como se describe en el artículo» ( (TextBox)PreviousPage.FindControl(«caja1»);)obtengo siempre referencias nulas. Investigando vi que al tener una master page, primero tengo que obtener una referencia al contenedor donde está el TexBox, para luego con esa referencia acceder al TexBox. Haciendo el siguiente código:
    Control placeHolder =
    (ContentPlaceHolder)Page.PreviousPage.Controls[0].FindControl(«ContentPlaceHolder1»);
    TextBox SourceTextBox =
    (TextBox)placeHolder.FindControl(«caja1»);

    Solucioné el acceso al TexBox.
    Pero no he podido generar código para acceder al método obtenerNombre. Con la forma PreviousPage.obtenerNombre No me funciona.
    Espero haber descripto bien el problema.
    Espero puedas orientarme con la solución.
    Saludos y desde ya muchas gracias.

  10. Hola a todos,
    Tengo el siguiente problema tengo un formulario que no esta en el master page y necesito que el valor de uno de sus textbox lo invoque o lo traiga al textbox de un masterpage. esto es en asp.net

    Les agradezco mucho su ayuda de antemano.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *