|
Articulo desarrollado usando los Productos Express 2005 de Microsoft.
Una de las grandes preocupaciones en la que estamos inmersos las personas encargadas de desarrollar software es la performance y la amigabilidad de nuestra aplicacion con el usuario final. En los proyectos web en los que he participado siempre he notado la molestia del usuario frente a ciertos Refrescos de pagina que se da en cada Postback que realiza nuestra aplicacion, ademas de otros problemas que se suscitan tales como la perdida de la posicion del scroll, problema que fue solucionado en parte por el atributo SmartNavigation de la directiva page, pero que de igual manera generaba problemas al momento de trabajar con ciertas caracteristicas especiales como Hojas de Estilo, las cuales se perdian en cada refresco que se hacia, al ir hasta el servidor, procesar cierta informacion y devolverla al cliente.
Frente a esta situacion existia soluciones que evitan esa ida y vuelta, entre ellas tenemos el uso de XMLDOM, cuyo esquema de trabajo era el siguiente:
Generabamos una pagina dinamica que seria la encargada de procesar la informacion del lado del servidor, esta pagina en si solo devolvia tags en formato xml con la informacion a ser utilizada por el cliente.
La pagina cliente, usando javascript recuperaria los datos desde el servidor en formato xml y lo utilizaria de la manera mas conveniente, de la siguiente manera:
|
Codigo utilizado anteriormente para traer datos del servidor sin hacer refresco
de pagina. |
<script language='javascript'>
//funcion para obtener las provincias en base
a un Dept elegido.
function ObtenerProvincias(oDept)
{
//Instaciamos DOM
var oXml = new ActiveXObject('MICROSFT.XLMDOM');
//Llamado a la pagina en background.
oXml.load('frmGeneradorXML.aspx?opcion=pr&dept='
+ oDept );
var root = oXml.documentElement;
//manejo de codigo cliente para procesar
los datos obtenidos.
}
</script> |
Si bien este metodo para traer datos funcionaba, tenia ciertas limitaciones que tenian que ser salvadas con mas codigo como para poder detectar si la maquina cliente contaba con el objeto DOM instalado, ademas que debia manejarse una pagina intermedia en la cual se generaba los datos en formato xml, y cuando ya se tenia bastantes metodos dentro de la misma, si se generaba un error en alguno de los metodos implicaba que todas las paginas que invocaran a esa pagina intermedia no funcionaran.
Ahora en ASP en su version 2.0, se ha tratado de dar una solucion a esta problematica incluyendo el manejo de Callback, que permite que ciertas rutinas del lado del cliente puedan hacer llamados a eventos del lado del servidor, recuperar estos valores y procesarlos segun su logica de negocios, ya para obtener descripciones, validar datos o disparar eventos.
En este documento vamos a solucionar un problema tipico que la mayoria de desarrolladores hemos pasado y que viene a ser el llenado de combos relacionados entre si, pero sin tener que refrescar toda la pagina para traer esos nuevos valores, para esto utilizaremos las herramientas que Microsoft nos provee, en este caso Visual Web Developer 2005 Express.
La idea es que tenemos dos combos, un combo inicial lleno con departamentos y que frente a la accion de seleccionar un departamento en este combo automaticamente y sin hacer Postback debemos llenar el segundo combo de las provincias pertenecientes al departamento elegido, los datos podrian obtenerse ya sea desde una base de datos o de un archivo xml, en este caso use un archivo xml por razones de que puedan estudiar la demo y no tengan problemas respecto al manejo de base de datos, los datos los obtendremos del archivo llamado Estructura.xml y la interfaz de usuario quedaria de la siguiente manera:
|
Interfaz de Usuario para este ejemplo. |
|
|
Formato del documento xml. |
<?xml version="1.0" encoding="utf-8" ?>
<Datos>
<Departamento>
<nombre>La Libertad</nombre>
<Provincias>
<nombre>Trujillo</nombre>
<nombre>Ascope</nombre>
<nombre>Gran
Chimu</nombre>
</Provincias>
</Departamento>
<Departamento>
<nombre>Cajamarca</nombre>
<Provincias>
<nombre>Contumaza</nombre>
<nombre>Cajabamba</nombre>
</Provincias>
</Departamento>
</Datos>
|
Luego de definir esto ya podemos empezar. En primer lugar creamos un nuevo web site, esto nos generara una pagina por defecto denominada default.aspx y con su codigo del lado del servidor alojado en el archivo default.aspx.vb. Lo primero que debemos hacer es que nuestra clase implemente la interfaz ICallbackEventHandler, el implementar esta interfaz ademas nos obliga a declarar una funcion denominada RaiseCallbackEvent, sera esta la funcion que invocara nuestro metodo del lado del cliente en donde se le pasara como parametro el departamento y que devolvera una cadena con las provincias concatenadas pertenecientes al mismo.
|
Codigo a implementar. |
Partial Class Default_aspx
Implements
ICallbackEventHandler
'Metodo que devolvera la cadena a la funcion javascript del lado del cliente.
Public Function RaiseCallbackEvent(ByVal eventArgument As String) As String Implements
System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent
End Function
End Class |
El flujo de ejecucion de nuestra aplicacion sera el siguiente:
|
Flujo de ejecucion. |
|
Primero en el evento load del lado del servidor se generara el script que manejara el evento onchange del combo de departamentos (1), en ese codigo se hace referencia a el metodo javascript "ObtenerProvincias" que se ejecutara en caso la function RaiseCallbackEvent se realice satisfactoriamente, en cambio si se da algun error se ejecutara el metodo javascript "ErrorServidor". En cada nueva seleccion que se realize en el combo de departamentos se hara un llamado al metodo del servidor (3) que devolvera una cadena con las provincias.
En el evento Load, lo primero que hacemos es cargar los departamentos, y generar el metodo del lado del cliente encargado de disparar el evento que nos devolvera la provincias del departamento selecccionado, para que el servidor sepa cual es el actual departamento seleccionado, pasamos el segundo argumento en donde indicamos el valor seleccionado en el combo de departamentos en el lado del cliente, todo este codigo generado lo agregamos como atributo al combo de departamentos para de esta manera asociarlo al evento del lado del cliente "onchange", esto significa que se traera los datos del servidor cada vez que se seleccione un nuevo departamento en el combo. Para cargar los departamentos he utilizado el objeto XmlDataDocument que se encuentra en el namespace System.Xml, con este objeto cargo el documento xml en memoria y selecciono los nodos correspondientes a los departamentos usando xpath, luego de seleccionar los nodos, agrego los valores correspondientes al combo de departamentos. El codigo para esta parte es el siguiente:
|
Evento Load |
Private Sub form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles
form1.Load
If Not Page.IsPostBack Then
CargaDepartamentos()
End If
Dim strScript As String
Dim strArgumento As String = "document.all('ddlDepartamentos').options[document.all('ddlDepartamentos').selectedIndex].value"
Dim strContexto As String = "null"
strScript = Me.GetCallbackEventReference(Me, strArgumento, "ObtenerProvincias",
strContexto, "ErrorServidor") & ";return false;"
ddlDepartamentos.Attributes.Add("onchange", strScript)
End Sub
Private Sub CargaDepartamentos()
ddlDepartamentos.Items.Add("Seleccionar")
Dim xmlDoc As New XmlDataDocument
xmlDoc.Load(Server.MapPath("Estructura.xml"))
Dim root As XmlNode
Dim nodeList As XmlNodeList root = xmlDoc.DocumentElement
nodeList = root.SelectNodes("descendant::Departamento/nombre")
For Each nodo As XmlNode In nodeList
ddlDepartamentos.Items.Add(nodo.InnerText)
Next
End Sub |
La funcion que se ejecutara en el servidor cada vez que se elija un nuevo departamento se denomina RaiseCallbackEvent, tiene un parametro de entrada denominado eventArgument, el cual nos va a traer el nombre del actual departamento seleccionado, con este valor podremos recorrer el documento XML para solo elegir las provincias que pertenecen a ese departamento, luego de seleccionar los nodos de las provincias, obtenemos su valor y los concatenamos utilizando un separador(#), para de esta manera poder hacer un split en el cliente y mostrar por separado cada provincia como un nuevo item en el combo. Para la concatenacion he usado StringBuilder ya que pueden existir muchas provincias para el departamento seleccionado y el usar un objeto de tipo String implica crear una nueva instancia del mismo cada vez que se hace una concatenacion, por el contrario stringBuilder usa la misma instancia mejorando esto la performance. Esta funcion al final retorna la cadena con los valores ya concatenados.
|
Evento de Servidor |
Public Function RaiseCallbackEvent(ByVal eventArgument As String) As String
Implements System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent
Dim sbResultado As New StringBuilder(String.Empty)
If eventArgument.Length > 0 Then
Dim xmlDoc As New XmlDataDocument
xmlDoc.Load(Server.MapPath("Estructura.xml"))
Dim root As XmlNode = xmlDoc.DocumentElement
Dim nodeList As XmlNodeList
Dim nodeListChild As XmlNodeList
nodeList = root.SelectNodes("descendant::Departamento[nombre='"
& eventArgument & "']")
For Each nodo As XmlNode In nodeList
nodeListChild
= nodo.SelectNodes("Provincias/nombre")
For Each nodoHijo
As XmlNode In nodeListChild
sbResultado.Append(nodoHijo.InnerText & "#")
Next
Next
End If
Return sbResultado.ToString
End Function |
Ahora luego de haber implementado el codigo del lado del servidor pasamos a revisar el codigo del lado del cliente para que nuestra aplicacion funcione correctamente. Primero implementare la funcion que se ejecutara en caso no haya existido problemas al generar los resultados, la funcion se denomina "ObtenerProvincias" y tiene como parametro el actual Departamento seleccionado en el combo. Lo primero que hacemos aca es definir un array en donde almacenaremos todos los resultados que nos envie el servidor, debo recordarles que los resultados vendran concatenados y con un separador (#), por lo que es necesario que hagamos un split a esta cadena para separar uno a uno los elementos y asi poder almacenarlos en el array que acabamos de crear. Luego de tener a nuestras Provincias dentro del array lo siguiente que hacemos es Remover del combo todas las provincias que este tiene, para evitar que se mantengan los datos de la seleccion anterior. Luego de eso recorremos el array uno a uno y vamos agregando los elementos al combo de provincias que acabamos de limpiar.
La otra funcion que implementaremos es la que se ejecutara en caso exista algun error al intentar traer los datos del servidor. la llamaremos "ErrorServidor" y lo unico que hara es mostrar un mensaje en un alert al usuario indicando que ha habido problemas al intentar traer los datos.
|
Eventos del Cliente |
<script language="javascript">
function ObtenerProvincias(oDatos)
{
var Prov = new Array();
var cboProv = document.all('ddlProvincias');
while (cboProv.length)
{
cboProv.remove(cboProv.options[0]);
}
Prov = oDatos.split('#');
for (var i = 0; i< Prov.length ; i++)
{
if (Prov[i].length
> 0)
{
cboProv.options[i] = new Option(Prov[i], Prov[i]);
}
}
}
function ErrorServidor(oMensaje, oContexto)
{
alert(oMensaje);
}
</script> |
y listo!!!! ya estaria implementada nuestra funcionalidad. El resultado se mostraria tal como se ve en la siguiente figura:
|
Flujo de ejecucion. |
|
Conclusion
Esta nueva caracteristica de ASP 2.0, nos permite obtener datos desde el servidor , tambien la posiblidad de poder ejecutar eventos en el servidor o actualizar objetos en el mismo, ademas de poder traer descripciones al cliente o validar datos que requieran ir hasta una base de datos para hacerlo. Lo importante es entender la definicion de esta nueva caracteristica y el resto ya es parte de la imaginacion de los desarrolladores, desde luego que gracias a esto ahora podemos evitar tener que refrescar toda la pagina, accion que no es muy apreciada por nuestros usuarios finales, ademas de evitar hacer un render completo para traer solo algunos datos en el cliente.
Referencias
ASP.NET 2.0's Client Callback Feature - http://www.dotnetjunkies.com/Tutorial/E80EC96F-1C32-4855-85AE-9E30EECF13D7.dcik
Script Callbacks in ASP.NET - http://msdn.microsoft.com/msdnmag/issues/04/08/CuttingEdge/default.aspx
Asynchronous Callbacks - http://weblogs.asp.net/dneimke/archive/2004/06/24/163561.aspx
Productos Express MS -
http://lab.msdn.microsoft.com/vs2005/get/default.aspx#express
|

Version PDF |
Copyright © 2002-2004 Grupo
Informatizate. Reservados todos los derechos.
Prohibida la reproducción total o parcial en cualquier
formato sin previa autorización.
On-line desde el 27 de Noviembre del 2002
|
|