Showing posts with label dotnet. Show all posts
Showing posts with label dotnet. Show all posts

Monday, June 22, 2009

RPC reverse BIND failed Access is denied

Cuando estas utilizando DTCPing para validar que los requisitos minimos de comunicacion entre tu Biztalk server y tu Database server esten habilitados entre ambas machines, puede que recibas este mensajito:

Received Bind call from Machine
Trying Reverse Bind to Machine
Error(0x5) at ServerManager.cpp @453
-->RPC reverse BIND failed
-->5(Access is denied.)
Reverse Binding to Machine Failed


Lo que sucede es que la clave HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows NT\RPC probablemente NO exista y debes crearla en el machine, entiendase este como el nombre del server donde estas configurando el soporte para MSDTC.

Dentro de dicha clave, deberas agregar la propiedad: RestrictRemoteClients del tipo REG_WORD con el valor igual 0 (cero).

New transaction cannot enlist in the specified transaction coordinator

Cuando estas utilizando el soporte a transacciones, System.Transactions, para realizar operaciones contra la Database en el desarrollo de tu producto de software, probablemente te encuentres con este mensajito.

System.Runtime.InteropServices.COMException (0x8004D00A): New transaction cannot enlist in the specified transaction coordinator

Lo que sucede es que NO se estan dando todos los requisitos necesario para la comunicacion entre tu Biztalk Server y tu Database Server.

Este mensaje es muy generico, aun, es necesario validar a bajo nivel si las caracteristicas necesarias para el MSDTC estan dadas, entre las dos machines.

Para ello, es necesario que utilices el DTCPing de Microsoft.

Una vez que copies el ejecutable tanto en el Biztalk Server como en el Database Server, los ejecutaras al mismo tiempo.

Desde el Biztalk Server colocaras el nombre de tu Database Server en la consola del DTCPing, y este testeara sin los requisitos minimos de comunicacion entre ambas machines, estan dadas, y te informara de los inconvenientes, para que puedas solucionarlo.

Alli, tendras informacion especifica sobre el inconveniente y ya NO un simple mensaje generico.

Monday, April 13, 2009

Interfaces Web Forms herencia multiple

Interfaces en .NET son pocas veces usadas, por NO decir que jamas son mencionadas, en la implementacion de tu producto de software.

¿Que esta sucediendo? ¿Como te sentis al saber que NO estas utilizando todo el potencial de la tecnologia que tienes en tus manos, hablando estrictamente de C#, claro esta?

Pues VB.NET es un juguete para niños, mas nada :)

Lo que sucede es que NO le encuentras, muchas veces, razon de ser a la necesidad de definir una serie de metodos en una Interface que luego deberas implementar en cada Clase o Class que requiera implementarla.

Suena a realizar trabajo doble. A que NO ganas nada, en realidad, desde un limitado punto de vista.

Nada mas falso que la verdad :)

Las Interfaces tienen una valiosa utilidad. Aquella en la que ese comportamiento definido pueda ser utilizado por otras clases con la finalidad de brindar una valvula de escape al famoso, pero poco usado polimorfismo, en un lenguaje de programacion Orientado a Objetos, quimicamente NO puro, como el caso de los lenguajes de .NET ;)

Por ejemplo, la interfaz IEnumerable, que por cierto es la mas utilizada por el .NET Framework, radica su valiosa utilidad en brindarle la posibilidad a la clase que la implemente en que esta pueda ser iterable sobre el famoso foreach. Omnipresente estructura de control de flujo en el C#.

IEnumerable es de un nivel primario que casi forma parte de la esencia misma del lenguaje C#.NET.

Nosotros ya NO implementamos IEnumerable en nuestras propias clases, pues existen diferentes estructuras de datos, que la implementan y nos facilitan ya esa tarea. Solo nos limitamos a usarla, a sabiendas que existe una estructura de control que la recibe para hacer algo con ella, iterarla. Hablamos del curioso foreach.

He alli la clave para la existencia de Interfaces en el modelo de clases orientadas al producto de software que estamos diseñando.

