Friday, May 09, 2008

[AJAX] Carga dinámica de páginas ASPX con AJAX Enabled WebService

por Ing. Juan Pablo Ibañez
http://ing.juanpablo.googlepages.com

Con la aparición de AJAX, ahora podemos cargar ciertas partes de una página ASPX sin tener que recargar toda la página. El problema surge cuando en una página queremos incluir diferentes funcionalidades que habitualmente están en páginas separadas. Si intentamos incluir todas las funcionalidades en nuestra página e ir cargándolas mediante AJAX, nuestra página comienza a hacerse demasiado grande para poder albergar todo el código que permite cambiar las partes y mostrar las distintas funcionalidades sin recargar toda la página. Hay aplicaciones grandes que requieren utilizar otro enfoque, como ser cargar páginas ASPX dentro de páginas ASPX pero sin hacer PostBack de la página contenedora. La técnica explicada en este artículo nos permite tener nuestra aplicación dividida en todas las páginas ASPX que necesitemos, y cargarlas dentro de una página contenedora usando AJAX, lo cual nos permite dividir mejor la funcionalidad, distintos equipos pueden trabajar independientemente en cada página ASPX, nuestra aplicaciones está mas desacoplada, prolija y demás beneficios.

En el siguiente ejemplo voy a mostrar como cargar diferentes ASPX dentro de otra página ASPX haciendo uso de AJAX WebServices. La imagen [Imagen1] que vemos a continuación es un esquema de lo que se pretende hacer.


[Imagen1]

La página contenedora tiene 1 div donde se insertará mediante AJAX el HTML de las páginas ASPX que se quieran cargar dinámicamente dentro de la página contenedora. Si nuestras ASPX que queremos cargar tiene elementos que hacen PostBack, debemos cargarlas dentro de un iframe, de lo contrario, por ejemplo, al presionar un Button en la página que se cargo dentro de la contenedora, se hará un PostBack que recargará también nuestra contenedora y la idea es que la contenedora nunca se recargue completamente.

Nuestra solución entonces deberá tener al menos los componentes que se muestran en la siguiente imagen [Imagen2].

Como vemos en esta imagen del Explorador de Soluciones, tenemos:
          1. Default.aspx, nuestra página contenedora.
          2. Default.js, código Javascript para hacer la llamada al WebService y cargar el contenido que este devuelve en nuestro div.
          3. Page1.aspx, una de las páginas que queremos cargar dentro de Default.aspx
          4. Page2.aspx, otra de las páginas que queremos cargar dentro de Default.aspx
          5. PageLoader.asmx, el WebService que devuelve el HTML que vamos a cargar dentro del DIV de Default.aspx
          6. web.config, configuración para hacer uso de las librerías de AJAX ASP.NET y configuración para usar AJAX ASP.NET WebServices.
          7. ajax-loader.gif, imágenes que mostramos mientras se cargan las páginas interiores.




[Image2]

La idea es que nuestra página Default.aspx tenga un DIV donde cargar el HTML de las páginas que queremos cargar, haga una llamada a un AJAX Enabled WebService y mientras se carga la página interior muestre un Loading...

La estructura de nuestra página Default.aspx sería algo así:

<body>

    <form id="form1" runat="server">

        <asp:ScriptManager ID="ScriptManager1" runat="server">

            <Scripts>

                <asp:ScriptReference Path="Default.js" />

            </Scripts>

            <Services>

                <asp:ServiceReference Path="PageLoader.asmx" />

            </Services>

        </asp:ScriptManager>

        <div align="center">

            <h2>Página Contenedora</h2>

            <input id="btnLoadPage1" type="button" value="Cargar Página 1" onclick="return btnLoadPage1_onclick()" />

            <input id="btnLoadPage2" type="button" value="Cargar Página 2" onclick="return btnLoadPage2_onclick()" />

            <br />

            <hr />

            <br />

            <div id="Loading" style="display: none">

                <table style="width: 200px; height: 200px">

                    <tr>

                        <td align="center" valign="middle">

                            <img id="Img1" src="Images/ajax-loader.gif" alt="loading..." />

                        </td>

                    </tr>

                </table>

            </div>

            <div id="Target">

            </div>

        </div>

    </form>

</body>


Tenemos un ScripManager configurado para tener acceso a nuestro código JavaScript:

<Scripts>

  <asp:ScriptReference Path="Default.js" />

</Scripts>

y también le configuramos el path a nuestro WebService para que pueda crear automáticamente el proxy que vamos a usar desde nuestro código JavaScript:
<Services>

    <asp:ServiceReference Path="PageLoader.asmx" />

