Friday, November 26, 2004

To Be Peruvian Is...

Disclamer: Cualquier semejanza con la realidad es pura coincidencia :)

Llevar tu bolsita cuando vas a una fiesta infantil, para tirarse todos los bocaditos.

Tirarse los sachet de mostaza y mayonesa cuando vamos al burguer.

Es decirle a tu prima para jugar al Papá y a la Mamá.

Tirarte un juergón de las 9 de la noche a las 6 de la mañana, con su pan con chicharrón y camote frito, tan delicioso como un ceviche con su chela pa'cortarla y con dos mas pa' seguirla.

Subir a la Combi diciendo "Una china aca a 3 cuadras" y se van hasta 20 cuadras.

Meterte donde no te importa...

Andar fashion hasta cuando no tienes ni para un te ....

Es ir al mercado del barrio con una bolsa ya toda arrugada de Wong o Metro que usaste hace tiempo para una fecha especial, y despues te panudeas diciendo q haces tus compras ahi ...

Llegar al paradero cerca a tu jato a las 7 de la mañana pa ir a estudiar o a trabajar y escuchar una melodiosa voz q te dice..... Todo ermitaño, balanza, hospital, curva, independencia, quiosco rico, 8 esquinas, revision tecnica, trocadero, zarumilla, todo benavides, larco, pardo, cmdte espinar, conquistadores, javier prado este, toda la marina, Faucett, aeropuerto,HABLA VAS???? oe chino cambiame 5 lucas en ripios, cierra la puerta, quita el letrero, pie derecho. 2, 1, 2, 1 se va Orion sigue Star guarda con Pamela Techo Alto adelante se va con 8 carro planchado, viene en correteo lobo gris y el GRINGO pisa pisa, suelta mi ferro pe!!!!!

Es reunirte con tus patas para chupar,hacer una chanchita de luca c/u pa comprar una oferta de CABITO ,y una vez que se pican son capaces de vacear sus bolsillos ,incluso quedarse sin pasaje ,por seguir chupando.

Es broncearte en el techo de tu casa y decir que has pasado el fin de semana en mancora o en colan.

Es aprovechar los martes, "dos por uno", pasar caleta, tu gaseosa de a luca, y tu bolsita de chisitos, y hacerla linda en el cine. Es que los peruanos somos misios pero nos las arreglamos.

Es tirarse la plata de la semana en una trancaza y luego decir la plata no alcanza y que el Cholo tiene la culpa es que no pagan bien y no hay trabajo...!!! ...

Es levantarse con optimismo todos los dias y tener fe que el PERU v ha cambiar algun dia...

Saturday, November 20, 2004

DataLayer.Primitives and DataLayer.Primitives.Core Public Version Released...!!!

Les entrego la version publica del DataLayer.Primitives and DataLayer.Primitives.Core

Que podran descargar de cualquiera de los siguentes lugares:

http://www.msnusers.com/guydotnetxmlwebservices/Documents/DataLayer.zip

http://www.msnusers.com/guydotnetxmlwebservices/Documents/DataLayer.rar


Pero previamente deberan unirse al grupo a traves del siguiente link:
http://groups.msn.com/guydotnetxmlwebservices/join

¿Que es DataLayer.Primitives and DataLayer.Primitives.Core? ¿Y para que sirve?

Es la solucion .NET orientada a la capa de acceso a datos de un producto de software que se desarrolla sobre la tecnologia del .NET Framework.

La intencion es poder construir un producto basado en una arquitectura de tres capas. Que permita flexibilidad y escalabilidad dentro de su tiempo de vida..

¿Como podria usarlo dentro de mi desarrollo de software?

Generalmente, deberiamos contar con tres soluciones, para la construccion de un producto de software.

DataLayer.sln -> Orientado a la capa de acceso a datos.
BusinessLayer.sln -> Orientado a logica de negocio
UserLayer.sln -> Orientado a interfaz del usuario

En esta oportunidad, les entrego la version publica del DataLayer.sln

¿Que existe dentro del DataLayer.sln?

En el encontraremos, los siguientes proyectos .cs.proj

CommonLayer.Customs : Clases customizadas para un uso particular
CommonLayer.Nullables : Tipos de datos que soportan nulo
CommonLayer.Exceptions : Excepciones para su uso dentro del producto
DataLayer.Primitives and DataLayer.Primitives.Core : Bloque orientado a las operaciones contra la BD
DataLayer.WinApp : Proyecto que testea esta capa de la arquitectura.

¿Como interactua el DataLayer.Primitives and DataLayer.Primitives.Core con las demas capas?

El BusinessLayer.sln es el lugar de donde podras interactuar con el DataLayer.Primitives and DataLayer.Primitives.Core y hacer uso de las clases que ella te brinda para poder consruir las operaciones contra la Base de Datos.

Dentro de ls version publica del DataLayer.Primitives, encontraras las siguientes clases:

PrimitiveEntity : Es una clase que debe ser heradada necesariamente para permitirte aprovechar las operaciones basicas para una tabla de base de datos, desde la perspectiva CRUD. Sobre escribiendo los metodos OnSelect, OnInsert, OnUpdate y OnDelete para poder indicar los parametros que han de ser usados para la ejecucion de cada uno de los stores procedures que han de realizar dichas operaciones.
PrimitiveExecutable : Es una clase que simplemente de ser instanciada para poder ejecutar operaciones contra la base de datos, sean estas a traves de store procedures o sentencias sql.
PrimitiveParameter : Es la clase que nos permitira la creacion sencilla de diferentes tipos de parametros para ser entregados en la ejecucion de los stores procedures, al PrimitiveEntity o el PrimitiveExecutable, dependiendo de lo que hayas usado para realizar operaciones contra la DB.
PrimitiveParameterCollection : Es una colleccion de PrimitiveParameter basada en DictionaryBase, para poder tener un acceso inmediato a cada uno de los elementos de la colleccion con solo tener el nombre del parametro. Muy util cuando se deseas retornar valores a traves de los parametros de un store procedure. Pero siempre usado en todo lugar del DataLayer.Primitives donde se necesiten parametros.
PrimitiveProcedure : Es una estructura que encapsula la definicion basica de un store procedure.
PrimitiveSql : Estructura simple para definir una sentencia SQL.

¿Como deberia estar estructurado el BusinessLayer.sln para poder interactuar facilmente con el DataLayer.Primitives and DataLayer.Primtives.Core?

El BusinessLayer.sln deberia contar con los siguientes proyectos:

BusinessLayer.Components and BusinessLayer.Components.Collections : Es el proyecto en el cual se establecen las clases que encapsulan la logica del negocio a la cual esta orientada el producto.
BusinessLayer.Entities : Aqui se definen las entidades que han de ser el medio por el cual se enviar informacion entre la capa del usuario y la logica de negocio.
BusinessLayer.IDataWrapper : Establece las interfaces para realizar operaciones permitidas contra la DB
BusinessLayer.DataAccess : Es el nexo entre las capa de negocio y la capa de datos. Es aqui donde se hace referencia explicita para poder hacer uso de las clases que brinda el DataLayer.Primitives and DataLayer.Primitives.Core.
BusinessLayer.WinApp : Es el proyecto que permite testear esta capa de la arquitectura.

¿Que es lo que no trae esta version publica del DataLayer.Primitives and DataLayer.Primitives.Core?

No todos los tipos de datos nulos estan entregados en esta version publica. Solo he liberado NullInt32, NullString, NullDataTime. Apoyados por la interfaz INullable. Esto dentro del CommonLayer.Nullables

No se ha entregado toda la gama de excepciones usadas para la construccion de los proyectos que lidero. Solo tres excepciones muy basicas. Esto dentro del CommonLayer.Exceptions.

Solo se ha liberado el CustomDataSet. Esto dentro del CommonLayer.Customs.

Del mismo modo, no se ha liberado el soporte para las transacciones contra la DB ni el soporte para todos los tipos de datos, en la creacion de PrimitiveParameter. Esto dentro de DataLayer.Primitives.

¿No hay mayor informacion sobre el DataLayer.Primitives.Core?

Digamos que justamente es el nucleo del DataLayer.Primitives. Las clases que se definen en ese namespace, tienen la particularidad de ser internal por lo que su uso no va mas alla del assembly correspondiente al DataLayer.Primitives.

¿Que tienes pensado liberar proximamente?

Seria ideal poder liberar un BusinessLayer.sln orientado a una realidad de negocio en particular que permita apreciar el uso adecuado del DataLayer.Primitives and DataLayer.Primitives.Core.

¿Cuando lo piensas hacer?

Coming soon...

Wednesday, October 20, 2004

Google Desktop Released

Para quienes aun no han descargado el ultimo juguete de Google, os invito:

Google Desktop
http://desktop.google.com/



Esta aplicacion aun corre sobre una web browser. Y no es una aplicacion desktop natural, como todos conocemos.

Uno quisiera tal vez, una agradable experiencia con el producto por tratarse de una aplicacion pequeña. O cierta integracion con el sistema operativo o con otras aplicaciones. Algo relativamente similal al Babylon o el WinZip

Pero aun asi, sigue siendo una opcion interesante. Al ver tan lejos a WinFS.

Este nuevo juguete se pasa algunas horas indexando la informacion de tu PC, tus documentos office, correos, HTML y TXT. Por unica vez.

Para luego darte resultados inmediatos, al realizar tus busquedas sobre el mismo Destop Google o sobre http://www.google.com/

En fin, un motivo para olvidar la opcion search del nuestro querido amigo, Windows.

Claro, si usas el Index Server de tu IIS sobre tu PC. Y haz aprovechado la interfaz que brinda, para visualizar tus documentos a traves de busquedas, pues no esta mal.

Pero para el publico en general, es una opcion agradable y facil de usar.

Microsoft Virtual PC 2004 - Service Pack 1

... y hasta que salio el primer Service Pack para VPC 2K4. :)

Para todos los que trabajamos frecuentemente con este producto, resulta una muy buena noticia, de veras.

http://www.microsoft.com/downloads/details.aspx?FamilyId=B07C9EF0-265A-4237-AE3B-25BC8937D40F&displaylang=en

Denle una revisada al README, para conocer mayores detalles de las correciones y mejoras que vienen con este parche:

http://download.microsoft.com/download/6/9/d/69de9b67-6498-41fb-9add-95ceab6eb5cc/readmesp1.htm

Friday, October 01, 2004

Inquire into MONO

Continuaba en mi afanoza investigacion sobre MONO, la plataforma de desarrollo de software libre basado en el .NET Framework que permite contruir aplicaciones GNU/Linux con una productividad sin precendentes sobre plataformas como Unix, Linux y MacOS, y me encontre con este post en el blog de Chris Anderson, uno de los arquitectos de Avalon:

Miguel, lets chat...
http://www.simplegeek.com/PermaLink.aspx/eb453f85-10e3-48ee-a6f5-cc4b886ce668

En respuesta a lo que Miguel De Icaza, quien lidera actualmente el equipo del proyecto MONO para la empresa Novell, escribio en este post:

Longhorn changes
http://primates.ximian.com/~miguel/archive/2004/Sep-01.html

Miguel, es mexicano, orgullo hispano para la comunidad Linux. Fue lider y fundador de la fundacion GNome, de su empresa Ximian y desarrollador instrumental de Linux para SPARC. Fue galardonado con el Premio del Software Libre y el premio Innovador del Año, ambos en el año 1999. Y algun otro galardon, seguramente... ;)

Es uno de los impulsores del Proyecto MONO, cuya implementacion se basa en los estandares de ECMA C# y la infraestructura del lenguaje comun. MONO incluye las herramientas de desarrollo necesarias para crear aplicacion de cliente y servidor.

Aun más, Miguel replico lo expuesto por Chris Anderson, en funcion a las criticas que el habia espobazado inicialmente y que Chris habia respondido, a traves de este post:

Avalon Part 2
http://primates.ximian.com/~miguel/archive/2004/Sep-09.html

Hace un tiempo, Miguel desecho una propuesta de Microsoft para trabajar en Redmond. Y uno de los arquitectos de Indigo, lo tuvo en sus planes, lo que se puede corroborar en una entrevista que le hace Microsoft-Watch a Don Box.

http://www.microsoft-watch.com/article2/0,1995,1418558,00.asp

Si te interesa leer la historia completa de Miguel, podrias verlo en:

http://www.rebelion.org/noticia.php?id=3911

Su blog personal es: http://primates.ximian.com/%7Emiguel/activity-log.php

Vale...!

Thursday, September 09, 2004

gmail is for me, too. Thanks Google!!!

El dia martes consegui mi cuenta de gmail a traves de un amigo de USA - Seattle. Al parecer pude calificar a este restringido servicio, aun :)

http://gmail.google.com

A pesar que aun se encuentra en version Beta. Las funcionalidades que brindan al usuario son muy comodas e intesantes.

Por ejemplo, propone el folder STARRED, que permite marcar nuestros emails con la finalidad de que estos puedan ser encontrados posteriormente, con mayor facilidad. Uno podria marcar multiples veces un email, para darle cierto status, a este.

La opcion de Archivar, brinda la posibilidad de alojar nuestros mails en un lugar logico, sin que sean eliminados aun. Pero tambien sin una acceso inmediato salvo al seleccionar la opcion 'All Mail'.

Ni que decir de la opcion de busqueda. Algo relativamente similar a lo que ya nos brindaba Yahoo, cuando hace dos meses atras hicieron el upgrade de su servicio. De pronto, un dia, mi buzon aparecio con 2GB de espacio disponible. Santo Dios!!!

Ni modo, para todos aquellos que deseen una cuenta de gmail, me envian un mensaje, a mi reciente cuenta de correo electronico:

Javier Luna AT gmail
javier.a.luna@gmail.com

Tuesday, September 07, 2004

I wanna be unplugged of my PC

Surfeando por la red, me encontre con el blog de Mauricio Sougarret.

¿Que quien es el? Uhm, bueno. El es uno de los chicos que trabaja para Microsoft Peru. Y participa constantemente de los eventos tecnologicos del gigante del software, aqui en nuestro querido pais.

Me di un tiempo para leer un post que finalmente me agrado.

Me estare poniendo viejo
http://msougablog.blogspot.com/2004/06/me-estar-poniendo-viejo.html

Nos habla un poco sobre la añoranza de las cosas que ha cambiado en nuestras vidas y de aquellas que hemos dejado detras, debido a como la tecnologia se ha hecho parte importante en nuestro dia a dia.

Os recomiendo ;)

Wednesday, August 25, 2004

Wonderful User Interface

El Microsoft Center for Information Work (MSCIW), fue uno de los ganadores en uno de los eventos de diseño mas importantes del mundo, Industrial Design Excellence Award, hace un año atras.



Este proximo entorno de trabajo, propuesto por Microsoft, estara orientado a incrementar la productividad de nosotros, es decir todo aquel que interactua con una PC para su trabajo del dia a dia.

Incluira productos de los prototipos que han sido planeados dentro de ese amplio conjunto de ideas que emergen del equipo de Microsoft Research y otras divisiones de Microsoft.

Desde otra perspectiva

Click para ver en popup

La interfaz de usuario deberia ser muy diferente a las que actualmente apreciamos en nuestra PCs.

Podria ser algo como lo que podemos ver en el siguiente link, para sacar provecho de ese precioso monitor pantalla enormemente ancha, que vemos en la primera imagen.

Click para ver en popup

Simplemente, alucinante!!!

El proximo release de Windows, codename Longhorn, que seria liberado el 2006, no participara concretamente de todas estas bondades, aun. Pero es el inicio para ello.

Longhorn - Contact User Experience
http://www.msdn.microsoft.com/longhorn/default.aspx?pull=/library/en-us/dnaero/html/wux_topic_contacts.asp

Esto ultimo no deberia verse tan distante o lejano en el tiempo. Si se tiene la curiosidad de experimentar con ello, ahora en nuestras PCs, solo es cuestion de preguntar ¿como lo consigo? ;)

MSN Web Messenger, Wow Yeah!!!

Los primeros dias de agosto fue liberada la version web de MSN Messenger.

http://webmessenger.msn.com/

A pesar que contabamos con diferentes medios para poder estar online a traves de nuestra propia cuenta, cuando no teniamos el permiso para poder instalar el cliente del MSN Messenger o el firewall bloqueaba los puertos. Algunos de esos medios no brindaban una autentificacion Passport.NET directa hacia el usuario por lo que nuestro muy codiciado password podia estar viajando por la red a su libre albedrio. Nada seguro por cierto.

Algunos hemos usado Hopster desde hace algun tiempo atras cuando nos encontrabamos enclaustrados en algun ambiente si salida al MSN Messenger. Con algunas limitaciones como no poder usar la Web Cam o el Audio, pero a no tener nada ;)

Ahora no tendremos que hacer tantos artificios para poder estar online con nuestro contactos.

A pesar que solo brinda un numero limitado de conecciones, pues aun es un trial. Sigue siendo una opcion interesante.

Asi que si ves un iconito con el mundo verde-azul dentro de tu lista de contactos, te percataras que ese contacto esta logeado sobre el nuevo MSN Web Messenger.

Por cierto, uno de los requerimientos para usarlo es:

Sobre Microsoft Windows
- Microsoft Internet Explorer 5.0 +,
- Netscape 7.0 +,
- Mozilla 1.6 +

Desde estos browser con soporte JavaScript:
Podria trabajar sobre OS-X (con Camino) y Linux (con FireFox).

Al parecer tambien trabaja sobre MAC OS 8/9 con IE 5.1 :)

Tuesday, August 24, 2004

Handling Events and Delegates

Una de las cosas mas interesantes que trajo consigo la llegada de ASP.NET, aya por el año 2002, fue la posibilidad de encapsular logica e interfaz de usuario a traves de los ahora muy conocidos Web User Controls.

Esto nos ha permitido reutilizar dichas funcionalidades a lo largo de nuestro projecto web, permitiendo reducir algunas lineas de codigo, haciendo mas sencillo y flexible los posteriores mantenimientos.

Sin embargo, la manera profesional de trabajar con los Web User Controls consiste en definir eventos, a partir de los cuales se envian mensajes hacia la entidad que los contenga, que generalmente son Pages u otros Web User Controls.

La intencion esta en que las paginas ASP.NET, asuman el rol de gestores de los eventos de los diferentes Web User Controls que contengan dentro de el.

Les alcanzo un pequeño ejemplo que podria mostrar lo sencillo que es definir un evento para un Web User Control, haciendo uso de un Delegate que define cierta firma a la que se ha de ajustar el evento que deseamos publicar.


Archivo .ASCX


<%@ Control Language="c#" AutoEventWireup="false" Codebehind="SearchEngine.ascx.cs" Inherits="DemoWebAppCSharp.Event.SearchEngine"%>
<asp:TextBox id="_text" runat="server"></asp:TextBox>
<asp:Button id="_go" runat="server" Text="Go"></asp:Button>

--- End File ---

Este archivo define como se ha de estructurar la interfaz del usuario para este Web User Control en particular.

Algo tan simple como un TextBox y un Button para un sencillo buscador.


Archivo .ASCX.CS



namespace DemoWebAppCSharp.Event
{
using System;
using UserInterface;

/// <summary>
/// Definimos el delegate que define la firma con la que publicaremos el evento
/// </summary>
public delegate void ClickedEventHandler( Object sender, ClickedEventArgs e );

/// <summary>
/// Este Web User Control hereda de un clase que permite encapsular
/// cierta funcionalidad similar para todos los controles de
/// nuestro projecto web
/// </summary>
public class SearchEngine : CustomControl
{
protected System.Web.UI.WebControls.TextBox _text;
protected System.Web.UI.WebControls.Button _go;

/// <summary>
/// Publicamos el evento Clicked del tipo ClickedEventHandler
/// el delegate que habiamos definido lineas arriba
/// </summary>
public event ClickedEventHandler Clicked;

/// <summary>
/// Es requisito sobre-escribir este metodo para todo Web User Control
/// que diga decente :)
/// </summary>
/// <param name="e">Uhmmm... obvio!!!</param>
protected override void OnInit( EventArgs e )
{
base.OnInit( e );

// Enganchamos el metodo SearchEngine_Load al evento Load del control
this.Load += new EventHandler(SearchEngine_Load);

// Enganchamos el metodo Go_Click al evento Click del Button
this._go.Click += new EventHandler( this.Go_Click );
}

private void SearchEngine_Load(object sender, System.EventArgs e)
{
}

/// <summary>
/// Este metodo estara enganchado al evento Click del Button
/// que se muestra en la interfaz del usuario del Web User Control
/// y soltara el evento propio de este control para dicha accion Clicked.
/// </summary>
/// <param name="sender">Una instancia de quien ocasiona el evento</param>
/// <param name="e">Informacion del evento</param>
private void Go_Click(
Object sender,
EventArgs e )
{
// Lanzamos el evento Clicked. Alguien lo gestionara y sino no hay problema
if( this.Clicked != null )
this.Clicked( this, new ClickedEventArgs( this._text.Text ) );
}
}

/// <summary>
/// Esta clase encapsula cierta informacion particular para el evento Clicked
/// del Web User Control que estamos implementando SearchEngine.
/// Lo unico que enviara es el texto que fue ingresado en el TextBox del
/// control para que se realize la accion esperada del usuario.
/// </summary>
public class ClickedEventArgs : EventArgs
{
private String _text;

public ClickedEventArgs( String Text )
{
this._text = Text;
}

public String Text
{
get { return this._text; }
set { this._text = value; }
}
}
}

--- End File ---

Aqui implementamos la manera en como nuestro Web User Control ha de interactuar con el usuario. En funcion a las opciones que permitamos, realizaremos ciertas acciones a traves de Eventos. En este caso particular, al hacer 'click' sobre el Button lanzaremos el evento Clicked propio de este Web User Control.

Para ello tenemos que engancharnos al evento Click del Button y dentro de su implementacion disparar nuestro propio evento, Clicked.

Debido a que tenemos la intencion de enviar cierta informacion a traves del evento. La manera de llevarlo a cabo es usando el definiendo una clases que herede de EventArgs. En nuestro caso particular ClickedEventArgs. El cual solo cuenta con una propiedad llamada Text, donde colocaremos el dato que haya ingresado el usuario sobre el TextBox del Web User Control.

El evento que publicaremos debe ajustarse al Delegate que hemos definido, ClickedEventHandler. Este delegate se ajusta a cierta firma, propia para este evento.

No hubiera sido necesario definir este Delegate si no hubieramos visto conveniente una firma particular para el evento o enviar informacion a traves de el.

En ese caso, hubiera sido suficiente definir el evento Clicked del tipo EventHandler, el delegate por default. De ese modo, ya no seria necesario enviar informacion adicional como parte del evento. Entonces tendrias que usar EventArgs.Empty en el momento de lanzar el evento Clicked.



Archivo .ASPX



<%@ Register TagPrefix="Custom" TagName="SearchEngine" Src="SearchEngine.ascx" %>
<%@ Page language="c#" Codebehind="Holder.aspx.cs" AutoEventWireup="false" Inherits="DemoWebAppCSharp.Event.Holder" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>Holder</title>
</HEAD>
<body>
<form id="Form1" method="post" runat="server">
<table>
<tr>
<td>
<Custom:SearchEngine id="_engine" runat="server"></Custom:SearchEngine></td>
</tr>
<tr>
<td>
<asp:TextBox id="_show" runat="server"></asp:TextBox>
</td>
</tr>
</table>
</form>
</body>
</HTML>

--- End File ---

Este archivo contiene el Web User Control y un TextBox.

La intencion con propositos de testeo, es la de pintar el texto ingresado por el TextBox del Web User Control sobre el TextBox de la Page.


Archivo .ASPX.CS



namespace DemoWebAppCSharp.Event
{
using System;
using UserInterface;

/// <summary>
/// Esta es la pagina que contendra el Web User Control que hemos implementado
/// Por cierto, hereda de una pagina que define cierta funcionalidad similar
/// para todas las paginas de nuestro proyecto web.
/// </summary>
public class Holder : CustomPage
{
protected System.Web.UI.WebControls.TextBox _show;
protected SearchEngine _engine;

/// <summary>
/// Del mismo modo, que para el Web User Control es requisito para
/// toda Page que se diga decente.
/// </summary>
/// <param name="e"></param>
protected override void OnInit( EventArgs e )
{
base.OnInit( e );

// Enganchamos el metodo Holder_Load al evento Load de la page
this.Load += new EventHandler(Holder_Load);

// Enganchamos el metodo Engine_Clicked al evento Clicked de Web User Control
this._engine.Clicked += new ClickedEventHandler( this.Engine_Clicked );
}

private void Holder_Load(object sender, System.EventArgs e)
{
}

/// <summary>
/// Este es el metodo que se enganchara al evento Clicked del Web User Control
/// y que dentro de su implementacion realizara la tarea que creemos
/// conveniente. Pero dicha accion estara dentro de la jurisdiccion de la Page.
/// </summary>
/// <param name="sender">La instancia de quien genera el evento</param>
/// <param name="e">Informacion propia de este evento</param>
private void Engine_Clicked(
Object sender,
ClickedEventArgs e )
{
// Algo tan sencillo como pintar el texto ingresado por el control sobre otro TextBox
this._show.Text = e.Text;
}
}
}

--- End File ---

Para llevar a cabo dicho testeo, tenemos que subscribirmos al evento Clicked del Web User Control. De esa manera, coger la informacion que trae consigo el evento para poder realizar una accion. En este caso, ClickedEventArgs nos brinda el dato que el usuario hubiera ingresado sobre el TextBox del Web User Control. El cual nosotros cogeremos para poder colocarlo sobre el TextBox de la Page.

Monday, August 23, 2004

Searching .NET PetShop 4.0...???

Leyendo el blog de Chris Strevel, uno de los fundadores de Intellekt.NET una joven empresa mejicana dedicada a las Tecnologias de Informacion, me encontre con este post:

Microsoft .NET PetShop
http://intellekt.ws/dottextweb/chris/archive/2004/08/07/361.aspx

Curiosamente, Chris nos cuenta sobre la nueva version liberada del .NET PetShop. A lo que le preste atencion inmediatamente, pensando que seria algun nuevo release.

Me dispuse a ingresar al GotDotNet, pero solo encontre la version con la que ya venia trabajando desde hace un tiempo :(

¿Que paso Chris? ¿Por que nos haces esto?

Wednesday, August 18, 2004

Windows XP Service Pack 2

Microsoft, a liberado el nuevo service pack para Windows XP, esta ultima semana que paso.

Este parche, esta orientado muy verticalmente al tema de seguridad. Que por cierto, es una de las preocupaciones de mayor prioridad dentro de las instalaciones de Redmond.

Sin embargo, existen algunos escenarios en los que estas nuevas prestaciones para Windows XP a traves de este nuevo Service Pack, impactan sobre nuestras aplicaciones de hoy. Es tarea de la gente de soporte, plataforma y desarrollo conocer mas fondo lo nuevo que trae esta segunda version para poder tomar los correctivos necesarios.

Claro si en tu centro de labores siguen con W98. No te preocupes de nada :)

Les alcanzo algunos links que podrian serles de utilidad para este nuevo dolor de cabeza.

Vídeos, instrucciones paso a paso y mucho más
http://support.microsoft.com/default.aspx?scid=fh;[ln];xpsp2cnfghowto

Interesantes videos que nos permitiran apreciar como configurar nuestras PCs con Windows XP + SP2

Microsoft Windows XP SP2 Screenshots
http://www.microsoft.com/presspass/press/2004/aug04/0806WinXPSP2Images.asp

Darle un ojito a estos screen-shots para darse una idea de lo que nos toca vivir.

Windows XP Service Pack 2 - Overview Developers
http://www.tonygoodhew.com/downloads/DEV270WindowsXPSP2DeveloperOverview-tgoodhew.zip

Esta es una presentacion que nos muestra el punto de vista de los developers para con el SP2 del WXP

Source Code for Demo
http://www.tonygoodhew.com/downloads/democode.zip

Los codigos fuentes de las demos que se realizaron en esta presentacion.

Microsoft Windows XP Service Pack 2 Platform SDK RC2
http://www.microsoft.com/downloads/details.aspx?FamilyID=9be921b3-585e-47d9-bcc1-980879b69b34&displaylang=en

Para poder hacerle un build a los Projectos de C++.NET que vienen con el source code deben bajarse el Platform SDK para el Service Pack 2.

Y obviamente haberse descargado el Service PAck 2, pe.
http://www.microsoft.com/downloads/details.aspx?FamilyId=049C9DBE-3B8E-4F30-8245-9E368D3CDB5A&displaylang=en

Friday, August 13, 2004

3D Support in Longhorn 4074

Aplicaciones tan impactantes -como se prensentan en este screenshot- podran realizarse en la proxima version de Windows, codename Longhorn.



Este ejemplo fue presentado en el ultimo WinHEC.

Si tienen instalado el Longhorn Build 4074 y su respectivo SDK. Entonces podran apreciarlo en su propia PC, descargando el codigo fuente desde aqui.

http://www.microsoft.com/downloads/details.aspx?familyid=9C1724D1-B63E-4D7D-835A-FF94A1FAD311&displaylang=en

Tener en cuenta que un requesito, aun para este build, es contar con una tarjeta aceleradora 3D como la GeForce FX 5900, ATI 9800 XT o alguna superior. Para el 2006 estas tarjetas seran mucho mas comodas de lo que ahora estan. Y seran parte de la configuracion basica para una PC de oficina. Como tener un procesador de 4GHz, HDD de 200GB, Memoria de 1GB DDR-II, etc.

Vale recalcar, que es necesario contar con el SDK que le corresponde al Build 4074, para poder compilar los fuentes y obtener el resultado esperado. Los SDKs de los build anteriores de Longhorn como el 4051 liberado en el PDC de octubre del año pasado, no te permitiran compilar siquiera. Pues muchos namespaces han sido cambiados y algunas propiedas dejadas en desuso.

System.MSAvalon --> System.Windows

.Visible (True/False) --> .Visibility (Visibility enum)

En caso, tengas los .EXE de una aplicacion para Longhorn, ya no es necesario contar con el SDK. Solo ejecutarlo.

Longhorn 4074 - WinHEC Build

El nuevo build de Longhorn, el codename para el proximo release de Windows, fue liberado en el ultimo WinHEC realizado en Mayo de este año.

http://www.microsoft.com/whdc/winhec/default.mspx

Podras instalarlo, sobre una particion de tu HDD o sobre una instancia de tu VPC2004, por cierto en este ultimo escenario, se demora un tiempo excesivamente largo. Lo ideal seria realizarlo de la primera forma.

Al testear el build te percataras que un pequeño bug. Simplemente no podras crear carpetas a traves de la interfaz del Windows Explorer. He aqui la solucion.

/***
Click on Start, then Run.
Type regedit, click on OK.
Go to HKEY_CLASSES_ROOT/.Folder (not Folder but .Folder with a dot) Double-click on (Default)
Type "Folder" (without the quotes) in the value data zone, then click on OK.
Close regedit.
***/

Nada es perfecto :)

Thursday, August 12, 2004

Windows Longhorn Glass Look

Aero es un conjunto de recomendaciones, lineas guia y valores en la experiencia de usuario, que permitiran a tus aplicaciones obtener un mayor provecho de las nuevas bondades que tendremos sobre el nuevo release de Windows, codename "Longhorn".

http://w3future.com/2003/glass/glass.html

Este link solo intenta mostrar que tan agradables podrian ser las nuevas interfaces de usuario de nuestras futuras aplicaciones. Obviamente no usa Longhorn para esto, aun. Solo JavaScript, CSS, filtros IE, etc.

Muy bonito. ¿Verdad?

Monday, July 12, 2004

Consuming XML Web Services from Javascript

Si bien es cierto ASP.NET nos brinda un mayor control sobre los elementos que colocamos sobre nuestras paginas, gracias al soporte que se brinda a traves ViewState y el modelo de objetos que propone el Framework para este tipo de aplicaciones.

Sin embargo, algunas veces el constante PostBack, no es muy bienvenido -que digamos- para muchos usuarios y esto trae como consecuencia darles a nuestra aplicaciones un comportamiento diferente, para ciertas interfaces de usuario que ameritan una implementacion hibrida.

La posibilidad de realizar operaciones sobre el servidor web, sin necesidad de postear la pagina, mostrar informacion a la usuario en funcion a las acciones que realize este sobre la interfaz que le otorgamos, tambien es factible de realizar en el mundo de ASP.NET.

Algunos le dice Callbacks, tecnicamente hablando es darle a nuestros scripts por el lado del usuario, una forma de comunicarse con el web server para realizar operaciones y obtener resultados.

Para ello existen muchas formas: Web Services Behaviors, Remote Scripting, Artificios usando Frames ocultos, etc.

En esta oportunidad la intencion es mostrarles, la forma de conseguirlo usando XML Web Services y el XMLHTTP, un componente del Microsoft XML Core Services.


Archivo .ASPX

<%@ Page language="c#" Codebehind="ParentChild.aspx.cs" AutoEventWireup="false" Inherits="DemoWebAppCSharp.Services.ParentChild" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>ParentChild</title>
<script language="javascript" src="../Resource/FactoryDom.js"></script>
<script language="javascript">
var _server = 'http://localhost';
var _app = '/DemoWebAppCSharp';
var _asmx = '/Services/General.asmx'

// Este metodo esta enganchado al evento onload del body.
function Load()
{
ParentRecordSet();
}

// Este metodo esta enganchado al evento onchange del DropDownList
// _child, en su representacion HTML como SELECT.
function Show( object )
{
ChildRecordSet( object.value );
}

// Este metodo esta enganchado al evento onclick del Button _submit
// y permite salvar la informacion de los DropDownList.
function Capture()
{
document.all( '_parent_selected' ).value = document.all( '_parent' ).value;
document.all( '_child_selected' ).value = document.all( '_child' ).value;
}

// Transforma la informacion de los documentos XML a un vocabulario
// comun a traves de una transformacion XSLT
function ToOptions( xmlstring, xsltfile )
{
factory = new FactoryDom();

xmldom = factory.CreateXml( xmlstring );
xsltdom = factory.CreateXslt( xsltfile );

output = factory.Transform( xmldom, xsltdom );
if( output == null )
{
alert( 'Error al ejectuar Transform' );
return null;
}

return output;
}

// Obtiene la informacion de los itemes padres a traves del
// XML Web Services
function ParentRecordSet()
{
url = new UrlTarget( _server + _app + _asmx + '/ParentRecordSet' );

ws = new WebService( url );
xmlstring = ws.Execute();
xsltfile = '../Resource/ParentItem.xslt';

var output = ToOptions( xmlstring, xsltfile );

childNodes = output.documentElement.childNodes;

_parent = document.all( '_parent' );
AddChoose( _parent );

while( ( node = childNodes.nextNode() ) != null )
AddOption( _parent, node );
}

// Obtiene la informacion de los itemes hijos a traves del
// XML Web Services
function ChildRecordSet( Parent )
{
url = new UrlTarget( _server + _app + _asmx + '/ChildRecordSet' );
url.Append( 'Parent', Parent );

ws = new WebService( url );
xmlstring = ws.Execute();
xsltfile = '../Resource/ChildItem.xslt';

var output = ToOptions( xmlstring, xsltfile );

childNodes = output.documentElement.childNodes

_child = document.all( '_child' );
RemoveAll( _child );
AddChoose( _child );

while( ( node = childNodes.nextNode() ) != null )
AddOption( _child, node );
}

// Inserta una opcion por default en los DropDownList
function AddChoose( select )
{
var option = document.createElement( 'option' );
option.value = '-1';
option.text = '-- Elija una opcion --';

select.options.add( option );
}

// Insert una opcion a parti de los datos del node
function AddOption( select, node )
{
var option = document.createElement( 'option' );
option.value = node.selectSingleNode( '@value' ).text;
option.text = node.text;

select.options.add( option );
}

// Elimina todos los options de un DropDownList
// especialmente usado para el _child
function RemoveAll( select )
{
while( select.options.length > 0 )
select.options.remove( 0 );
}

// UrlTarget (Objecto)
// Permite realizar la construccion de una peticion POST hacia un destino
function UrlTarget( target )
{
this._empty = true;
this._target = target;
this._post = '';

this.Append = UrlTarget_Append;
}

// Metodo
function UrlTarget_Append( name, value )
{
if( this._empty )
this._empty = false;
else
this._post += '&';

this._post += name + '=' + value;
}

// WebService (Objeto)
// Encapsula el pedido a un XML Web Service a traves de peticiones POST
function WebService( Url )
{
this._url = Url;
this.Execute = WebService_Execute;
}

function WebService_Execute()
{
factory = new FactoryDom();
http = factory.CreateHttp();
http.Open( 'POST', this._url._target, false );
http.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' )
http.Send( this._url._post );

if( http.status != 200 )
{
message = '';
message += 'Hubo un error al ejecutar el WebService\n';
message += 'url: ' + this._url._target + '\n';
message += 'post: ' + this._url._post + '\n';
message += 'status: ' + http.status;

alert( message );
if( http.status == 500 )
_error.innerHTML = http.responseText;
return null
}

return http.responseText;
}
</script>
</HEAD>
<body onload="Load();">
<form id="ParentChild" method="post" runat="server">
<table>
<tr>
<td><asp:dropdownlist id="_parent" runat="server" Width="168px"></asp:dropdownlist></td>
</tr>
<tr>
<td><asp:dropdownlist id="_child" runat="server" Width="168px"></asp:dropdownlist></td>
</tr>
<tr>
<td id="_error"></td>
</tr>
</table>
<asp:Button id="_submit" runat="server" Text="Submit"></asp:Button>

<!-- Estos elementos no seran vistos en la interfaz del usuario -->
<div style="display: none">
<asp:TextBox id="_parent_selected" runat="server"></asp:TextBox>
<asp:TextBox id="_child_selected" runat="server"></asp:TextBox>
</div>
</form>
</body>
</HTML>

--- End File ---


Lo curioso en este archivo es el uso de dos objetos javascript, importantes para nuestro objetivo, pues ambos nos permiten encapsular cierta funcionalidad y no repetir codigo innecesariamente.

El primero de ellos es UrlTarget, este objeto permite definir cual sera nuestra destino para realizar una peticion y almacena la informacion a enviar a dicho destino, en el formato POST que todos conocemos.

El segundo es WebService, este objeto estable la forma de consumir un XML Web Service que existen en algun lugar de la red. La forma de consumir dicho servicio web es a traves del protocolo POST. Sin embargo, esto no excluye que no podamos hacer peticiones GET o SOAP. Para lo primero, GET, es mucho mas secillo, pues basta con pasar la informacion a traves del url pero, con las limitaciones conocidas de hacerlo por esa forma. Para lo segundo, SOAP, solo habra que construir el documento XML que se ajusta a la forma de solicitar informacion al servicio web y enviarlo como parte de la peticion.

Cuando testean sus XML Web Services a traves del VS.NET, veran los detalles en que esta permitido la forma en que podran consumirlo. Revisan dichas formas y listo.


Archivo .ASPX.CS

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace DemoWebAppCSharp.Services
{
/// <summary>
/// Descripción breve de Ubigeo.
/// </summary>
public class ParentChild : System.Web.UI.Page
{
protected System.Web.UI.WebControls.DropDownList _parent;
protected System.Web.UI.WebControls.Button _submit;
protected System.Web.UI.WebControls.TextBox _parent_selected;
protected System.Web.UI.WebControls.TextBox _child_selected;
protected System.Web.UI.WebControls.DropDownList _child;

private void Page_Load(object sender, System.EventArgs e)
{
if( ! this.IsPostBack )
{
// Enganchando metodos a los eventos DHTML correpondientes
this._parent.Attributes.Add( "onchange", "Show(this);" );
this._submit.Attributes.Add( "onclick", "Capture();" );
}
}

#region Código generado por el Diseñador de Web Forms
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: llamada requerida por el Diseñador de Web Forms ASP.NET.
//
InitializeComponent();
base.OnInit(e);
}

/// <summary>
/// Método necesario para admitir el Diseñador. No se puede modificar
/// el contenido del método con el editor de código.
/// </summary>
private void InitializeComponent()
{
this._submit.Click += new System.EventHandler(this._submit_Click);
this.Load += new System.EventHandler(this.Page_Load);

}
#endregion

private void _submit_Click(object sender, System.EventArgs e)
{
// Muestra la informacion que ha sido posteada
this.Response.Write( "Parent: " + this._parent_selected.Text + "<br/>Child: " + this._child_selected.Text );
}
}
}

--- End File ---


No hay mucho que explicar de este archivo. Solo, debido a que la informacion para cada DropDownList se ingresa por el lado del cliente a traves de las peticiones a los XML Web Services, en los siguientes postback no habra informacion trascendente en dichos controles. Por lo que se nos apoyamos en los TextBox para salvar la informacion del item seleccionado de los DropDownList por el usuario de manera que podamos enviarsela hacia el servidor por este medio.

La intencion del ejemplo, consite en presentar al usuario dos DropDownList dependiente uno del otro, para efectos practicos les llamaremos _parent y _child. Mas claro el agua.

Los itemes de _parent se solicitan al XML Web Services, al lanzarse el evento onload del documento HTML que presentamos al usuario. Al cual esta enganchado el metodo Load(), en el script por el lado del cliente.

Cada vez que el usuario seleccione un item de _parent, se ejecuta el metodo Show() por el lado del cliente aun, el cual solicitara los itemes de _child a otro WebMethod del XML Web Services, que estamos usando para este ejemplo.


Archivo .ASMX.CS

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;

using System.Xml.Serialization;

namespace DemoWebAppCSharp.Services
{
/// <summary>
/// Descripción breve de General.
/// </summary>
[WebService(Namespace="http://guydotnetxmlwebservices.com")]
public class General : System.Web.Services.WebService
{
public General()
{
//CODEGEN: llamada necesaria para el Diseñador de servicios Web ASP .NET
InitializeComponent();
}

#region Código generado por el Diseñador de componentes

//Requerido por el Diseñador de servicios Web
private IContainer components = null;

/// <summary>
/// Método necesario para admitir el Diseñador. No se puede modificar
/// el contenido del método con el editor de código.
/// </summary>
private void InitializeComponent()
{
}

/// <summary>
/// Limpiar los recursos que se estén utilizando.
/// </summary>
protected override void Dispose( bool disposing )
{
if(disposing && components != null)
{
components.Dispose();
}
base.Dispose(disposing);
}

#endregion

[WebMethod]
public ParentContainer ParentRecordSet()
{
ParentContainer container = new ParentContainer();
container.Fill();
return container;
}

[WebMethod]
public ChildContainer ChildRecordSet( Int32 Parent )
{
ChildContainer container = new ChildContainer();
container.Fill();
return container.FilterBy( Parent );
}
}

/// <summary>
/// Business Entity para salvar informacion del tipo Parent
/// </summary>
public class ParentItem
{
private Int32 _id;

public Int32 Id
{
get { return this._id; }
set { this._id = value; }
}

private String _name;

public String Name
{
get { return this._name; }
set { this._name = value; }
}

public ParentItem()
{}

public ParentItem( Int32 Id, String Name )
{
this._id = Id;
this._name = Name;
}
}

/// <summary>
/// Una colleccion del tipo ParentItem fuertemente tipeado
/// </summary>
public class ParentCollection : CollectionBase
{
public void Add( ParentItem Item )
{
this.List.Add(Item);
}

public ParentItem this[ Int32 index ]
{
get { return (ParentItem)List[ index ]; }
set { List[ index ] = value; }
}
}

/// <summary>
/// Un container para la coleccion ParentCollection
/// </summary>
[XmlRoot("ParentRoot")]
public class ParentContainer
{
private ParentCollection _collection;

[XmlArray("ParentCollection")]
public ParentCollection Collection
{
get { return this._collection; }
set { this._collection = value; }
}

public ParentContainer()
{
this._collection = new ParentCollection();
}

/// <summary>
/// Llena informacion inicial en la coleccion
/// </summary>
public void Fill()
{
this._collection.Add( new ParentItem( 1, "simplegeek" ) );
this._collection.Add( new ParentItem( 2, "spoutlet" ) );
this._collection.Add( new ParentItem( 3, "fabrik" ) );
}
}

/// <summary>
/// Business Entity para salvar informacion del tipo Child
/// </summary>
public class ChildItem
{
private Int32 _id;

public Int32 Id
{
get { return this._id; }
set { this._id = value; }
}

private Int32 _parent;

public Int32 Parent
{
get { return this._parent; }
set { this._parent = value; }
}

private String _name;

public String Name
{
get { return this._name; }
set { this._name = value; }
}

public ChildItem()
{
}

public ChildItem( Int32 Id, Int32 Parent, String Name )
{
this._id = Id;
this._parent = Parent;
this._name = Name;
}
}

/// <summary>
/// Una colleccion del tipo ChildItem fuertemente tipeado
/// </summary>
public class ChildCollection : CollectionBase
{
public void Add( ChildItem Item )
{
this.List.Add(Item);
}

public ChildItem this[ Int32 index ]
{
get { return (ChildItem)List[ index ]; }
set { List[ index ] = value; }
}
}

/// <summary>
/// Un container para la coleccion ChildCollection
/// </summary>
[XmlRoot("ChildRoot")]
public class ChildContainer
{
private ChildCollection _collection;

[XmlArray("ChildCollection")]
public ChildCollection Collection
{
get { return this._collection; }
set { this._collection = value; }
}

public ChildContainer()
{
this._collection = new ChildCollection();
}

/// <summary>
/// Llena informacion inicial a la coleccion
/// </summary>
public void Fill()
{
this._collection.Add( new ChildItem( 1, 1, "longhorn" ) );
this._collection.Add( new ChildItem( 2, 1, "avalon" ) );
this._collection.Add( new ChildItem( 3, 2, "soa" ) );
this._collection.Add( new ChildItem( 4, 2, "ws" ) );
this._collection.Add( new ChildItem( 5, 2, "indigo" ) );
this._collection.Add( new ChildItem( 6, 3, "nodes" ) );
this._collection.Add( new ChildItem( 7, 3, "network" ) );
this._collection.Add( new ChildItem( 8, 3, "agents" ) );
}

/// <summary>
/// Filtra la collection inicial a traves de un criterio
/// </summary>
/// <param name="Parent">El codigo del padre</param>
/// <returns></returns>
public ChildContainer FilterBy( Int32 Parent )
{
ChildContainer child = new ChildContainer();

foreach( ChildItem Item in this._collection )
{
if( Item.Parent == Parent )
child._collection.Add( Item );
}

return child;
}
}
}

--- End File ---


Para este archivo tenemos que explicar algunas cosas.

Primero, podran percatarse el uso del System.Xml.Serialization, este namespace permite -obviamente- serializar la informacion que tengamos de las clases que implementemos. De por si, cuando intentamos devolver informacion a traves de un XML Web Services, cometemos el un error involutario al hacerlo como un DataSet, esta estructura es de uso generico y para efectos de implemtacion de nuestra aplicaciones en general dentro del mundo .NET, su uso solo deberia estar sesgado -en lo posible- a la capa de acceso a datos.

En las demas capas, necesitamos de estructuras de datos, fuertemente tipeadas -AKA Strongly Typed- para brindar una mayor escalabilidad en el producto que entregamos.

En nuestro ejemplo, usamos el CollectionBase, para dar soporte a las coleciones que necesitmos implementar. Su uso es recomendado para encapsular conjuntos de datos para cada uno de los Business Entities que requerimos. Su comportamiento es relativamente similar en cada diferente coleccion, es decir: Add, Remove, this, etc.

Cuando se libere la proxima version de VS.NET (Codename: Whidbey), esta soportara la version 2.0 de C#, la que traera entre algunas cosas interesantes, el uso de templates <T>, dicha estructura nos permitira reducir muchas lineas de codigo, y seran usadas muy puntualmente para este tipo de requerimiento, las colecciones.

Volviendo a nuestro ejemplo en el codigo, se observa tambien, el uso de ciertos atributos como: XmlArray, XmlRoot, etc.

Estos atributos, se encuentran dentro del System.Xml.Serialization, y permiten customizar la forma en que se ha de serializar la estructura que vayamos a devolver a traves del XML Web Services.

Si intentasen, devolver un ArrayList a traves de un WebMethod, veran que el documento XML entregado a quien consuma dicho servicio web, tendra un vocabulario, similar a este.


<ArrayOfAnyType>
<anyType />
<anyType />
...
</ArrayListOfAnyType>


Obviamente, dicho vocabulario, no nos da mucha informacion -que digamos- debido a que se encuentra en terminos genericos.

El uso de Business Entities, Collections (a traves de CollectionBase) y Containers, permitiran entregar un documento XML mucho mas explicito en la informacion que contienen.


Archivo PARENT.XSLT

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ws="http://guydotnetxmlwebservices.com">

<xsl:template match="/">
<select>
<xsl:apply-templates select="/ws:ParentRoot/ws:ParentCollection/ws:ParentItem" />
</select>
</xsl:template>

<xsl:template match="ws:ParentItem">
<option>
<xsl:attribute name="value">
<xsl:value-of select="ws:Id" />
</xsl:attribute>

<xsl:value-of select="ws:Name" />
</option>
</xsl:template>
</xsl:stylesheet>

--- End File ---



Archivo Child.XSLT

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ws="http://guydotnetxmlwebservices.com">

<xsl:template match="/">
<select>
<xsl:apply-templates select="/ws:ChildRoot/ws:ChildCollection/ws:ChildItem" />
</select>
</xsl:template>

<xsl:template match="ws:ChildItem">
<option>
<xsl:attribute name="value">
<xsl:value-of select="ws:Id" />
</xsl:attribute>

<xsl:value-of select="ws:Name" />
</option>
</xsl:template>
</xsl:stylesheet>

--- End File ---


Estos dos ultimos archivos que aqui les alcanzo, permite tranformar la el documento XML que se obtiene a traves del XML Web Services, para consefuir un vocabulario que nos permita una mayor facilidad para construir los OPTIONS de cada DropDownList, por el lado del cliente.

Es importante recalcar, el uso de este namespaces dentro de los documentos XSLT:

xmlns:ws="http://guydotnetxmlwebservices.com"

Esta definicion, simplemente es necesaria, si la obviasemos, no podremos conseguir los resultados deseados al realizar las transformaciones.

Hay que entender que el documento XML viene firmado por un namespace, desde su origen, en la definicion misma del XML Web Services. Dicho namespace debe ser tomado encuenta, cada vez que usemos dicho documento, dentro de nuestra aplicacion.

Call a .NET Webservice using XMLHTTP, XMLDOM and VBScript
http://www.eggheadcafe.com/articles/20001006.asp

Web Methods Make it Easy to Publish Your App's Interface over the Internet
http://msdn.microsoft.com/msdnmag/issues/02/03/WebMethods/default.aspx

Tuesday, July 06, 2004

Soccer Refactory and Breakpoint

Y Grecia se alzo con el triunfo de la Eurocopa 2004. Un equipo que termino jugando fiel al estilo que propuso Otto Rehhagel, el dictador-democratico del futbol.

http://fifaworldcup.yahoo.com/06/es/040330/1/9tf.html

Tal vez ahora al final del torneo, uno haga memoria y revisando los encuentros que sostuvo el equipo Griego, se hara esta pregunta:

¿Sera que Franceses, Chekos, Portugueses y los demas jugaron tan apaticos sus respectivos encuentros, por que hubo un equipo al frente que los llevaba hacia ese ritmo? ¿Sera esa una consecuencia del plateamiento estrategico del nuevo rey griego?

Otto se llamó el primer monarca. Otto I de Baviera, entonces de 16 años, fue nombrado Rey de Grecia el 7 de mayo de 1832. Ahora, un nuevo Otto es elevado por los griegos al Olimpo: Otto Rehagel, el entrenador alemán del seleccionado griego, reciente campeon del torneo de naciones mas importante de Europa.

Pero regresemos a lo nuestro, a lo oriundo, a lo autoctono.

Hoy se inicia, en nuestra tierra, nuestro Peru, una nueva version de la Copa America.

No llegaron los Ronaldo, Ronaldinho, Roberto Carlos, y demas. Pero Brasil es Brasil. Y con KaKa seguramente aspiren a mas que jugar solo las finales de este torneo.

Sin embargo, por lo experimientado en los ultimos tiempos, en los que algunos equipos que no contaban con una historia futbolistica importante, empiezen a construirla con triunfos resonantes. Asi entonces, dificil dar un pronostico.

Quien podria negar que Venezuela, la que aun no ha conseguido algo trascendente -futbolisticamente hablando- por esta parte del mundo. Ahora lo logre.

Sino, preguntemosle a Grecia (EuroCopa 2004), Porto (Copa de Campeones 2004), Once Caldas (Copa Libertadores 2004) y Cienciano (Copa Sudamericana 2003)

http://www.go2peru.com/copa_america/copaamerica.htm

De todos modos, nos daremos un tiempo -alguno de estos dias- para dejar la garganta en la tribuna, alentando a los muchachos. Que por cierto, ni se lo merecen. Pues debieron ganarle a Venezuela, por las eliminatorias. Pero, que le vamos hacer.

Estamos convencidos, de que el Futbol -es solo Futbol- cuando se juega con el corazon.

Thursday, July 01, 2004

Dynamic WebForms in ASP.NET

Muchas veces, segun los requerimientos del cliente, se da la necesidad de poder construir -en ciertos casos- formularios webs y grillas de datos de manera dinamica, a partir de cierta logica para definir la estrucura que se ha de presentar a traves de la interfaz del usuario.

Les muestro un ejemplo que puede darles las primeras pautas de como poder llevar a cabo estas tareas.

Archivo .ASPX

<form id="SimpleDynamic" method="post" runat="server">
<asp:PlaceHolder id="_holder" runat="server"></asp:PlaceHolder><br/>
<asp:Button id="_submit" runat="server" Text="Submit"></asp:Button><br/>
<asp:Label id="_post" runat="server"></asp:Label><br/>
<asp:Label id="_message" runat="server"></asp:Label><br/>
</form>

--- End File ---


Notese el uso del control PlaceHolder, que permitira alojar en el diferentes tipos de controles en tiempo de ejecucion, para su posterior presentacion e interaccion.


Archivo .CS

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace DemoWebAppCSharp.Custom
{
/// <summary>
/// Descripción breve de Dynamic.
/// </summary>
public class SimpleDynamic : System.Web.UI.Page
{
protected System.Web.UI.WebControls.Button _submit;
protected System.Web.UI.WebControls.Label _message;
protected System.Web.UI.WebControls.Label _post;
protected System.Web.UI.WebControls.PlaceHolder _holder;

private void Page_Load(object sender, System.EventArgs e)
{
if( ! this.IsPostBack )
{
// Llenando el DropDownList de datos
this.FillList();
}
}

private void DefineForm()
{
TextBox Name = new TextBox();
Name.ID = "_name";

DropDownList List = new DropDownList();
List.ID = "_list";
List.AutoPostBack = true;

// Enganchando una funcionalidad al evento del DropDownList
List.SelectedIndexChanged += new EventHandler( this.List_SelectedIndexChanged );

// Colocando los controles en el PlaceHolder
this._holder.Controls.Add( Name );
this._holder.Controls.Add( List );
}

private void FillList()
{
// Solicitando el DropDownList al PlaceHolder
DropDownList List = (DropDownList)this._holder.FindControl( "_list" );

List.Items.Add( "-- Elija una opción --" );
List.Items.Add( "Simple Geek");
List.Items.Add( "Spoutlet" );
List.Items.Add( "Frabriq" );
}

// Funcion que se enganchara al evento correspondiente del DropDownList
private void List_SelectedIndexChanged( Object sender, EventArgs e )
{
DropDownList List = (DropDownList)sender;
this._post.Text = "Item selected: " + List.SelectedValue;
}

#region Código generado por el Diseñador de Web Forms
override protected void OnInit(EventArgs e)
{
InitializeComponent();
base.OnInit(e);
}

/// <summary>
/// Método necesario para admitir el Diseñador. No se puede modificar
/// el contenido del método con el editor de código.
/// </summary>
private void InitializeComponent()
{
this._submit.Click += new System.EventHandler(this.Submit_Click);
this.Load += new System.EventHandler(this.Page_Load);

this.DefineForm();
}
#endregion

// Posteando la informacion
private void Submit_Click(object sender, System.EventArgs e)
{
TextBox Name = (TextBox)this._holder.FindControl( "_name" );
DropDownList List = (DropDownList)this._holder.FindControl( "_list" );

this._message.Text = Name.Text + " : " + List.SelectedValue;
}
}
}

--- End File ---

Explicando, se contruira un TextBox y un DropDownList que esta seteado como AutoPostBack. De esta manera, cada vez que el usuario seleccione un item en la lista la pagina se posteara inmediatamente.

Revisando el metodo DefineForm. En este punto se muestra algo interesante, que es el enganche de un metodo hacia el evento de un control que se crea on-fly, es decir en tiempo de ejecucion.

Este metodo -el DefineForm- es llamado desde el InitializeComponent, que permite ejecutar operaciones sobre el metodo sobre-escrito OnInit. Que por cierto, es el lugar adecuado para poder colocar elementos dinamicos en la pagina.

Vale decir, que por el hecho de ser llamado desde dicho evento -el Init- la construccion dinamica de los elementos se realiza, por cada peticion de la pagina. Pues este evento siempre es solicitado por cada PostBack, al igual que el evento Load.

Es trabajo del modelo de objetos de ASP.NET, mantener el estado de los controles en la pagina por cada posterior PostBack.

Se remarca tambien, que los itemes adheridos al DropDownList, solo se realiza una sola vez, y esta operacion se lleva a cabo dentro del evento Load, validando el IsPostBack.

Se quiere dar a entender de esta manera, que la estructura del formulario es independiente de los datos que se plasmaran en dicha estructura. El evento Init es el lugar correcto para construir estructuras dinamicas y el Load para llenar datos en esas estructuras.

El metodo List_SelectedIndexChanged, solo hace un casting del objeto sender. Pues es justamente en esta variable que se encuentra una referencia al control que provoco el posting de la pagina, es decir el DropDownList.

Finalmente, el metodo Submit_Click, solicita al PlaceHolder, los controles que se adherieron al el, para presentar los valores que el usuario haya ingresado o seleccionado.

En conclusion, la intencion es poder construir cualquier estructura en el webform, a partir de una metadata, que brinde toda la informacion necesaria para la presentacion de dicha estructura y los datos que han de colocarse en el.

Les recomiendo descargar una interesante herramienta que he constuido, y que justamente parte de lo aqui mostrado es el 'core' de dicho producto.

http://groups.msn.com/mugperu/general.msnw?action=get_message&mview=1&ID_Message=11466

En dicho lugar, podran encontrar mayor informacion de como instalar el software y como trabajar con el.

Comparto tambien estos lugares de donde podran encontran mayor informacion sobre los eventos asociados a una pagina, el orden en el que son llamados y las actividades que se realizan en cada uno de ellos.

The ASP.NET Page Object Model
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/aspnet-pageobjectmodel.asp

The ASP.NET Page Life Cycle
http://www.15seconds.com/issue/020102.htm

Al igual que esto, la construccion de un DataGrid dinamico en funcion a las columnas y al contenido en cada DataGridItem, sean estos datos u otros controles, tambien es posible realizarlo, de esta forma.

Javier Luna
-- Software Architect and blogger too ;)
-- Movil: (51-1) 9-731-7187

"Indigo: Ports, Messages, Channels and more..."