Gerardo Contijoch

Experiencias del día a día trabajando con .NET – ASP.NET, C#, ASP.NET MVC y demas…

Acceder a variables de servidor desde Javascript

Posted by Gerardo Contijoch en junio 6, 2009

Un problema con el que nos solemos encontrar los desarrolladores web es el de acceder desde un script (en el cliente) a datos que se encuentran sólo disponibles en el servidor. No me refiero a recursos que están en el servidor, sino mas bien a valores o datos que pueden ser resultado (o formar parte) de cierto procesamiento y que no se exponen al cliente.

El caso más común con el que me encuentro yo es conocer el id de ciertos controles desde el lado del cliente. Sabemos bien que ASP.NET tiene la costumbre de renombrar nuestros controles con unos nombres bastante crípticos y esto es un gran problema si queremos acceder a ellos desde javascript. El verdadero nombre de estos controles (lo que se conoce como el ClientId) se encuentra accesible desde el código del lado del servidor, pero no desde el cliente. Y es por esto que Rick Strahl creo la clase wwScriptVariables que nos permite pasarle a nuestros scripts los valores que querramos desde el servidor.

Veamos un ejemplo con el cual vamos a trabajar. Imaginemos que tenemos una página en donde se ingresa un valor y como respuesta, se informa si ese valor es numérico o no. Esta es la parte interesante del código HTML:

   1: <div id="valor">Ingrese un valor: <asp:TextBox ID="txtValor" runat="server"></asp:TextBox>
   2:     <asp:Button ID="btnEnviar" runat="server" Text="Enviar" onclick="btnEnviar_Click" />
   3: </div>
   4: <div id="resultado">
   5:     <asp:Label ID="lblResultado" runat="server" Text=""></asp:Label>
   6: </div>

Y este es el código del lado del servidor:

   1: using System;
   2:
   3: public partial class _Default : System.Web.UI.Page
   4: {
   5:     protected void Page_Load(object sender, EventArgs e){}
   6:
   7:     protected void btnEnviar_Click(object sender, EventArgs e) {
   8:         if (EsNumero(this.txtValor.Text)) {
   9:             this.lblResultado.Text = "Es un número!";
  10:         } else {
  11:             this.lblResultado.Text = "No es un número!";
  12:         }
  13:     }
  14:
  15:     private bool EsNumero(string valor) {
  16:         int val = 0;
  17:         if (int.TryParse(valor, out val)) {
  18:             return true;
  19:         }
  20:         return false;
  21:     }
  22: }

Si ingresamos un valor numérico el resultado se vería así:

RegistrarVariablesServidor-respuesta-original

Como se ve puede ver, todo es muy sencillo, pero imaginemos que queremos aplicarle algún efecto a la página dependiendo del resultado. En mi caso voy a usar jQuery para esto y el efecto va a consistir simplemente en aplicarle un estilo a la respuesta (ya se que lo mismo se puede hacer desde el lado del servidor, pero la idea es modificarlo desde el lado del cliente como un ejemplo).

Normalmente uno agregaría algo similar a esto en la sección head de la página:

   1: <link href="style.css" rel="stylesheet" type="text/css" />
   2:
   3: <script src="jquery-1.2.6.min.js" type="text/javascript"></script>
   4:
   5: <script type="text/javascript" language="javascript">
   6:   $(document).ready(function() {
   7:
   8:     var lbl = $("#lblResultado");
   9:
  10:     lbl.addClass("claseResultado");
  11:
  12:     });
  13: </script >

Pero eso sólo funciona cuando nuestro control (en este caso el label ‘lblResultado’) no se encuentra dentro de un contenedor, como puede ser una grilla o una master page. Esto se debe a que ASP.NET modifica los Id de los elementos renderizados para evitar la colisión de nombres y por eso, nuestro ‘lblResultado’ se puede transformar en algo como ‘ctl00_ContentPlaceHolder1_lblResultado’ provocando un error en nuestro script. Lo que necesitamos es pasarle a nuestros scripts el verdadero nombre de los controles lo que se puede lograr con algunos code nuggets incrustados en medio de nuestro script:

   1: $(document).ready(function() {
   2:     var lbl = $("#<%= lblResultado.ClientId %>");
   3:     lbl.addClass("claseResultado");
   4: });

