He de aclarar antes de empezar que este post no intenta ahuyentar a programadores que estén trabajando o evaluando ASP.NET AJAX, simplemente pretende atraer atención sobre el hecho de que hay que tener cuidado con lo que se hace con los UpdatePanels y no usarlos para todo 😉
Pongamos una simple página ASP.NET AJAX con un botón, al hacer click tendremos una llamada AJAX al servidor para actualizar la hora que se muestra en pantalla.
Ésta es la parte relevante del código
<asp:UpdatePanel ID=»up1″ runat=»server»> … el .aspx.cs … protected void actualizar(object sender, EventArgs ea) |
Cada vez que se pide la información al servidor estamos haciendo una petición de este tipo
ctl02=up1%7Cb1&__EVENTTARGET=&__EVENTARGUMENT=&__VIEWSTATE=%2FwEPDwULLTE1NzUzNjc2NjNkZPprXRC88qjwsppC6ijFSkTPpJOl
&__EVENTVALIDATION=%2FwEWAgLmpKatCgK%2B7%2BbtDMzDEjpVzHzhiCikPAfrk6sPE4AT&b1=Actualizar
y recibiendo una respuesta como esta…
129|updatePanel|up1|
<span id=»l1″>16:43:17</span>
<input type=»submit» name=»b1″ value=»Actualizar» id=»b1″ />
|112|hiddenField|__VIEWSTATE|/wEPDwULLTE1NzUzNjc2NjMPZBYCAgM
PZBYCAgMPZBYCZg9kFgICAQ8PFgIeBFRleHQFCDE2OjQzOjE3ZGRk+JnW9
BNv8dIcJmqvxt10mIGvh4w=|48|hiddenField|__EVENTVALIDATION|/wEW
AgL38IziBAK+7+btDLtfoq6BnTLgLznM9KGlIW/BK1GH|0|asyncPostBackControlIDs||
|0|postBackControlIDs|||4|updatePanelIDs||tup1|0|childUpdatePanelIDs|||3|
panelsToRefreshIDs||up1|2|asyncPostBackTimeout||90|12|formAction||Default.aspx
|27|pageTitle||Update Panel vs PageMethods|
…y teniendo en cuenta que sólo nos importa la parte en negrita… pues… como que es bastante…. El resto de información es:
En la petición… va la información del viewstate de la página, para que desde el aspx.cs podamos acceder a los controles de servidor y tomar decisiones en base a los valores (además de información de parámetros, eventos…)
En la respuesta…va la información para reconstruir gráficamente la parte de la página afectada por la operación
Pero además de la sobrecarga de tráfico generada, cuando el postback causado por la petición AJAX llega al servidor, con la información del viewstate se recrea la clase Page, se ejecutan los eventos de página, etcétera….lo cual es una sobrecarga para el servidor.
Esto no es malo, siempre y cuando vayamos a trabajar con estado nos hace falta regenerar la clase para poder tomar decisiones en base a los controles y el estado en curso. Pero en el caso que nos ocupa (obtener una fecha/dato independiente) todo esto es excesivo 🙂
Vamos a ver una alternativa que consume menos ancho de banda y menos recursos en el servidor
ASP.NET AJAX UpdatePanel vs PageMethods
Pero… que es un PageMethod???
Teniendo en cuenta que un aspx internamente es una clase System.web.Page. Un PageMethod es un método dentro de esa clase Page que cumple dos requisitos… es static y esta decorado con el atributo WebMethod. Lo que nos permiten es que podamos llamar desde javascript a un método específico de una página web aspx.
Si tenemos en cuenta que estamos obteniendo una funcionalidad concreta a través de una llamada desde Javascript, podemos decir que es algo «»»parecido»»» a un webservice.
La diferencia fundamental radica en que el PageMethod vive dentro de la página y ésta es el único cliente que puede consumirlo, mientras que el webservice es una funcionalidad que reside en un servicio accesible desde cualquier cliente, es un concepto mucho más amplio 🙂
En este ejemplo concreto podríamos llamar a un WebService en lugar a un PageMethod, conceptualmente nos da igual.
Vamos al lío….para llamar al pagemethod modificamos un poco el código cliente
Es necesario que habilitemos el trabajo con PageMethods estableciendo el valor de un flag del ScriptManager: <asp:ScriptManager runat=»server» id=»s1″ EnablePageMethods=»true» />
Esto va a crearnos un objeto Javascript que se llama PageMethods y que nos va a dar acceso a los metodos «especiales» de la página:
<script type=»text/javascript»>
function actualizar()
{
PageMethods.actualizar (actualizarOK, actualizarFAIL);
}
function actualizarOK(result)
{
$get(‘l1’).innerHTML = result;
}
function actualizarFAIL(error)
{
$get(‘l1’).innerHTML = «Intentelo mas tarde»;
}
</script>
Habéis observado que es más incómodo para el desarrollador que el UpdatePanel, dado que ahora somos nosotros los que tenemos que navegar por el DOM para actualizar la parte cliente.
En el lado cliente sólo nos falta modificar los controles ASP.NET para que apunten al Javascript
<asp:Label ID=»l1″ runat=»server» />
<input type=»button» id=»b1″ onclick=»actualizar();» value=»Actualizar»/>
y el servidor… configurar el método como PageMethod
using System.Web.Services;
….
[WebMethod]
public static string actualizar()
{
return System.DateTime.Now.ToLongTimeString();
}
Lo ejecutamos…..y…vemos que se envía menos información
( De hecho en el cuerpo no va nada… vemos que la petición al servidor es un post a http://server/website/default.aspx/actualizar para invocar al servicio )
y definitivamente vuelve menos información
{«d»:»15:56:53″}
Porqué un PageMethod y no un WebService?
A ojo de buen cubero…si dudáis… encapsulad esa información en un webservice, así estará accesible desde más puntos..obviamente habría que ver el caso concreto para ver si realmente no merece la pena tener un webservice, esto sería si la funcionalidad va a ser específica a esa página, en ese caso tiraríamos por un PageMethod
Lo dicho al principio
Este post no es para desanimar a nadie en el trabajo con UpdatePanels y AJAX, es para que penséis un segundo antes de liaros la manta a la cabeza y poner updatepanels por todas partes. Funcionar….funcionará, pero… a qué coste? 🙂
Happy hacking!
David Salgado