</Services>


También tenemos 2 HTML Buttons, uno para llamar a Page1.aspx y otro para Page2.aspx y además 2 divs, uno para mostrar la imagen de Loading mientras se carga la página interior y otro para cargar el HTML que devuelve el WebService.


Al presionar cualquiera de los botones se hace una llamada al AJAX Enabled WebService como vemos en el siguiente código:


function btnLoadPage1_onclick()
{
    ret = PageLoader.LoadPage("Page1.aspx", OnComplete, OnTimeOut, OnError);
    document.getElementById('Loading').style.display = 'block';
    return(true);
}
function btnLoadPage2_onclick()
{
    ret = PageLoader.LoadPage("Page2.aspx", OnComplete, OnTimeOut, OnError);
    document.getElementById('Loading').style.display = 'block';
    return(true);
}

function OnComplete(args)
{
    document.getElementById('Target').innerHTML = args;
}

function OnTimeOut(args)
{
    alert("Service call timed out.");
}

function OnError(args)
{
    alert("Error calling service method.");
}


PageLoader es el proxy creado por el ScriptManager y LoadPage es el [WebMethod] expuesto por nuestro WebService. La llamada es asíncrona por lo que nos pide que especifiquemos la función que se va a llamar cuando se haya completado la petición, la función que se llama si se produce un time out y la función que se llama si se produce un error.

O sea que las funciones de los botones hacen 2 cosas: la petición y mostrar la imagen de Loading.

Una vez que el AJAX Enabled WebService devuelve el HTML, cargamos este dentro del div "Target" en la función OnComplete.

Lo que queda ahora es ocultar el Loading, esto lo hacemos desde la página interior, por ejemplo, Page1.aspx, en el evento onload en el body:

<body onload="parent.document.getElementById('Loading').style.display='none';" style="margin:0px;">

    <form id="form1" runat="server">

        <table style="width:200px;height:200px;">

            <tr>

                <td valign="middle" align="center" style="background-color:Blue;color:White">

                    Page1.aspx

                </td>

            </tr>

        </table>

    </form>

</body>


Solo quedaría ver el WebService, que lo que hace basicamente es devolver un HTML con un IFRAME con la página que le pasamos como parámetro, de esta forma si nuestra Page1.aspx o Page2.aspx hacen un PostBack, este no afecta a la página contenedora.


[WebService(Namespace = "http://tempuri.org/")]

[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

[System.Web.Script.Services.ScriptService]

public class PageLoader : WebService

{

    [WebMethod]

    public string LoadPage(string pageName)

    {

        return @"<iframe frameborder='0'

                         scrolling='no'

                         marginheight='0'

                         marginwidth='0'

                         height='200px'

                         width='200px' id='frame' src='" + pageName + "' runat='server'></iframe>";

    }

}


Es importante destacar la siguiente línea que es la que permite que el hacer AJAX Enabled al WebService:


[System.Web.Script.Services.ScriptService]


El siguiente gif animado muestra el ejemplo funcionando:






Tuesday, May 06, 2008

[Células.NET] Células.Net en Córdoba

En esta oportunidad quiero comentarles sobre Células.Net, un programa
académico de Microsoft para estudiantes que estén interesados
en aprender mas sobre tecnologías Microsoft. Córdoba se está
convirtiendo en un gran foco de grupos de estudios y tengo el agrado de comentarles
que estoy formando parte como profesor guía de 3 de estos grupos. Quiero
darles la bienvenida a estas personas que se han puesto por objetivo aprender
mas sobre tecnologías Microsoft formando parte de esta comunidad. Les
presento las células:


Nombre Clave: Developnet
Blog: http://developmentnet.blogspot.com

Nombre Clave: Hibridos
Blog: http://hibrides.blogspot.com



Nombre Clave: Antares
Blog: http://antarescell.blogspot.com

En este proyecto estoy junto
a Matías Iácono quien es profesor guía de otro conjunto
de células. Para el manejo de todas las células que tenemos entre
los 2 hemos creado una lista de distribución, usando los grupos de Google.
Los interesados pueden ver los avances de estas células en: http://groups.google.com.ar/group/celulasnetcordoba

Saludos a todos.


Wednesday, March 26, 2008

[Conferencias] 1ras Jornadas de Actualización Informática en el ISIPE

Hola, les comento que voy a participar de las primeras jornadas de actualización informática en el ISIPE. Voy a estar disertando sobre como mejora la productividad ASP.NET 2.0.

Les dejo el anuncio que mando la gente del ISIPE.


1º JORNADAS DE ACTUALIZACIÓN INFORMÁTICA



Un espacio creado por I.S.I.P.E. - Instituto de Servicios Informáticos para Empresas de la Universidad Empresarial Siglo 21-, para que puedas actualizarte en el campo de las Tecnologías Informáticas -IT-.
Vas a tener la oportunidad de escuchar a figuras destacadas del ámbito nacional e internacional, y conocer las distintas herramientas de IT existentes en el mercado, su aplicación, ventajas y desventajas para generar beneficios competitivos en un mercado que así lo exige.

27 y 28 de marzo / 2008 - Córdoba



Jueves 27

16.00 hs. ''Nuevas tecnologías en el mundo Java''

Objetivos: Introducir a los presentes en las nuevas tecnologías para interfaces gráficas JavaFX. Mostrar ambientes de desarrollo para tecnología J2ME y la integración de Java con lenguajes scripting modernos Ruby.

Disertante: Ezequiel Singer -Trabaja en la división de educación de Sun Microsystems. Integra desde la Argentina a un equipo de más de 500 estudiantes de las principales universidades del mundo en un proyecto que tiene como base acercar a la tecnología SUN a los ámbitos académicos. Su misión es interactuar con profesores, alumnos y directivos en la formación de grupos de usuarios, foros, en la confección de eventos, charlas, seminarios y talleres y en el continuo apoyo a las currículas, manteniendo actualizados los ámbitos académicos con la última tecnología SUN-.

18:30 HS. Break

19.00 hs. ''Herramientas para mejorar la productividad en desarrollo Web con .NET''

Objetivos: - Dar a conocer las diferencias y nuevas mejoras que se han introducido en el mercado a partir del Visual Studio 2005, haciendo hincapié en el desarrollo de aplicaciones web
.

- Mostrar las nuevas herramientas de ASP.NET 2.0 que ayudan a mejorar notablemente la productividad, acortando los tiempos y estandarizando los métodos de desarrollo.
- Mostrar las principales características de Silverlight, su implementación en el desarrollo de sitios web e interacción con lenguajes de servidor.

Disertante: Mgt. Gustavo Ferrero -Ingeniero en Sistemas (UCC).Master en Ingeniería de Software (ITBA). Tiene experiencia en integración de tecnología (J2EE y .NET) y gran capacidad de investigación. Posee sólidos conocimientos técnicos en diferentes lenguajes de programación (Visual Basic, Visual C, DELPHI) y ha liderado grandes proyectos tecnológicos. Algunas de sus publicaciones: "Ciclo de vida en Espiral Win-Win", "Métricas de Software", "Algoritmos de Minería de Datos"-
Ing. Juan Pablo Ibáñez -
Ingeniero en Sistemas. Posee experiencia en el desarrollo de aplicaciones mobiles y aplicaciones para Internet en proyectos de gran envergadura para empresas nacionales y extranjeras. Sus publicaciones: "Tecnologías AJAX", en Netdeveloper y Ineta Latam - International .NET Association-
Ing. Matías Saúl Iacono Dagatti -Licenciado en Ingeniería de Sistemas. Aprobado con Honores, en la certificación en ASP.net 2.0 (Whidbey), otorgado por Microsoft MVP Academy. Certificado en C# nivel 100 otorgado por Microsoft MVP Academy-



Viernes 28

16:00 hs. "Gestión por Procesos" Caso de éxito: CONAGUA Gobierno de México (Premiado con el Premio Anual de Transparencia México 2005).

Objetivos: Lograr que los asistentes aprendan cómo las organizaciones hacen de la administración de la información el aspecto clave de su gestión. Exponer porque un modelo de gestión por procesos de negocio reduce costos, incrementa la eficiencia, mejora la calidad y acorta los tiempos de producción y respuesta

Disertantes: Lic. Federico Silva (Marketing Manager - PECTRA Technology, Inc.),
AS.
Alfredo Cisterna (Product Manager - PECTRA Technology, Inc.), Ing. Isidro Gaytán Arvizu (Director del Sistema CONAGUA.) Lic. Juan Carlos Garcés del Ángel (Coordinador Operativo del Sistema de Gestión Hidroagrícola, CONAGUA)

18.30 hs. Break

19:00 hs. ''Testing de Software, adaptación y como aplicar técnicas efectivas ''. Caso de Éxito: Nimbuzz (Holanda)

Objetivos: Lograr ser capaces de Identificar las técnicas de testing adecuadas y los modelos a aplicar. Generar independencia de Vendors y reportar Errores en empresas internacionales.

Disertantes: Sergio Emanuel Cusmai -Director de QAustral S.A. Empresa especializada en Calidad de Software y Negocios. Gerente General de Nimbuzz Argentina S.A. Tester Certificado por la British Computer Society.-
Menno Johan Bieringa
. Holanda -Web Manager de Nimbuzz Argentina S.A. Desarrollador Web Senior-

Arancel: $24 por jornada.


INSCRIPCIONES
Ituzaingó 484 - 5º piso
de 17 a 20 hs.

Tuesday, March 25, 2008

[NET2.0] Usando WMI (Windows Management Instrumentation) technology

por Ing. Juan Pablo Ibañez
http://ing.juanpablo.googlepages.com

Esta tecnología nos permite recuperar toda la información que deseemos de cualquier sistema operativo Windows ya sea local o remoto. Información como cuales son los adaptadores de red, la memoria RAM, los discos fijos y removibles, la CPU, etc. de nuestra PC puede ser obtenida programáticamente mediante WMI.

La definición de WMI es:

Instrumental de administración de Windows (WMI) es un componente del sistema operativo Windows que permite obtener acceso mediante programación a información de administración en un entorno empresarial. WMI en .NET Framework se basa en la tecnología WMI original y permite el mismo desarrollo de aplicaciones y proveedores, además de las ventajas que ofrece la programación en .NET Framework.


WMI en .NET puede ser utilizada mediante una serie de objetos lo cual nos facilita mucho su uso. Estos objetos se encuentras agrupados dentro del namespace System.Management. WMI utiliza una sintaxis muy parecedida a la de SQL para armar "queries" sobre los componentes de los cuales queremos obtener información.

Más información teórica sobre WMI puede ser encontrada en http://msdn2.microsoft.com/es-es/library/ms257353(VS.80).aspx. Microsoft nos proporciona también un software llamado WMI Code Creator v1.0 para generar código (VBScript, C# y VB.NET) que use WMI.

Nada mejor para entender WMI que llevarlo a la práctica. Supongamos que quisieramos obtener información sobre los discos fijos que tenemos en nuestra PC.

Primero debemos definir un objeto ManagementScope que representa un ámbito (espacio de nombres) para las operaciones de administración.


ManagementScope
scope = new ManagementScope(ManagementPath.DefaultPath);

Luego debemos armar la query que nos devuelva por ejemplo el nombre y el tamaño de los discos fijos usando un objecto del tipo ObjectQuery que representa una consulta de administración que devuelve instancias o clases.

ObjectQuery query = new ObjectQuery("SELECT Size, Name FROM Win32_LogicalDisk where DriveType=3");


Por último crear un instancia de la clase ManagementObjectSearcher que recupera una colección de objetos de administración basándose en una consulta especificada. Esta clase es uno de los puntos de entrada más utilizados para recuperar información de administración. Se puede utilizar, por ejemplo, para enumerar todas las unidades de disco, adaptadores de red, procesos y muchos otros objetos de administración del sistema, o para saber qué conexiones de red están activas, qué servicios están detenidos, etc.

El método Get de este objeto nos devuelve el resultado de la consulta en una colección de objetos del tipo ManagementObjectCollection.

ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope,query);
ManagementObjectCollection drives = searcher.Get();

