Webforms: Forzar postbacks

 ·  ☕ 5 min  ·  ✍️ eiximenis

    Nota: Este post ha sido importado de mi blog de geeks.ms. Es posible que algo no se vea del todo "correctamente". En cualquier caso puedes acceder a la versión original aquí

    Jejejee… Sí, aunque no lo parezca a veces hago temillas con Webforms, y es que uno tiene que conocer al enemigo! 😛

    Lo que voy a comentar hoy, es como forzar un postback desde un control propio.

    Una búsqueda en google da varios resultados, pongo un par de ejemplo:

    1. http://tratadooscuro.blogspot.com.es/2009/02/dopostback-ese-gran-desconocido.html
    2. http://programacion.porexpertos.es/provocar-un-postback-desde-javascript-con-aspnet/

    Ambos ejemplos dicen lo mismo pero lo cierto es que, en mi opinión, hay una manera ligeramente mejor que hacerlo, pero parece que se desconoce bastante porque buscando en google aparecen menos resultados.

    Bueno, si miráis los dos enlaces que he puesto arriba, forzar un postback desde un control propio es tan simple como llamar a __doPostback. Este método lo añade automáticamente Webforms cuando lo necesita.

    Si seguimos las instrucciones de cualquiera de los dos enlaces anteriores, si queremos generar un control que sea p.ej. un enlace que al pulsarlo genere un postback vemos que debemos usar un código como este:

    [DefaultProperty(“Text”)]

    [ToolboxData(“<{0}:MyControl runat=server>”)]

    public class MyControl : WebControl

    {

        [Bindable(true)]

        [Category(“Appearance”)]

        [DefaultValue(“”)]

        [Localizable(true)]

        public string Text

        {

            get

            {

                String s = (String)ViewState[“Text”];

                return s ?? string.Empty;

            }

     

            set

            {

                ViewState[“Text”] = value;

            }

        }

     

        protected override void RenderContents(HtmlTextWriter output)

        {

            output.AddAttribute(HtmlTextWriterAttribute.Href,

                “javascript:__doPostBack(”,”);”);

            output.RenderBeginTag(HtmlTextWriterTag.A);

            output.Write(Text);

            output.RenderEndTag();

        }

    }

    Si creamos una Webform vacío y añadimos el control y probamos la página, efectivamente se renderiza el tag que incluye la llamada a __doPostBack. Pero fijaos que este es el código HTML generado por el Webform:

    ¿Alguien ve el método __doPostBack? No, ¿verdad? Eso es porque Webforms no lo ha generado, y no lo ha generado porque no sabe que alguien va a usarlo. La verdad es que Webforms solo genera este método cuando sabe que algún control lo requiere. En páginas medio complejas la probabilidad de que algún control requiera postback es tan grande que por eso mucha gente cree que siempre se genera. Pero no es así.

    Poner código “a saco” para llamar a __doPostBack funciona en la mayoría de casos pero no es una buena práctica porque estamos usando una característica interna de Webforms. Si en la siguiente release de Webforms Microsoft decide renombrar esta función todo nuestro código se viene abajo.

    Vale… entonces si no podemos llamara a __doPostBack a saco, que debemos hacer? Pues usar el método GetPostBackClientHyperlink de la clase ClientScriptManager. Para obtener una instancia de ClientScriptManager se puede usar la propiedad ClientScript del objeto Page:

    ¡Listos! Ahora si ejecutamos de nuevo el Webform, vemos que el código generado es:

    DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

     

    <html xmlns=”http://www.w3.org/1999/xhtml” >

    <head><title>

     

    title>head>

    <body>

        <form name=”form1″ method=”post” action=”default.aspx” id=”form1″>

    <div>

    <input type=”hidden” name=”__VIEWSTATE” id=”__VIEWSTATE” value=”/wEPDwUKLTk1OTYxMjkxMmRkGui/AV2Pv2fTTQJWmL8w2grZiZY=” />

    div>

     

    <div>

     

        <input type=”hidden” name=”__EVENTTARGET” id=”__EVENTTARGET” value=”” />

        <input type=”hidden” name=”__EVENTARGUMENT” id=”__EVENTARGUMENT” value=”” />

    div>

        <div>

     

            <span id=”MyControl1″><a href=”javascript:__doPostBack(‘MyControl1’,”)”>Demoa>span>

     

        div>

     

    <script type=”text/javascript”>

    //

    var theForm = document.forms[‘form1’];

    if (!theForm) {

        theForm = document.form1;

    }

    function __doPostBack(eventTarget, eventArgument) {

        if (!theForm.onsubmit || (theForm.onsubmit() != false)) {

            theForm.__EVENTTARGET.value = eventTarget;

            theForm.__EVENTARGUMENT.value = eventArgument;

            theForm.submit();

        }

    }

    //]]>

    script>

     

    form>

    body>

    html>

    Por un lado ahora Webforms nos ha generado el __doPostBack y por otro como podemos ver el el atributo href de nuestro enlace tenemos la llamada a doPostBack correcta (por norma general el primer parámetro es el ID del control que realiza la llamada).

    Y ya que sabemos generar PostBacks… ¿como recibirlos?

    Hemos visto como generar un PostBack desde nuestro control, ahora… como podemos decirle a Webforms que nuestro control quiere enterarse de los postbacks que él haya efecutado?

    Pues para esto basta con implementar la interfaz IPostBackEventHandler que tiene un solo método:

    Esta interfaz nos permite hacer algo cuando hay un postback generado por el propio control. Por norma general lo que se hace es lanzar un evento de .NET (p.ej. Click). Vamos a ver un ejemplo muy rápido. Para ello añadimos un evento Click a nuestro control:

    Ahora implementamos la interfaz IPostBackEventHandler y el método RaisePostBackEvent:

    Cuando ahora se pulse nuestro enlace se generará un evento Click que podemos capturar desde el Webform, como cualquier otro evento.

    Además fijaos que RaisePostBackEvent recibe una cadena (eventArgument). El valor de esta cadena es el valor del segundo parámetro de GetClientPostBackHyperlink que hemos usado para generar la llamada a __doPostBack. De esta manera podemos crear controles que lancen varios eventos en función del valor de eventArgument.

    Un saludo!


    eiximenis
    ESCRITO POR
    eiximenis
    Compulsive Developer