00011101

Hola!


Ya es oficial. Hoy soy un año más viejo que ayer. ¿A que no adivináis cuántos cumplo? [:P]


Aprovecho para dar las gracias a todos los lectores de Geeks.ms. Muchas gracias por estar ahí, y aportar comentarios que enriquecen muchísimo los contenidos de los blogs.


Saludos!

Invocando páginas ASP.NET con procesos pesados y no morir en el intento

Hola!

Hoy voy a escribir un artículo sobre procesamiento asíncrono en ASP.NET. El escenario planteado es el siguiente: Tenemos una aplicación ASP.NET desde la que necesitamos lanzar un proceso bastante pesado. Es decir, que llevará bastante tiempo terminarlo. Obviamente, si lo invocamos de la manera tradicional, es muy probable que recibamos un error de Timeout en el servidor.

Cuando se presenta una situación como la que describimos, lo primero que se suele venir a la cabeza es lo de siempre: usar hilos. Pero he aquí que estamos desarrollando bajo ASP.NET, en el que los objetos que se crean desde una página se destruyen cuando esa página se termina de procesar, para volver a ser creados en la siguiente petición. Esto quiere decir que si lanzamos un hilo para ejecutar un proceso pesado, hemos de dejarlo corriendo (sin esperar a que termine) para no bloquear el procesamiento de la página si no queremos recibir el error de Timeout.

Esta situación además implica que si queremos saber en qué estado se encuentra nuestro proceso, debemos de ser capaces de consultar el estado desde un objeto diferente (y probablemente desde un hilo diferente también) a aquél que lo haya iniciado.

También hemos de tener en cuenta que se pueden dar varios de estos procesos de forma simultánea, con lo que si queremos consultar el estado de la operación, hemos de identificar de alguna manera a qué operación nos estamos refiriendo.

En este caso, una posible solución sería la siguiente:

Lo primero, podemos crearnos una clase que encapsule el procesamiento pesado que hemos de realizar. Esta clase debe proveer los métodos necesarios para consultar el estado actual del proceso que estamos lanzando. Las ventajas de encapsularlo en una clase es que para lanzar el proceso, podremos crear una instancia de esa clase, dar valores a las propiedades que sean necesarias como datos de entrada del proceso, y arrancar en un hilo aparte el procesamiento llamando a un método de la instancia que acabamos de crear. Si es necesario podemos implementar el interfaz IDisposable si tenemos que liberar recursos al finalizar el proceso.

Lo segundo, podemos crear una clase que haga de repositorio para todos los procesos que se están ejecutando. Para identificar cada una de las instancias de la clase comentada en el apartado anterior, podríamos utilizar un Guid que generaremos al lanzar el proceso. Si estamos utilizando .NET 2.0, podríamos utilizar un Dictionary genérico, con clave de tipo Guid, y usando como tipo del valor la clase comentada en el apartado anterior. Si estamos usando .NET 1.0 ó 1.1, podremos utilizar un Hashtable. Esta clase deberá implementar el patrón Singleton, de manera que podamos acceder a la misma instancia desde la página que queramos, y además implementará los métodos necesarios para facilitarnos la interacción con la colección.

Por último, en la página que inicia el proceso, crearemos una instancia de nuestra clase que encapsula el procedimiento, y generaremos el Guid que lo indentificará en la clase repositorio. Añadimos la instancia al repositorio utilizando dicho Guid, y arrancamos un hilo pasándole el método que hace el trabajo pesado como punto de arranque del hilo.

Después podemos redirigir la respuesta a otra página donde se comprobará el estado de la petición, pasándole a esta página el Guid que hemos generado. O también se podría redirigir a una página que muestre el listado de peticiones pendientes.

Si no estamos usando Ajax, podemos hacer que la página que comprueba el estado del proceso se refresque (si no ha terminado aún) añadiendo una cabecera a la respuesta de la siguiente manera: Response.AddHeader(«Refresh», «2»)

Si el proceso ha terminado, simplemente quitamos del repositorio la instancia que ha terminado su ejecución (utilizando nuevamente el Guid) – y si implementa el interfaz IDisposable, llamar al método Dispose – y redirigimos a una página que indique que ya hemos terminado la ejecución del proceso.

Bueno, pues esto es todo por hoy… Saludos!

Technorati tags: ,

Configurando Windows Live Writer para escribir en Geeks.ms

Hola a todos!


Después de pensármelo desde hace un tiempo, he decidido probar Windows Live Writer para escribir los artículos de este blog. La verdad es que lo estoy probando en el mismo momento que estoy escribiendo esta entrada.


La configuración del Live Writer para utilizarlo con Geeks.ms ha sido de lo más sencilla, y ha recuperado los post anteriores sin ningún problema. Supongo que el hecho de que los propios blogs de MSDN utilicen Community Server (al igual que Geeks.ms) influirá de alguna manera para que esta herramienta funcione tan bien con ellos.


Los pasos a realizar para configurar Live Writer con Geeks son los siguientes:



  • Seleccionar la publicación para otro servicio de Weblog (Another weblog service). Pulsamos Next>.

Paso 1



  • Introducir la URL de la página de inicio del blog, el usuario y el password utilizados para la publicación. Pulsamos Next>.





  • Por último, introducimos el nombre del blog (vendrá relleno con el nombre del blog por defecto), y pulsamos Finish.


Con esto, podremos publicar entradas en el blog usando Windows Live Writer (siempre y cuando estéis leyendo esta misma entrada… 😉 )


Saludos!

Accediendo a datos de Excel desde C# con OleDb

Microartículo al canto sobre extracción de datos de Excel utilizando ADO.NET. Excitante, ¿verdad?


¿Que no?… Bueno, quizá no tanto, pero como me ha resultado útil, sobre todo para evitar picar datos a mano, y pasarlos a SQL Server… Pues aprovecho y calzo un microartículo.


Lo primero que debemos hacer es hacer nuestros datos accesibles a OleDb. Para ellos, desde Excel, abrimos nuestro fichero excel, y en la hoja en la que tengamos los datos, los seleccionamos, incluyendo las cabeceras de las columnas. Incluir las cabeceras es importante, porque nos darán los nombres de las columnas cuando accedamos al DataTable.


Teniendo los datos seleccionados, vamos al menú Insertar->Nombre->Definir…, (Insert->Name->Define…), y elegimos un nombre para la selección. Este nombre será el que usemos a la hora de hacer nuestra consulta como nombre de tabla.


Una vez hecho esto, guardamos el fichero y cerramos Excel.


En nuestra aplicación C#, lo que debemos hacer es crear una OleDbConnection con la siguiente cadena de conexión:


String sConnectionString = «Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Book1.xls;Extended Properties=Excel 8.0;»;

Y ya tenemos lista la conexión. Para recuperar los datos, crearemos un OleDbCommand, con una consulta similar a la siguiente:


OleDbCommand objCmdSelect =
      new OleDbCommand(«SELECT * FROM NombreAsignadoEnExcel», objConn);

Y con esto, habremos terminado.


Saludos!

Creando un Web Crawler con .NET

Hola!

Este artículo tratará sobre dos temas: Las capacidades de red del Framework de .NET (sin entrar en WCF) y las expresiones regulares. Y para mostrar un ejemplo sencillo de cómo utilizar ambas, vamos a desarrollar un Web Crawler, que no es nada más que una aplicación que tomando como punto de partida una URL, examina la página de dicha URL buscando enlaces, y los sigue para completar un mapa de la web. Este proceso se lleva a cabo de forma recursiva, y para evitar que se quede corriendo indefinidamente le indicaremos la profundidad máxima que puede explorar.

Además, como las páginas pueden tener enlaces comunes, iremos marcando las páginas que ya se han visitado, e incluso podríamos usar un sistema de puntos o pesos para ver qué páginas son las que más enlaces reciben. Esto a una escala mayor, y con un sistema de pesos más complejo (aparte de un análisis del contenido, cosa que no haremos) es básicamente lo que realizan los robots de los buscadores para alimentar sus bases de datos.

Primero vamos a olvidarnos de cómo obtener el HTML de las páginas web (que veréis que es muy sencillo) y vamos a centrarnos en cómo procesarlo para obtener los enlaces y las rutas de los mismos. Aquí es donde entran en juego las expresiones regulares. Utilizaremos dos: Una para detectar los enlaces en el HTML (realmente vamos a buscar los href=»…», que aparecen también en CSS, y otros tags), y la otra para procesar URLs.

private Regex urlRegex = new Regex(@"^(?<s1>(?<s0>[^:/?#]+):)?(?<a1>"
                + @"//(?<a0>[^/?#]*))?(?<p0>[^?#]*)" 
                + @"(?<q1>?(?<q0>[^#]*))?" 
                + @"(?<f1>#(?<f0>.*))?");
 
private Regex hrefRegex = new Regex("href\s*=\s*(?:(?:\"(?<url>[^\"]*)\")|(?<url>[^\s]* ))");

Una vez que tenemos listas las expresiones regulares, podremos obtener todos los href presentes en la página actual. Para seguir avanzando en profundidad, simplemente debemos pedir el recurso al que apunta, y repetir el proceso. De ahí que utilicemos la recursión.

El segundo tema a tratar es cómo pedir las páginas: .NET provee de clases en el namespace System.Net que nos permiten hacer peticiones HTTP de forma sencilla. Nosotros usaremos System.Net.WebRequest, System.Net.HttpWebRequest y System.Net.HttpWebResponse

Un posible uso de estas clases es el siguiente:

HttpWebRequest req = (HttpWebRequest) WebRequest.Create(currentURL); 
HttpWebResponse resp = (HttpWebResponse) req.GetResponse();
if(resp.ContentType.ToLower().IndexOf("text/html") > -1)
{
    Stream istrm = resp.GetResponseStream();
    StreamReader rdr = new StreamReader(istrm);
    string pageHtml = rdr.ReadToEnd();
 
    ...
}
resp.Close();

Podéis ver los detalles de la implementación del crawler en el código del adjunto.

Saludos! 

Se acercan novedades…

Hola!

En este blog generalmente escribo artículos técnicos que suelen estar basados en cosas que me encuentro en mis quehaceres diarios. Sin embargo, quiero llevar esto un paso más allá, y por eso se acercan novedades, para compartir también desde un punto de vista diferente mis experiencias en este mundo de la informática. Eso sí, sin abandonar los artículos técnicos 🙂

Estad atentos… Porque probablemente podáis ver de lo que estoy hablando el próximo domingo, si las cosas no se tuercen… 😉

Saludos!
 

Más sobre depuración

Este va a ser un microArtículo en el que os voy a comentar cómo depurar componentes en tiempo de diseño.
 
A veces, si no tenemos cuidado, al desarrollar componentes podemos encontrarnos con comportamientos no deseados en tiempo de diseño, y no saber qué puede estar causándolos. Para arrojar un poco de luz sobre qué puede estar causando el error, podemos depurar nuestros controles en tiempo de diseño.

¿Cómo?

Es muy sencillo. Supongamos que tenemos abierto una instancia de Visual Studio, donde estamos desarrollando nuestro componente. Hemos de abrir una segunda instancia de Visual Studio. Desde esta segunda instancia depuraremos nuestro componente en tiempo de diseño. Para ello, vamos al menú Herramientas (Tools) y seleccionamos la opción «Procesos de depuración…» (Debug processes…), como en el artículo anterior.

En esta ocasión, el proceso a depurar es el devenv.exe (el propio Visual Studio). Aseguraos de escoger el proceso cuyo título coincida con aquél en el que estáis desarrollando el componente. Además, en la columna Tipo («Type») deberá aparecer «.NET» (también podrá poner Win32, y puede que alguna otra cosa). En la ventana en la que nos indica qué queremos depurar, aseguraos de que está marcada la opción «Common Language Runtime» (es decir, que queremos depurar código .NET)

Tras esperar un (más o menos largo) momento a que el depurador haya cargado toda la información (dlls, pdbs y demás), abrimos el fichero con el código del componente (directamente, sin abrir el proyecto, sólo el fichero con la clase que nos interesa), y empezamos a poner puntos de interrupción (Breakpoints). Una vez estemos preparados, pasamos a la primera instancia de Visual Studio .NET, y abrimos (o usamos) el componente en tiempo de diseño. En el momento que alcance alguno de nuestros puntos de interrupción, podremos empezar a depurar tranquilamente 😉

Un consejo: Puede ser interesante el cambiar la configuración de las excepciones en la segunda instancia del Visual Studio, de manera que en el momento en el que se lance una excepción (sea manejada o no) se interrumpa la ejecución para poder depurar. Esto se puede hacer en el menú Depuración, seleccionamos Excepciones. En la ventana que aparece, seleccionar las excepciones del CLR, y en los radio buttons que aparecen abajo, marcad «Break Into The Debugger» tanto para las excepciones manejadas como para las lanzadas.

Pues eso es todo por hoy.

Saludos!