foreach (ManagementBaseObject drive in drives)
{
Console.WriteLine("Drive Name: " + drive["Name"]);
Console.WriteLine("Drive Size: " + drive["Size"]);
}

Console.ReadLine();

Otro lindo ejemplo es como recuperar cuales los los adaptadores de red conectados a nuestra PC.

class
Program
{

public const string IP_Enabled = "IPEnabled";

public const string IP_Address = "IPAddress";

public const string IP_Subnet = "IPSubnet";

public const string DNS_Hostname = "DNSHostName";

public const string DNS_Domain = "DNSDomain";

static void Main(string[] args)
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration");
ManagementObjectCollection networks = searcher.Get();

foreach (ManagementBaseObject network in networks)
{
Console.WriteLine("-----------------------------------------------------");
Console.WriteLine("Description: " + network["Description"]);
Console.WriteLine("MacAddress: " + network["MacAddress"]);

if (Convert.ToBoolean(network[IP_Enabled]))
{
string[] ips = (string[])network[IP_Address];
string[] subnets = (string[]) network[IP_Subnet];

Console.WriteLine("DNS Hostname: " + network[DNS_Hostname]);
Console.WriteLine("DNS Domain: " + network[DNS_Domain]);

foreach (string ip in ips)
Console.WriteLine("IP: " + ip);
foreach (string subnet in subnets)
Console.WriteLine("Subnet: " + subnet);
}
}
Console.ReadLine();
}

}

Tuesday, March 04, 2008

[Conferencias] LINQ to SQL

por Ing. Juan Pablo Ibañez
http://ing.juanpablo.googlepages.com

Estoy organizando una conferencia sobre LINQ to SQL en el Colegio de Ingenieros Especialistas de Córdoba, ya que desde el año pasado tengo el agrado de formar parte la Comisión de Informática. El disertante es el Ing. Matías Iácono (MVP).

Les dejo el flyer que mandamos con la gente del CIEC.
Saludos.

Córdoba, 04 de Marzo de 2008

Estimado/a

El Colegio de Ingenieros Especialistas de Córdoba informa la realización de la:


"CONFERENCIA: LINQ TO SQL"

Esta contará con la disertación del profesional
Ing. Matías Saúl Iacono Dagatti

Licenciado en Ingeniería de Sistemas
Aprobado con Honores, en la certificación en ASP.net 2.0 (Whidbey), otorgado por Microsoft MVP Academy. Certificado en C# nivel 100 otorgado por Microsoft MVP Academy.


Miércoles 19 de Marzo de 2008
18.30 a 21.30

(Coffee Break de 15 minutos)


PROGRAMA
  1. Conceptos generales de Linq
  2. Entidades de Linq
  3. Modelado de datos usando Linq
  4. Modelado de consultas usando Linq
En esta conferencia se verán conceptos generales de Linq para ayudar a la comprensión de este nuevo modelo de programación. Finalmente, se hará especial hincapié en el uso de Linq para el acceso a base de datos.


"NOS HONRARA CONTAR CON SU GRATA PRESENCIA"

Lugar: Auditorio Ciec Jujuy 441 Centro
Coordina el evento: Ing. Juan Pablo Ibañez

SIN CARGO

Se requiere pre-inscripción por capacidad limitada



INFORMES E INSCRIPCION
Colegio de Ingenieros Especialistas de Córdoba - Jujuy 441- 5000 - Córdoba- Tels: 0351-4220046 - 4220081 - 4236074
Cel: 155-553410
Email: ciec@ciec.com.ar


Colegio de Ingenieros Especialistas de Córdoba - Jujuy 441 - 5000 - Córdoba - Tels: (0351) 4220081/46 - Email: ciec@ciec.com.ar - Home Page: www.ciec.com.ar

Sunday, February 24, 2008

[ASP.NET2.0] Extendiendo ASP.NET Server Controls

por Ing. Juan Pablo Ibañez
http://ing.juanpablo.googlepages.com

Muchas veces, al comienzo de nuestra carrera profesional, en la desesperación por programar, nos pasa que nos olvidamos de pensar un poco mas allá de lo que tenemos que hacer justo en este momento y terminamos haciendo las cosas mas de una vez, en otras palabras nos olvidamos de pensar en "reusar". Código duplicado, funcionalidad aquí y allá, nos cuenta mas tiempo y esfuerzo, por lo cual, cuando identificamos una funcionalidad que consideramos que puede ser reusada, lo que debemos hacer es crear un componente que pueda ser usado mas de una vez, documentarlo y agregarlo a nuestra librería de componente.

Para lograr esto, muchas veces lo que debemos hacer extender la funcionalidad de un control de servidor ASP.NET. Por ejemplo, tenemos el control Calendar, pero nos gustaría que cuando pasamos el mouse sobre un día este se pinte de otro color para destacarlo. Esta funcionalidad no la provee el control Calendar clásico de ASP.NET. Podríamos programar la funcionalidad en la misma página donde tenemos agregado el control o podríamos crear un control nuevo con toda la funcionalidad y reusarlo.

Para crear este nuevo control debemos extender la funcionalidad del control Calendar usando el modelo de herencia de ASP.NET.

Lo primero que tenemos que hacer es abrir VisualStudio y crear un proyecto del tipo ASP.NET ServerControl.

Lo que debemos hacer para resolver el problema es crear una clase, la cual llamaremos HoverCalendar, que herede de Calendar, así podemos acceder a toda la funcionalidad de Calendar y agregarle el comportamiento especial que queremos.
El atributo ToolboxData especifica la etiqueta predeterminada generada para un control personalizado cuando éste se arrastra desde un cuadro de herramientas en una herramienta como Microsoft Visual Studio.

Luego dos propiedades, una para el BackColor, la cual llamaremos DayHoverStyleBackgroundColor y otra para el ForeColor, la cual llamaremos DayHoverStyleForeColor, del día sobre4 él cual el mouse esta parado.
Tenemos que tener en cuenta que el valor de estas dos propiedades no sobrevive entre postbacks por lo cual tenemos que guardar estos valores en el ViewState.


El atributo Category especifica el nombre de la categoría en la que se agrupa la propiedad o el evento cuando se muestra en un control de PropertyGrid establecido en el modo por categorías.

El atributo DefaultValue especifica el valor predeterminado de una propiedad.

Ahora lo que debemos hacer es registrar código Javascript para que sea ejecutado cuando se produzcan los eventos onmouseover y onmouseout de cada una de las celdas del calendario.

Cuando el mouse esta sobre un día del calendario el día se debe renderizar con los colores seleccionados en las propiedades DayHoverStyleBackgroundColor y DayHoverStyleForeColor y cuando el mouse sale del día en que estaba se deben volver a renderizar con los coroles que tenia anteriormente.

Para hacer esto nuestro Javascript guarda en 2 variables los colores que tiene el día, renderiza los nuevos y al salir vuelve a cargar los colores guardados en las variables.

Este es el Javacript que necesitamos:

Esta es una función auxiliar usada en la generación del Javascript:
Ahora, para indicarle al control que debe registrar el Javascript en el cliente debemos hacer uso de la clase ClientScriptManager y el momento indicado para hacerlo es cuando se dispara el evento PreRender, por lo cual debemos sobreescribir el metodo OnPreRender indicando que debe registrar el código Javascript ya que este evento es la última oportunidad antes de que se guarde el estado del control en el ViewState y el HTML se generado. O sea que si queremos que el control envíe Javascript al cliente la última oportunidad es aquí.
Bien lo último que queda por hacer es indicar que los eventos onmouseover y onmouseout de las celdas que representan los días del calendario llamen a las funciones que declaramos en nuestro archivo Javascript. Para realizar esta tarea debemos sobreescribir el modo en que se renderizan las celdas para agregarle la funcionalidad nueva, sobreescribiendo el método OnDayRender.



Bueno, con esto tendríamos nuestro control listo.

Monday, December 10, 2007

[NET2.0] Crear objetos que implementen una Interface seleccionando la implementación desde un Archivo de Configuración usando Reflection

Crear objetos dinámicamente dependiendo de un archivo de configuración es una práctica fundamental para crear aplicaciones altamente cohesivas y débilmente acopladas. Usando esta técnica podemos cambiar módulos de una aplicación sin tener que recompilar la misma, sólo cambiamos el valor de una variable en un archivo de configuración y la aplicación comenzará a usar el nuevo módulo definido.
Un caso muy común donde sucede esto es en los frameworks de acceso a datos. Generalmente con estos frameworks nos conectamos a diferentes fuentes de datos y sería bueno que cambiar nuestra fuente de datos sea transparente para el resto de nuestra aplicación. Esto se puede lograr mediante el uso de interfaces y de técnicas como cargar assemblies dinámicamente seleccionándolas desde archivos de configuración. A fines de este artículo no vamos a demostrar con un framework de acceso a datos sino con un conjunto simple de clases e interfaces. La idea es crear un interface, un contrato que deben respetar las clases que lo implementen. Luego crear dos clases que implementen la interface de manera diferente, en assemblies diferentes, y por último creamos una aplicación de prueba que tendrá un archivo de configuración de donde le indicaremos cual es la interface que se debe cargar. Comencemos con nuestro ejemplo. Definamos una interface. Nuestra interface tiene un método T GetMessage(T) que recibe un parámetro de un tipo T y devuelve un tipo T. No es necesario definir una interface genérica como esta, en este ejemplo se realizó así a fin de probar solamente, pero podría haberse hecho de igual manera con un tipo string.



Ahora definamos las dos clases en dos assemblies diferentes que implementen la interface de dos maneras distintas. A los fines de este ejemplo haremos algo simple, cada clase retornará el parámetro de entrada todo en mayúsculas o todo en minúsculas junto con un mensaje.

Implementación 1:
Implementación 2:
Tengamos en cuenta que para poder implementar estar interfaces tenemos que haber hecho previamente una referencia a la assembly (IMessageX) que tiene la interface.