Pero esto tiene algunos problemas. Primero y principal, si nuestro script esta en un archivo externo y no embebido en la página, no se pueden usar code nuggets. Otro problema es que el valor que pasemos tiene que estar correctamente escapado para que javascript no lo malinterprete o falle. Sumado a esto, no es muy elegante la solución de incrustar código de servidor dentro de un script y no facilita para nada la reutilización de los scripts.

Ahora veamos como solucionamos este inconveniente con la ayuda de wwScriptVariables. Su uso es sencillísimo, solo hay que instanciarla y mediante el método Add() agregamos los valores que queremos pasarle a nuestros scripts. Luego, desde el lado del cliente, podemos acceder a estos valores desde una nueva variable que tendremos a nuestra disposición, la cual es generada (durante el renderizado) por la clase wwScriptVariables. Veamos como queda nuestro ejemplo con el uso de esta clase.

Del lado del servidor:

   1: using System;
   2:
   3: public partial class NuevaVersion : System.Web.UI.Page
   4: {
   5:     protected void Page_Load(object sender, EventArgs e){}
   6:
   7:     protected void btnEnviar_Click(object sender, EventArgs e) {
   8:
   9:         Westwind.Web.Controls.Controls.wwScriptVariables scriptVar = new Westwind.Web.Controls.Controls.wwScriptVariables(this, "variables");
  10:         scriptVar.Add("lblResultado", this.lblResultado.ClientID);
  11:
  12:         if (EsNumero(this.txtValor.Text)) {
  13:             scriptVar.Add("esNumero", "true");
  14:             this.lblResultado.Text = "Es un número!";
  15:         } else {
  16:             scriptVar.Add("esNumero", "false");
  17:             this.lblResultado.Text = "No es un número!";
  18:         }
  19:     }
  20:
  21:     private bool EsNumero(string valor) {
  22:         int val = 0;
  23:         if (int.TryParse(valor, out val)) {
  24:             return true;
  25:         }
  26:         return false;
  27:     }
  28: }

y del lado del cliente:

   1: $(document).ready(function() {
   2:     var lbl = $("#" + variables["lblResultado"]);
   3:
   4:     // Aplicamos distintas clases dependiendo del resultado
   5:     if (variables["esNumero"] == "true")
   6:     {
   7:         lbl.addClass("resultadoNumero");
   8:     } else {
   9:         lbl.addClass("resultadoTexto");
  10:     }
  11: });

El funcionamiento de la clase es muy sencillo, básicamente lo que hace es registrar los valores que queremos pasar al cliente y dentro del evento PreRender genera el siguiente script:

   1: <script type="text/javascript">
   2: //<![CDATA[
   3: var variables = {
   4:     "lblResultado": 'ctl00_ContentPlaceHolder1_lblResultado',
   5:     "esNumero": 'false'
   6: }
   7: //]]>
   8: </script >

Lo mejor de todo es que Rick pone a nuestra disposición el código completo de la clase para que la modifiquemos a gusto si así lo que deseamos.

La página donde pueden bajar esta clase es ésta, pero aclaro que esa es una versión vieja, hay una versión más nueva acá, la cual agrega nuevas funcionalidades como la posibilidad de actualizar el valor de las variables desde el cliente y pasárselas al servidor. Si no nos interesa esto último, les recomiendo usar la primer versión, ya que tiene menos dependencias y es mucho mas liviana.

¡Nos vemos en el próximo post!

Publicado originalmente en https://gerardocontijoch.wordpress.com.

Una respuesta to “Acceder a variables de servidor desde Javascript”

  1. […] por Gerardo Contijoch en Junio 12, 2009 En mi último post les comentaba sobre un gran problema que hay en ASP.NET (por lo menos hasta que salga la 4.0) con […]

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

 
A %d blogueros les gusta esto: