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.

Wednesday, October 24, 2007

[AJAX]Tecnología AJAX

Luego del boom de los .com, la web entró en una meseta hasta el año 2005 donde renació con lo que hoy es conocido como Web 2.0. Este resurgimiento ha sido fomentado, entre otras cosas, por cambio en el paradigma en la forma en que se publican los datos, la mejora en las telecomunicaciones y las nuevas tecnologías como AJAX que fomentaron a que el nuevo modelo de web sea mas interactivo y le permita al usuario tener una experiencia mas rica y mas interactiva con los contenidos a los cuales está accediendo.

Hoy ya no son los editores de contenidos quienes publican la información y el resto de la comunidad es un mero espectador, sino que es la comunidad misma la que crea, participa y juzga el contenido de los portales. Pero estas nuevas activadas, que ahora realiza la comunidad, deben ir acompañadas por mejoras tecnológicas que permitan, a gente que no es experta en sistemas informáticos, realizarlas de una manera sencilla, simple, dinámica y productiva.

Las tecnologías AJAX están presentes en las interfaces gráficas de GMAIL, MySpace, Knowii, Meebo, entre otras.

AJAX es el acrónimo de Asynchronous Javascript and XML y es una técnica de programación donde se combinan y se explotan tecnologías ya existentes como JavaScript y XML, para lograr enviar y recibir mensajes en segundo plano sin que el usuario note que la pagina web que navegando esta procesando algunas tareas, es decir sin que se realicen postbacks. El uso adecuado de AJAX trae como consecuencia un aumento considerable de la usabilidad, productividad, velocidad y tiempo de respuesta de un sitio web.

AJAX ASP.NET Framework

Uno de los frameworks de AJAX mas usados es AJAX ASP.NET, que será el usado en este artículo a modo de ejemplificación para mostrar algunas de las tareas que podemos realizar con esta tecnología.

Este framework permite implementar AJAX en sitios ASP.NET mediante el uso de controles de servidor. Siguiendo con la forma de trabajo de ASP.NET, los desarrolladores programan sus aplicaciones de la manera convencional y cuando desean usar una funcionalidad AJAX solo debe agregar unos de los controles que las extensiones AJAX ASP.NET proveen y el framework se encarga de realizar la generación del Javascript correspondiente para realizar los procesos en segundo plano.
También existe la posibilidad de usar este framework mas a fondo, optimizando el rendimiento, programando ciertas tareas desde Javascript combinando con Servicios Web para evitar el procesado completo del ciclo de vida de una pagina ASP.NET.

Es un framework muy potente, que si integra perfectamente con Visual Studio y ASP.NET 2.0, y también cuenta con un AjaxControlToolkit, que es un conjunto de controles que permiten llevar la interactividad al máximo.

Utilizando AJAX ASP.NET Framework en un caso real

Utilizando este framework es muy interesante, entre otras cosas, obtener datos de un servicio web asíncronamente y devolver el resultado del mismo sin hacer un postback de la página, optimizando el rendimiento y llevando el uso del framework a su máximo poder.

Supongamos que tenemos un conjunto de web services que resuelven nuestra lógica de negocios, se encargan de interactuar con la base de datos, resolver las reglas de negocio, etc. Solo queda por hacer un front-end que obtenga los datos que se desean presentar desde el servicio web.

El webservice que usaremos de ejemplo recibe por parámetro, por ejemplo, un nombre, y devuelve "Hola + parámetro".
Por lo que nuestro cliente del webservice tiene un textbox donde ingresar el nombre, un botón para solicitar la respuesta del webservice y un label donde se mostrara la respuesta. La idea es evitar el postback al presionar el botón y mostrar el resultado en el label asíncronamente sin refrescar la página completa.

Podríamos consumir el webservice sin hacer uso de AJAX, simplemente, creando una webreference en nuestro proyecto del cliente y en el evento Click del botón hacer la llamada al webservice y setear el resultado en el label, pero esto nos implicaría un full postback de la pagina.

La solución para implementar AJAX en una llamada a un webservice es hacer uso del ASP.NET AJAX Framework, combinado con JavaScript del lado del cliente para hacer la llamada al webservice y para la actualización del label con el resultado.
Analicemos esta solución paso por paso.

Lo primero que debemos hacer es indicarle al webservice como debe responder a una llamada JavaScript. Para esto debemos primero modificar el web.config de nuestro proyecto que tiene el webservice agregándole algunas configuraciones.

<?xml version="1.0"?>

<configuration>

<configSections>

<sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">

<sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">

<section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>

<sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">

<section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="Everywhere"/>

<section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>

<section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>

&nbsp; </sectionGroup>

</sectionGroup>

</sectionGroup>

</configSections>

<system.web>

<pages>

<controls>

<add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>

</controls>

</pages>

<compilation debug="true">

<assemblies>

<add assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>

</assemblies>

</compilation>

<httpHandlers>

<remove verb="*" path="*.asmx"/>

<add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>

<add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>

<add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/>

</httpHandlers>

<httpModules>

<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>

</httpModules>

</system.web>

<system.webServer>

<validation validateIntegratedModeConfiguration="false"/>

<modules>

<add name="ScriptModule" preCondition="integratedMode" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>

</modules>

<handlers>

<remove name="WebServiceHandlerFactory-Integrated"/>

<add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>

<add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>

<add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>

</handlers>

</system.webServer>

</configuration>


Este seria el web.config completo que deberíamos tener. Con este web.config nuestro webservices seguirán funcionando si los invocamos con SOAP pero también podrán ser invocados desde JavaScript.

El siguiente paso de decorar el webservice agregando lo siguiente:
[System.Web.Script.Services.ScriptService()]

