martes, 2 de junio de 2009

RegisterStartupScript y RegisterClientScriptBlock

Ayer estuve peleando un rato tratando de hacer que un script de JavaScript se ejecutara al cargar la página y como siempre traté de usar las famosas rutinas que provee Asp.Net para estos casos pero hace tiempo que no las usaba y tuve algunos problemillas que revisaré ahora.

En primer lugar los métodos RegisterStartupScript y RegisterClientScriptBlock ya no pertenecen directamente a la página (fueron desechados de esta ubicación) y deben ser llamados directamente desde una nueva clase encargada de estos scripts llamada ClientScript y que es parte de la misma página (Page.ClientScript).

En segundo lugar ahora podemos preguntar si el script ya ha sido agregado a la página para no estar re-creándolo de nuevo mediante el método IsStartupScriptRegistered.

Finalmente recuerdo haber usado antes casi siempre el método RegisterClientScriptBlock para registrar mis scripts en el lado del servidor y en el caso que estaba probando necesitaba que el script se ejecutara durante la carga de la página pero al usar este método la llamada al script se dibujaba antes que los elementos de la página estuvieran dibujados por lo tanto no hacía nada y me tiraba un error de JavaScript.

Averiguando la otra alternativa siempre era usar RegisterStartupScript pero no tenía clara la diferencia, y en mi caso éste método efectivamente funcionaba como yo quería porque la forma en que se dibuja en la página es distinta a RegisterClientScriptBlock.

Básicamente las diferencias entre ambos métodos radican en la posición en la que se dibujan los scripts solicitados, para ver como funciona aquí tenemos una llamada a ambos métodos en el code behind de una página de ejemplo (Default.aspx.cs):

protected void Page_Load(object sender, EventArgs e)
{
if(!ClientScript.IsClientScriptBlockRegistered("RegisterClientScriptBlock"))
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "RegisterClientScriptBlock", "document.write('RegisterClientScriptBlock');", true);

if (!ClientScript.IsStartupScriptRegistered("StartupScriptRegistered"))
Page.ClientScript.RegisterStartupScript(this.GetType(), "StartupScriptRegistered", "document.write('StartupScriptRegistered');", true);
}

Para el ejemplo usamos la siguiente página (Default.aspx):

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="Default" %>
<!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 runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<table>
<tr>
<td>Contenido</td>
</tr>
</table>
</div>
</form>
</body>
</html>

Al ejecutar la página podemos ver el siguiente resultado en el navegador:

RegisterClientScriptBlock
Contenido
StartupScriptRegistered
Si revisamos el código Html generado podemos ver cómo el método RegisterClientScriptBlock dibuja el contenido al principio de la página después del Form y del ViewState, también podemos ver cómo el método RegisterStartupScript dibuja el contenido solicitado al final de la página justo antes de cerrar el Form con lo que nos aseguramos que la página ya ha sido dibujada en el cliente antes de ejecutar el script que deseamos correr.

<!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>Untitled Page</title>
</head>
<body>
<form name="form1" method="post" action="Ejemplo.aspx" id="form1">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJNzgzNDMwNTMzZGT4JJog3qP93QeYemlckRLadGZVuw==" />
</div>
<script type="text/javascript">
//<![CDATA[
document.write('RegisterClientScriptBlock');//]]>
</script>
<div>
<table>
<tr>
<td>Contenido</td>
</tr>
</table>
</div>
<script type="text/javascript">
//<![CDATA[
document.write('StartupScriptRegistered');//]]>
</script>
</form>
</body>
</html>

Saludos.