Ahora debemos crear un programa que use esta estas interfaces dependiendo del archivo de configuración.
El programa tiene que tener un archivo de configuración, por ejemplo:

Como vemos en el archivo de configuración, para crear una instancia de una clase por Reflection necesitamos 2 cosas: el path a el assembly, que lo obtenemos del valor de configuración AssemblyPath1 o AssemblyPath2 y el nombre completo de la clase que queremos instanciar incluyendo el namespace de la misma, que lo obtenemos del valor de configuración ClassName1 o ClassName2.

Para leer un valor desde de un archivo de configuración usamos la clase ConfigurationManager del namespace System.Configuration y usamos el método estático Get("key") de la clase AppSettings que es expuesta por el ConfigurationManager mediante la propiedad AppSettings.

Una vez que obtuvimos el path a la assembly, podemos levantar la assembly mediante Reflection.
Para realizar esto creamos una referencia del tipo Assembly y usamos el método estático LoadFile("path") de la clase Assembly que pertenece al namespace System.Reflection.

Ahora debemos crear una instancia de la clase que implementa la interface.
Para lo cual necesitamos el nombre completo de la clase que obtenemos del archivo de configuración, luego
creamos una referencia del tipo de la interface, en nuestro caso, IMessageX y por últimos usando la assembly cargada previamente creamos la instancia del objeto con el método CreateInstance("classname") del objeto Assembly que ya levantamos.
Recordemos que este este método nos devuelve un object y debemos castearlo al tipo de nuestra interface.


Por último, para probar llamamos al método GetMessageX con el parámetro de entrada y vemos si se realizó correctamente lo que esperábamos.


Como vemos el resultado es el esperado, tenemos dos funcionalidades diferente para la misma interface cargadas desde 2 assemblies distintas dinámicamente seleccionadas desde un archivo de configuración.

Si vemos las referencias de nuestro programa veremos que solo hay referencias a la assembly que tiene la interface (IMessageX) y no hay ninguna referencia a las implementaciones (MessageXX y MessageXY).


El código de ejemplo, acá.

Thursday, November 29, 2007

[AJAX] Identificando Full PostBack y AJAX AsyncPostBack

Para aquellas personas que hayan usado AJAX ASP.NET un poco mas en profundidad que sólo arrastrar un UpdatePanel este artículo les va a resultar muy útil.
Un UpdatePanel nos permite refrescar ciertas partes de la página, en vez refrescar la página completa usando un Full PostBack.
Ahora depende como hayamos programado nuestra aplicación estaremos usándo AJAX de una manera más performante o no.
Cuando se produce un evento dentro de un UpdatePanel o un trigger que activa un UpdatePanel, se ejecuta el ciclo de vida completo de una página ASP.NET pero no se refresca toda la página sino que el objeto PageRequestManager (client-side) se encarga de recibir el nuevo HTML y reemplazar el viejo HTML.
Ejecutar el ciclo de vida completo de la página significa que se ejecutan todos los eventos del ciclo de vida de la pagina como ser Load,PreInit, Init, etc, etc.

Es en el evento Load donde se puede preguntar si es un Full Postback o un AJAX AsyncPostBack y definir distintas funcionalidades dependiendo de que sea uno u otro. Esto es muy importante tenerlo en cuenta ya que muchos desarrolladores solo preguntan si es un Full PostBack o si es la primera vez que se ejecuta la página y pierden la posibilidad de optimizar sus aplicaciones corriendo las funciones que necesitan para cada caso.
Ahora, con es uso de AJAX, tenemos 3 alternativas: que sea la primera vez que se ejecuta la página, que sea un Full PostBack o que sea un AJAXAsyncPostBack.

Veremos ahora como hacer esto en el código:



Como se ve en el ejemplo se consulta al objeto ScriptManager para saber si es un AsyncPostBack y se consulta al objeto Page para saber si es un Full PostBack.

Wednesday, November 14, 2007

[MISC] Cómo hacer para que te llaman a una entrevista?

He quedado impactado por un training que recibí en mi trabajo sobre el tema de currículum y su importancia en el proceso de ser llamado a una entrevista. Por lo cual quisiera compartir con uds los lineamientos que nos bajo el Ing. Fabio Bustos.
Antes que nada, la charla que recibimos tuvo una gran dinámica lo cual influyo positivamente en todos nosotros.

Pero volviendo al tema, cuál es el fin que tiene un currículum? Muchos dirán es nuestra carta de presentación, un folleto de venta, etc. todo esto es válido, pero el fin principal es que nos llamen a una entrevista!!
Pero para que esto suceda el currículum debe llegar a la persona correcta, y en ese camino para llegar a la persona correcta parara por, por ejemplo, recursos humanos, recruiting, etc, etc, etc, personas que quizá no entiendan lo que ponemos en el currículum, por ejemplo, la búsqueda laboral dice: "Conocimiento de Programación Orienta a Objetos" y nosotros ponemos en nuestro CV, "Conocimiento de POO", para un ingeniero en sistemas no debería haber problema en darse cuenta lo que quiere decir pero para otro persona, aunque sea muy capaz en su área, por cierto, pero que no conoce la terminología, va a descartar nuestro CV por el hecho de que nosotros escribimos el CV orientado a una persona súper técnica y no pensamos en que debe pasar otras personas que quizá no son ingenieras en sistemas, así que nuestro currículum debe ser capaz de atravesar todo ellos.
Supongamos que a esa persona, que no es el destinatario final de nuestro currículum, le llega el currículum por primera vez y también le llegan otros 300 curriculum, cuando la persona revisa los currículum descarta todos aquellos que en la primera media página no encuentra lo que está buscando, así de simple. Esto significa que nuestro currículum de 30 páginas, que nos costo horas llenarlo y mantenerlo actualizado, la primera media página tiene que ser la llave que abra las puertas hasta la persona que realmente va a leer las 30 páginas de nuestro currículum y va a entender lo que pusimos ahí, o sea, nuestro futuro jefe posiblemente.

Por eso una de las cosas que primero debemos hacer es identificar el target de nuestro currículum, y adaptar nuestro el mismo para cada una de las ocasiones. Generalmente tenemos un currículum standart y cada vez que buscamos trabajo mandamos nuestro currículum como si fuera un SPAM. No, No, grave error, debemos primero adaptar nuestro currículum a la búsqueda en que estamos interesados en ser encontrados. Con "adaptar" no quiero decir mentir ni engordar nuestro currículum porque al momento que se den cuenta de nuestra mentira, automáticamente quedaremos marcados para todo el viaje, recordemos que una persona que tiene una buena impresión se lo cuenta a otra pero una persona que tiene mala impresión se lo cuenta a otras siete personas, así que de mentir por favor nada.

Teniendo esto en claro, pasamos a la estructura de nuestro CV. Como párrafo inicial podríamos poner una breve descripción de que conocimientos tenemos que sea matchean con el puesto para el cual nos postulamos, con lo cual le informamos a la persona que lee que tenemos capacidades que sirvan para el puesto que ellos buscan. Con esto logramos que lean las siguientes lineas y evitamos que nuestro CV termine en el tacho de basura.

Luego podríamos poner algunos Strenghs, aquí debemos ser cuidadosos, deberíamos utilizar verbos y sustantivos, nunca adjetivos, dejemos que los adjetivos los deberían poner otros y no nosotros mismos. Por ejemplo poner cosas como Commitment, no sirve de nada, es obvio que van a querer contratar una persona con commitment. O poner Initiative, es obvio que van a querer contratar una persona con iniciativa, no van a contratar una persona que le tengan que andar arreando para hacer algo. Poner Integrity, es obvio que no van a contratar un ladrón. O Quick Learning, es obvio que no van a contratar una persona que le lleve tres años para aprender algo. Un bueno ejemplo de que poner seria, problem solving skills, o algo así.

Todo CV tendrá experiencia laboral, así como logros académicos y demás. Lo importante de todo esto es ordenarlos por fecha, lo mas actual es lo mas relevante, generalmente a la gente le importa poco lo que hicimos hace 10 años atrás, posiblemente ya no hayamos olvidado, por lo cual lo mas importante es lo mas actual. También cuenta este mismo concepto si queremos agregar una breve descripción, a lo mas nuevo podemos hacerle una descripción mas detallada y a lo mas antiguo una descripción mas breve.

Como conclusión podríamos decir que antes de enviar un CV, deberíamos orientarlo al mercado que apunta, poner solo lo relevante, ordenarlo cronológicamente de lo mas nuevo a lo mas viejo, explicar mas detalladamente lo mas nuevo, identificar las posibles personas que van a leer nuestro CV, identificar claramente una dirección y teléfono de contacto en la primera página, destacar cuales son las características que tenemos que coinciden con la búsqueda que se esta realizando pero sin mentir, engordar, timar.

Créditos al Ing. Fabio Bustos.

Saludos.