La necesidad de la existencia de una Clase a la par que defines Interfaces para que las utilizen y hagan algo con ellas, el trabajo pesado. Es decir, para que estas sean parte de la implementacion de un comportamiento de orden superior por el cual fueron concebidos.

¿Se entiende? ¿Toy hablando piedras?

Un ejemplo por favor...!

Bueno, el mas trivial de todos se encuentra en la definicion de un Modelo de Clases e Interfaces para el manejo de Web Forms y Web User Controls en productos de software con conectividad a Base de Datos.

Los Web Forms asumen la gestion de las acciones realizadas por el usuario e implementan el comportamiento, como respuesta a dichas acciones.

Los Web User Controls realizan las tareas a un nivel especifico de detalle, hacen el trabajo laborioso: asignar valores a los TextBox, llenar un DropDownList, recolectar los valores seteados de su propia estructura en un Business Entity y entregarselos a quien lo solicita, and other stuffs :)

En ese sentido, son los Web User Controls candidatos ideales a implementar tus propias Interfaces, previamente definidas, con la intencion de centralizar ciertos comportamientos e implementarlos a nivel de Web Forms.

En concreto, tendras una clase UIPage que hereda de Page, facilitando cierta funcionalidad comunmente usada.

class UIPage : Page
{
protected override void OnLoad( EventArgs e )
{
if( ! this.IsPostBack )
{
this.FirstRequest();
}
}

protected virtual void FirstRequest() { }

protected override void OnInit( EventArgs e )
{
this.DefineHandlers();
this.DefineObjects();
}

protected virtual void DefineHandlers() { }
protected virtual void DefineObjects() { }

// Otras tantas funcionalidades
}

A la vez, tendras una clase UIPageForm que hereda de UIPage

class UIPageForm<TForm> : UIPage
where TForm : IForm
{
protected virtual TForm MyForm
{
get { throw new NotImplementedException(); }
}

// Otras tantas funcionalidades
}

Asi mismo, tendras una clase UIPageEdit que hereda de UIPageForm, centralizando el comportamiento para editar los elementos de ciertas entidades de negocio.

class UIPageEdit<TForm, TAtom> : UIPageForm<TForm>
where TForm : IFormEdit<TAtom>
where TAtom : ITransaction
{
protected virtual TAtom MyAtom
{
get { throw new NotImplementedException(); }
}

// Otras tantas funcionalidades
}

Ahora, imaginemos que se requiere un nuevo comportamiento, por el cual al editar un Business Entity sobre el Web Form, uno de los datos ingresados por el usuario, sobre la vista o View, deba ser unico. Permitiendo la posibilidad de validar aquello a traves de una opcion especial en el View. Asi como, tambien, estrictamente validable al elegir la opcion Save.

Entonces optaremos por una implementacion como esta:

class UIPageEditValidate<TForm, TAtom> :
UIPageEdit <TForm, TAtom>
where TForm : IFormEdit<TAtom>, IFormValidate
where TAtom : ITransaction
{
// Se varia el comportamiento base sobre este contexto
// para soportar el nuevo requerimiento.
}

Ahora, se requiere que ciertos Web Forms soporten el manejo de informacion historica por cada registro, permitiendo navegar sobre dicho historico a traves del mismo Web Form.

Este nuevo requerimiento podria aplicar tanto a Web Forms que soporten la funcionalidad de IFormValidate como a los que NO.

Aqui empieza nuestro problema, como consecuencia de la NO existencia de una herencia multiple de clases, como lo pregona aquella preciosa teoria de la POO, que tanto añoramos.

Si nuestro C# fuese un lenguaje Orientado a Objetos quimicamente puro, bastaria implementar la funcionalidad requerida sobre una clase llamada Navigator, llamada asi para efectos didacticos, y hacer que los Web Forms que requieran dicha funcionalidad la herenden, a la par que heredan su tradicional clase base, que en el mas alto nivel hereda de Page.

Pero NO es posible, entonces tendremos que buscar una forma de superar esta limitacion tecnica.

En esa busqueda, el uso correcto de Interfaces sera la solucion para este requerimiento, definiendo una interfaz INavigator y una clase llamada ConcreteNavigator.

Haciendo una simple analogia, con fines didacticos, INavigator seria como IEnumerable y a su vez ConcreteNavigator seria como la estructura de control foreach. Aquella que hace algo con la interfaz, que la utiliza en el contexto de la implementacion de un comportamiento de orden superior a la simple definicion de una Interfaz.

En ese sentido, tendriamos algo como esto para la interfaz INavigator:

public interface INavigator
{
event EventHandler PreviousClicked;
event EventHandler CurrentClicked;
event EventHandler NextClicked;

void StatusPrevious( Boolean enabled );
void StatusCurrent( Boolean enabled );
void StatusNext( Boolean enabled );
}

Por su parte la clase ConcreteNavigator tendria una implementacion como esta.

public class ConcreteNavigator<TForm, TAtom>
where TAtom : IHasHistory, IBuildHistory<TAtom>
where TForm : IFormEditHistory<TAtom>
{
StateBag _viewstate;
INavigator _navigator;
TForm _form;
TAtom _atom;

public ConcreteNavigator(
StateBag viewstate,
INavigator navigator,
TForm form,
TAtom atom )
{
this._viewstate = viewstate;
this._navigator = navigator;
this._form = form;
this._atom = atom;
}

public void DoPreviousClicked()
{
// Implementacion del comportamiento requerido
// usando los parametros entregados
// al instanciar ConcreteNavigator
// estando INavigator como parte de ellos.
}

public void DoNextClicked()
{
// Idem
}
public void DoCurrentClicked()
{
// Idem
}
}

Entonces se definiran dos nuevas clases para aquellos Web Forms que requieran utilizar el comportamiento plasmado en ConcreteNavigator.

Asi, tendremos las clase UIPageEditNavigator que hereda de UIPageEdit utilizando una instancia de ConcreteNavigator.

public class UIPageEditNavigator<TForm, TAtom> :
UIPageEdit<TForm, TAtom>
where TAtom : ITransaction, IHasHistory, IBuildHistory<TAtom>
where TForm : IFormEditHistory<TAtom>
{
private ConcreteNavigator<TForm, TAtom> _concrete;

protected virtual INavigator MyNatigator
{
get { throw new NotImplementedException(); }
}

protected override void DefineObjects()
{
this._concrete = new ConcreteNavigator<TForm, TAtom>(
this.ViewState,
this.MyNavigator,
this.MyForm,
this.MyAtom );
}

private void MyNavigator_PreviousClicked( Object sender, EventArgs e )
{
this._concrete.DoPreviousClicked();
}

// Otras tanta funcionalidades que se ajustan con
// lo soportado por ConcreteNavigator
}

De la misma forma, definimos la clase UIPageEditValidateNavigator que hereda de la clase UIPageEditValidate utilizando una instancia de ConcreteNavigator

public class UIPageEditValidateNavigator<TForm, TAtom> :
UIPageEditValidate<TForm, TAtom>
where TAtom : ITransaction, IHasHistory, IBuildHistory<TAtom>
where TForm : IFormEditHistory<TAtom>, IFormValidate
{
private ConcreteNavigator<TForm, TAtom> _concrete;

protected virtual INavigator MyNatigator
{
get { throw new NotImplementedException(); }
}

protected override void DefineObjects()
{
this._concrete = new ConcreteNavigator<TForm, TAtom>(
this.ViewState,
this.MyNavigator,
this.MyForm,
this.MyAtom );
}

private void MyNavigator_PreviousClicked( Object sender, EventArgs e )
{
this._concrete.DoPreviousClicked();
}

// Otras tanta funcionalidades que se ajustan con
// lo soportado por ConcreteNavigator
}


De esta manera, se supera la limitacion tecnica de la NO herencia multiple de clases inexistente en los lenguajes de .NET, como C#.

La clase ConcreteNavigator hace el trabajo pesado de una funcionalidad que luego es posible reflejar en diferentes clases, evitando el COPY & PASTE.

Al NO lograr este nivel de abstraccion, estaremos con seguridad, dejando de utilizar todas las bondades que la tecnologia nos brinda, hablamos de la POO.

Nuestro producto de software muy probablemente este disgregado de codigo, como consecuencia irresponsable del COPY & PASTE por everywhere.

Haciendo de este dolorasemente mantenible y vergonzosamente presentable :)

Wednesday, April 08, 2009

Por que usar interfaces en .NET

¿Por que usar interfaces en .NET?

Es la pregunta que siempre aflora cada vez que te encuentras implementando un modelo de clases que se ajuste a la realidad de negocio para el cual debes encontrar una solucion y en la que estas involucrado.

La Programacion Orientada a Objetos, aka POO, nos enseña que uno de los pilares de su existencia es la herencia, en sentido estricto: la herencia multiple.

La herencia multiple de clases es una bondad de la POO, pero al tocarse con la cruda realidad encuentra dificil su implementacion, sin brindarle estabilidad al modelo de clases construido.

Dificil implementacion en el sentido, de una flexibilidad atroz, que en algun momento escape de nuestro control y permita la construccion posterior de comportamientos NO concebidos por el negocio, plasmadas en la construccion de ese modelo de clases que vienes implementando.

La herencia multiple permite que pueda converger en una sola entidad diferentes comportamientos que muy probablemente colisionen sin tener mayor control sobre esa futura mutacion.

Esa flexibilidad se acota en .NET, al permitir solo la herencia simple de clases, NO la herencia multiple.

Los lenguajes de desarrollo en .NET dejan de ser, por eso, lenguajes orientado a objetos como mandan los canones :)

Fue una decision de diseño del CLR Team y el equipo de C#, que se tomo en algun momento, luego de evaluar las debilidades de un leguaje orientado a objetos quimicamente puro, como el precioso C++, por ejemplo.

Por su parte, la teoria de la POO, ya concebia la definicion de interfaces, de una manera distinta. Las clases abstractas son, en la actual implementacion de los lenguajes orientado a objetos, las famosas interfaces con una restriccion: que cada metodo de dicha clase abstracta sea de orden publico.

Las interfaces nacen alli. Y al tener su implementacion en control de quien construye el modelo de clases, de tu producto de software, se permite a nivel de diseño heredar multiples interfaces.

Las interfaces son esa valvula de escape de un lenguaje orientado a objetos que NO permite herencia multiple de clases, con la ambicion de serlo a regaña dientes.

Pero, ¿por que usar interfaces en .NET?

Al utilizar interfaces y definirlas en nuestro modelo de clases estaremos permitiendo la posibilidad de aprovechar las bondades de un lenguaje orientado a objetos en .NET, en beneficio de una mejor implementacion del producto de software.

Una de esas tantas bondades es el polimorfismo.

¿Que beneficio encontrare al utilizar las interfaces?

Tiempo, simplemente. ¿Te parece poco, pregunto?

El uso de interfaces que definen comportamientos, que aquellas clases que las hereden deban establecer su correcta implementacion, eleva tus posibilidades de reducir los tiempos en la construccion del software, abrumadoramente.

Orientar la implementacion de tu modelo de objetos en funcion a la herencia simple de clases apoyada en la herencia multiple de interfaces, para el uso de estas en el envio de informacion entre las clases de tu propio modelo, para la definicion de tus Templates y para el manejo apremiante de delegates, te permitiran alcanzar un nivel de abstraccion, en el diseño y la arquitectura de tu modelo de clases, que se vera reflejado en reducir los tiempos para desarrollar tu producto de software y por ende los costos.

De nada sirve tipear codigo a diestra a siniestra, que promueve el COPY & PASTE por everywhere, haciendo del codigo un telaraña dolorosamente mantenible y vergonzosamente presentable.

Si NO defines tus propias interfaces en el modelo de objetos que haz diseñado, NO estaremos avanzando, solo retrocediendo.

El dolor vendra la proxima vez que tengas que meterle mano a esa basura de codigo, donde las clases que tienen comportamientos similares esten implementadas de formas totalmente distintas, sin guardar coherencia entre si, NI centralizar las lineas bases de dicho comportamiento.

Solo te quedara exclamar: Esos cambios son muy drasticos...!!!

Wednesday, March 25, 2009

Templates Tipos Genericos Herencia

Cuando estas desarrollando software, es una consecuencia natural el uso de Templates para facilitar la construccion del codigo, ahorrar lineas repetitivas disgregadas en diferentes clases de uso final, y reducir los tiempos.

Si dentro de la construccion de tus clases solo utilizas Templates para hacer un List<String> o a lo mucho un IEnumerable<Client>, ten la plena seguridad que estas desperdiciando el uso favorable de la tecnologia que tienes en tus manos, en este caso C#, de manera irresponsable y muy probablemente estes quemando tus neuronas haciendo el laborioso COPY & PASTE por everywhere...!

Debes cambiar el rumbo, alguien debe girar el timon :)

En ese uso de siniestros Templates, dentro de la definicion de aquellas clases que heredan su comportamiento de otras clases que se han diseñado como Templates, muy probablemente te encuentres con un mensaje como este:

'TEntity' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'TEntity' in the generic type or method 'SomeClass<TEntity>'

Lo que sucede es que la clase SomeClass presenta una serie de restricciones para su normal ejecucion. Dichas restricciones se implementan con el uso de la clausula where en la definicion de la clase o en los metodos de la misma, que el arquitecto establecio en el diseño de dicha clase.

En consecuencia, al implementar la herencia de una clase que tiene dichas restricciones, solo queda ir de la mano con ella.

En terminos sencillos, tendras que establecer las mismas restricciones haciendo uso de la clausula where en la implementacion de tu nueva clase y agregar otras nuevas que creas conveniente para la construccion de la tuya.

En el caso en concreto del mensaje que te mostre anteriormente, este nos indica que el tipo generico TEntity requiere ser instanciada en alguna parte del codigo de la clase heredable.

Es decir, debes agregar esta restriccion: where TEntity : new() en tu nueva clase.

Friday, January 09, 2009

Usando Threads con parametros

Utilizar Threads brota a la necesidad de ejecutar multiples operaciones relativamente pesadas.

Pesadas en el sentido que el tiempo para concluir su ejecucion, es relativamente indeterminado. Es decir, la aplicacion NO puede quedarse a la espera de que concluya dicha operacion sin que el usuario quede inhabilitado de continuar usando el software.

Los Threads permiten una solucion a esta necesidad.

Sin embargo, como toda operacion siempre se requerira de una especie de parametrizacion, es decir, enviarle una serie de parametros para que se ejecute con ciertas variables inicializadas previamente.

¿Que hacer ante este requerimiento? ¿Como puedo pasarle parametros a un metodo corriendo sobre un Thread?

Un metodo extenso, es casi siempre una potencial clase, es decir un class, que podras encapsular de la manera que mejor creas conveniente.

Aquel metodo relativamente extenso y pesado, podra ser abstraido a una clase, a la cual expondras un metodo publico sin parametros: Run, por ejemplo.

El constructor de la clase, tendra todos los parametros necesarios que requiera esa operacion relativamente pesada.

Entonces, tu instanciaras un objeto de dicha clase, y colocaras sobre un Thread el metodo Run de aquella class.

MyClass o = new MyClass( param1, param2 )
Thread t = new Thread( o.Run );
t.Start();

Este mecanismo te brindara la solucion a tus problemas.

Por otro lado, existe una clase propia del .NET Framework llamada ParameterizedThreadStart pero como todo lo que esta disponible para usar en el .NET Framework, tiene un costo, perder el control sobre la ejecucion interna de la operacion sobre el Thread.

Algo que a la primera, puede que NO le tomes la minima importancia, pero que luego, conforme van madurando el producto de software, este debe ajustarse a mas necesidades que la inicialmente indicadas.

Por lo que perder el control, tendra un costo mas alto despues.

Ese despues, esta solo a la vuelta de la esquina. NO lo dudes!

Monday, October 06, 2008

Visual Studio 2010 y Rosario

Microsoft anuncio que Visual Studio 2010 y .NET Framework 4.0 seran los proximos productos para el desarrollo de aplicaciones y su respectiva plataforma.

NO pasaron solo 10 meses desde que las versiones anteriores salieron al mercado.

Estamos jodidos, cada vez es mas facil programar. NO hay dudas. Un chiquillo de primero de secundaria podria sentarse al frente del Visual Studio .NET 2010 y construir una sencilla interfaz de usuario y luego darle una trivial funcionalidad, sin mayores inconvenientes.

Con mayor razon, si tienes algunos años mas de experiencia.

Visual Studio Team System VSTS 2010 comunmente llamado Rosario, esta orientado a ser el siguiente pilar para el desarrollo de software.

Al lado de Windows Comunication Fundation WCF, Windows Presentation Fundation WPF, y Windows Workflow WF, el proximo Visual Studio Team System 2010 trae consigo ALM Application Life-cycle Management, una especia de gestor de ciclo de vida del software.

En fin, NO hay dudas que al coger Visual Studio 2010 hace que las cosas sean mas sencillas de lo que eran ya con la version anterior, el Visual Studio 2008.

Venga Rosario!

Monday, July 28, 2008

SetValue PropertyInfo FieldInfo Struct

Cuando defines tus Business Entities como structuras y NO como clases, es decir como struct.

Estableciendo sus diferentes atributos, para que posteriormente manejar el mapping correcto con su correspondiente tabla a nivel de base de datos, requeriras de una mecanismo generico para hacer la lectura de los registros de dicha tabla de base de datos hacia una coleccion de Business Entities, para manejarlos como tal dentro del mundo .NET

Hasta alli, todo relativamente normal.

Pero al usar un struct para definir cierto Business Entity, te daras cuenta que el metodo SetValue del PropertyInfo o el FieldInfo -dependiendo lo que estes usando para definir las propiedades o atributos de tu Business Entity- NO estan funcionando como tu esperas.

Lo que sucede es que las estructuras o struct, son tipos de datos por valor a diferencia de las clases o class.

Y este es uno de los puntos en contra al utilizar estructuras o struct para definir tus Business Entities.

En este incidente la clase ValueType resuelve tu problema.

TEntity entity = new TEntity();

Debera ser reemplazado por:

ValueType entity = new TEntity();

Dentro del bucle que este leyendo el SqlDataReader para iterar cada uno de los registros de la consulta que hayas realizado, mapeando cada uno de estos registros dentro de su Business Entity para retornar finalmente a una coleccion de Business Entities, a quien haya utilizado el metodo generico que implementaste.

IEnumerable ExecuteReader( String sql ) where TEntity : struct

Vale recalcar que es importante utilizar la clausula where TEntity : struct para poder instanciar el template TEntity dentro de la implementacion de dicha funcion y para poder castearlo a un ValueType, posteriormente.

Friday, September 29, 2006

SmtpClient and SmtpMail

Otra de las clases que quedaron obsoletas para el .NET Fx 2.0 es el famosisimo SmtpMail, el cual encapsulaba la funcionalidad del CDONTS para .NET Fx 1.1.

La clase que la sustituye es el SmtpClient ubicado en el System.Net.Mail namespace esto dentro del System.dll assembly.

Sin embargo, el SmtpClient no es una clase estatica (static) que pueda usar como lo haciamos en el .NET Fx 1.1 ahora es necesario instanciar la clase para poder usar sus metodos y propiedades.

Aparecen nuevas clases que pueden ser usadas, como MailAddress que encapsula una dirección electronica de correo.

Las propiedades From y To del SmtpClient no son del tipo String como en el caso del SmtpMail. Ahora son del tipo MailAddress. La propiedad To es de solo lectura.

Cuando instancias la clase MailMessage es más util usar el constructor:

MailMessage message = new MailMessage( from, to );

Al instanciar el SmtpClient puedes indicar un puerto distinto al 25, si es que lo necesitases, así.

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...!

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?