martes, 28 de febrero de 2012

Criptografía



Navegando por ahí encontré este video que nos explica de una forma sumamente simple cómo es que funciona la criptografía en internet, comenzando con una conexión segura utilizando un algoritmo asimétrico para establecer una llave simétrica.

Los algoritmos de llave asimétrica son los más seguros pero consumen muchos recursos dada la complejidad de su cifrado y descifrado.

Los algoritmos de llave simétrica son los más rápidos pero presentan la problemática de compartir de una forma segura la llave que nos ayudará para cifrar y descifrar.

Espero les sea de mucha utilidad.

viernes, 24 de febrero de 2012

Ícono en control personalizado



Es común que no nos preocupemos por darle una imagen significativa (metáfora visual) a nuestros controles dado que como desarrolladores creemos que son cosas que no interesan mucho, total, funcionan y para eso fueron creados ¿no?

No quiero iniciar una discusión acerca de si es bueno o no, cada quien tiene sus razones y serán tan válidas como sus clientes (otros desarrolladores que utilicen sus controles) acepten las imágenes asociadas a los controles.

Asignarle un ícono diferente al del engrane con el que aparecen de inicio no es complicado, lo único que debemos hacer es:
  1. Generar una imagen de 16x16 en mapa de bits
  2. Guardarle con el mismo nombre de nuestro control, por ejemplo, si nuestro control se llama AsyncSchedule, el archivo deberá llamarse AsyncSchedule.bmp
  3. Agregamos el archivo al proyecto y en sus propiedades (seleccionar archivo en el explorador de soluciones - clic derecho - propiedades) elegimos que es un recurso incrustado.
  4. Recompilamos nuestro ensamblado.
  5. Eliminamos el control de la barra de herramientas y lo volvemos a agregar.
¡Lixto!

En lo personal me gusta que tengan imágenes, le da variedad al contenido de mi barra de herramientas.

martes, 21 de febrero de 2012

Controles extendidos



Controles personalizados es uno de los temas más interesantes y desafiantes de la programación en ASP .NET, todo esto debido a la complejidad y versatilidad que se tiene para poder crearlos.

Podemos dividir los controles personalizados en las siguientes categorías (las pondré en inglés dado que la mayor referencia de información la encontrarán en ese idioma):

1. Web controls.    También llamados "from the scratch", debemos crear cada pedazo de código HTML que conforme a
nuestro control.
2. Composite controls.    Conformado a partir de la agrupación de controles existentes.
3. Inherited controls (extended controls).    Se le agregan o modifican las características funcionales o visuales de controles que ya existen.
4. Templated controls.    Permiten la personalización de los componentes que los conforman... a mi forma de ver, estos son los más complejos.
5. Web user controls.    Recomendados para controles que sólo se utilizarán en un proyecto.

Esta entrada está dedicada a explorar de una forma simple los controles compuestos (composite controls) a través de la creación de un control que nos ayudará a cargar un archivo al servidor sin tener que esperar a que el usuario dé clic en un botón o link en especial para poder enviar el archivo al servidor.

Los controles compuestos son fáciles de identificar dado que heredan de la clase CompositeControl
(System.Web.UI.WebControls)

Vamos a crear un proyecto de tipo "Biblioteca de clases" en Visual Studio y lo llamaremos "MyControls", allí agregamos una clase que llamaremos "ImmediateUploader".

Hacemos referencia al ensamblado System.Web y agregamos las siguientes líneas a nuestro archivo ImmediateUploader.cs:

using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;

Ahora haremos que nuestra clase ImmediateUploader herede de CompositeControl:

public class ImmediateUploader : CompositeControl

Recordemos que los controles compuestos son aquellos que están formados a partir de controles ya existentes, es decir que toman las características y ventajas que tienen y los agrupan de tal forma de exponer la funcionalidad deseada.

En nuestro caso queremos mostrar un control donde el usuario pueda elegir un archivo de su computadora e inmediatamente después de darle clic al botón "Abrir" u "Ok" comience la carga del archivo.

De primera vista es fácil identificar que necesitaremos un control FileUpload pero para enviar el post de la página con el archivo seleccionado utilizaremos un botón oculto el cual disparará el evento deseado.

En los controles personalizados existe un método llamado CreateChildControls el cual es llamado cuando se necesita que el control genere la jerarquía de controles que lo conformarán.    Dado que CompositeControl viene vacío, aprovecharemos este método para agregar los controles FileUpload y Button:

protected override void CreateChildControls()
{
  FileUpload fu = new FileUpload();
  fu.Width = this.Width;
  fu.ID = "FileUpload";
 
  Button upload = new Button();
  upload.Style.Add(HtmlTextWriterStyle.Display, "none");
  upload.Click += new EventHandler(upload_Click);
  upload.ID = "Upload";
 
  Controls.Add(fu);
  Controls.Add(upload);
 
  fu.Attributes.Add("onchange", "raiseUploadClick_" + this.ClientID + "('" + upload.ClientID + "')");
}

Notemos lo siguiente:

1. Estamos ocultando el botón al asignarle a su estilo un "display" un valor de "none".
2. Estamos agregando el manejador del evento Click del botón para enterarnos del momento en que se realiza el POST por parte del navegador.
3. Estamos agregando un atributo "onchange" a nuestro control FileUpload para que nos avise a través de una función javascript que el usuario seleccionó un archivo.

Para avisarle a la página (donde se estará utilizando nuestro control) que se ha elegido un archivo, nuestro control lanzará un evento llamado FileUploaded.    Para lograrlo escribiremos el siguiente código:

public delegate void FileUploadedHandler(object sender, HttpPostedFile postedFile);
public event FileUploadedHandler FileUploaded;
void OnFileUploaded(HttpPostedFile postedFile)
{
  FileUploadedHandler handler = FileUploaded;
  if (handler != null)
    handler(this, postedFile);
}
void upload_Click(object sender, EventArgs e)
{
  if ((FindControl("FileUpload") as FileUpload).HasFile)
  {
    OnFileUploaded((FindControl("FileUpload") as FileUpload).PostedFile);
  }
}

Por último, vamos a modificar la forma en que nuestro control realizará el Render de su estructura:

protected override void Render(HtmlTextWriter writer)
{
  base.Render(writer);
  StringBuilder sb = new StringBuilder();
  sb.Append("<script type=\"text/javascript\">");
  sb.Append("function raiseUploadClick_" + this.ClientID + "(b){");
  sb.Append("document.getElementById(b).click()");
  sb.Append("}");
  sb.Append("</script>");
  writer.Write(sb.ToString());
}

La llamada base.Render hace que cada uno de los controles que se encuentran en la propiedad Controls de nuestro control compuesto sea traducido al HTML que le corresponde y escrito en el HtmlTextWriter.

Podemos ver que después de la llamada a base.Render estamos escribiendo una función de javascript para que se lance el post de nuestra página a través de la llamada del evento click del botón oculto.

Compilemos nuestro proyecto (Shift + Ctrl + B) y para probarlo haremos los siguiente:

1. Agregaremos un sitio web a nuestra solución (File - Add - New Web Site)
2. Abrimos en modo diseño nuestra página Default.aspx
3. Desplegamos la barra de herramientas y vamos a ver que aparece un control llamado ImmediateUploader, lo arrastramos a nuestra página.

Ejecutemos nuestro sitio web y veremos que al elegir un archivo y abrirlo se dispara el POST de la página.

Cerremos el navegador y finalicemos nuestro ejercicio cachando el evento y agregando metadatos a nuestro control.

Abrimos a nuestra clase ImmediateUploader.cs y agregamos el atributo "DefaultEvent" a nuestra clase de la siguiente forma:

[DefaultEvent("FileUploaded")]
public class ImmediateUploader : CompositeControl

Y también agregaremos un atributo "Description" a nuestro evento de forma tal que el programador que utilice nuestro control entienda para qué sirve o cuándo se dispara nuestro evento:

[Description("Raised when end user select a file from its computer")]
public event FileUploadedHandler FileUploaded;

Compilamos de nuevo el proyecto (Shift + Ctrl + B) y abrimos "Default.aspx" en vista diseño para dar doble clic sobre nuestro control ImmediateUploader.    Veremos que nos crea un procedimiento (Default.aspx.cs) que estará ejecutándose cuando el evento FileUploaded de
nuestro control se haya disparado:

protected void ImmediateUploader1_FileUploaded(object sender, HttpPostedFile postedFile)
{
}

¿Qué podemos hacer con postedFile?, depende del objetivo del control en la página, eso queda a su criterio dependiendo de las necesidades u objetivos de su página.