El código completo del webservice nos debería haber quedado de la siguiente forma:

using System;

using System.Web;

using System.Collections;

using System.Web.Services;

using System.Web.Services.Protocols;

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

[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

[System.Web.Script.Services.ScriptService()]

public class SimpleService : System.Web.Services.WebService {

public SimpleService (){}

[WebMethod]

public string SayHello(String inStr) {

return "Hello : " + inStr + "; Thanks for visiting.";

}

}

Hasta este momento hemos preparado todos nuestros componentes del lado del servidor para que sean capaces de responder la llamada JavaScript que se le hará al webservice, en otras palabras, tenemos un AJAX-Enabled WebService.

Ahora debemos crear un cliente para probar este AJAX-Enabled WebService. Recordemos que no necesitamos crear una webreference.
Lo primero que debemos hacer es agregar un ScriptManager a la pagina .aspx.
El ScriptManager es un componente que forma parte de las extensiones que se agregan a ASP.NET 2.0 para crear aplicaciones AJAX.
El ScriptManager es el encargado de enviar dinámicamente el código JavaScript que el cliente necesita para realizar todas las funcionalidad que nos permite hacer el AJAX ASP.NET Framework.
El conjunto completo de componentes que tenemos disponibles cuando agregamos el ASP.NET AJAX Framework son ScriptManager, ScriptManagerProxy, Timer, UpdatePanel y UpdateProgress.

Necesitamos agregar controles, pero no vamos a utilizar controles del servidor, no son necesarios, utilizaremos controles HTML puros.
Nuestra página .aspx debería tener esta estructura:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head id="Head1" runat="server">

<title>Untitled Page</title>

</head>

<body style="text-align: center">

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

<div>

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

</asp:ScriptManager>

<input id="Text1" type="text" />

<input id="Button1" type="button" value="button"/>

<input id="Text2" type="text" />

</div>

</form>

</body>

</html>

Debemos indicarle al ScriptManager cual es el path al webservice, por lo que agregaremos el webservice a la colección de webservices del ScriptManager de la siguiente forma:

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

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

</Services>

</asp:ScriptManager>

Ahora hemos indicado al ScriptManager que el código va a llamar a un webservice vía JavaScript, entonces el ScriptManager le solicita al servidor que le envié el código JavaScript necesario para conectarse al webservice, esto nos ahorra escribir todo el código JavaScript necesario para conectarnos a un webservices, como por ejemplo, crear a mano un objeto XmlHttpRequest y demás.

Ahora crearemos una función en JavaScript que será ejecutada en el evento onclick del botón que agregamos a nuestra pagina HTML. La llamada al webservice no se hace directamente llamando al método sino que se hace a través de un proxy. También queremos hacer esta llamada asíncrona para no tener que detener la ejecución de la aplicación hasta que el webservice nos devuelva la información que le solicitamos.
Debemos agregar código JavaScript a nuestra pagina .aspx de la siguiente forma:

<script language="javascript" type="text/javascript">

<!--

function Button1_onclick() {

ret = SimpleService.SayHello(document.getElementById('Text1').value, OnComplete, OnTimeOut, OnError);

return(true);

}

function OnComplete(args) {

document.getElementById('Text2').innerText = args;

}


function OnTimeOut(args) {

alert("Service call timed out.");

}

function OnError(args) {

alert("Error calling service method.");

}

// -->

</script>

Recordemos que no estamos llamando al método SayHello directamente sino que lo hacemos a través de un proxy que recibe algunos otros parámetros más que el string que recibe el método SayHello.
El primer parámetro es el del método SayHello, por lo cual le pasamos el contenido de la caja de texto.
El segundo parámetro es el nombre de la función JavaScript que será llamada cuando el webservice nos devuelva exitosamente la información que le solicitamos de manera asíncrona.
El tercer parámetro es el nombre de la función JavaScript que será llamada en el caso que el webservice no responda.
El cuarto parámetro es el nombre de la función JavaScript que será llamada en el caso que se produzca un error, esto significa que el webservice atendió mi petición pero no puedo responder debido a un error.

En la función OnComplete, parseamos la respuesta del webservice en nuestro caso, solamente asignamos el texto que nos envió el webservice al label donde queremos mostrar la respuesta en la página.

Por ultimo debemos agregar que función debe llamarse al ejecutarse el evento onclick del botón.
<input id="Button1" style="width: 193px" type="button" value="button" language="javascript" onclick="return Button1_onclick()" />

En este momento tendríamos el cliente que va a consumir el webservice listo.

Conclusiones

Muchas son las ventajas de utilizar este framework pero las más importantes son: implementar aplicaciones AJAX altamente performantes, reutilizar los webservice que ya tenemos creados y crear fácilmente aplicaciones ricas para el usuario mejorando la productividad y la performance.

Recursos

Para bajar el AJAX ASP.NET Framework:
http://asp.net/ajax/downloads/

Sunday, July 29, 2007

[NXT] Lego Mindstorm
Hola, este es mi primer post sobre mi NXT, luego de muchos problemas para conseguirlo al fin llegó. No tardé mucho en armar el Tribot, el primer modelo que sugiere LEGO que armemos. Luego de haberlo armado pude conectarlo via bluetooth sin ningún problema. El bluetooth que tengo es uno que me vino con un celular motorola. El modelo es MOTOROLA SYN0717A. Por ahora sólo creé algunos programas simples, con el lenguage gráfico que trae el software de LEGO, es bastante completo, asique estoy leyendo la ayuda para saber cuales son todas las funciones que tiene. La idea es luego programarlo desde C#.

Aca les dejo unas fotos de mi Tribot: