20 ago 2009

Escribiendo un archivo de texto en Web

Por alguna razón, necesitaba escribir un archivo de texto a modo de Log con mensajes desde una aplicación web, y dejarlo dentro de la propia estructura del sitio en una carpeta especial parametrizable por web.cofig, y el nombre del archivo siempre debía ser Log.txt

Primeramente en el proyecto que usemos para almacenar las clases utilitarias creamos una nueva o reutilizamos alguna afín. Creamos un método que invocar cuando queramos usar para registrar los mensajes. En la clase que usemos debemos incluir el siguiente import
using System.IO;

y en el método lo siguiente:
String rootPath = System.Web.HttpContext.Current.Request.PhysicalApplicationPath;
string pathLog = ConfigurationSettings.AppSettings["PATHLOG"];
if (!string.IsNullOrEmpty(pathLog))
{
    pathLog = Path.Combine(rootPath, pathLog);
    pathLog = Path.Combine(pathLog, "Log.txt");

    if (!File.Exists(pathLog))
    {
          using (StreamWriter sw = File.CreateText(pathLog))
          {
                sw.WriteLine("Archivo creado " + DateTime.Now.ToString());
                sw.WriteLine();
          }
    }

    using (StreamWriter sw = File.AppendText(pathLog))
    {
          sw.WriteLine("");
          sw.WriteLine("NUEVO EVENTO______Fecha y Hora:" + DateTime.Now.ToString());
          sw.WriteLine("");
          sw.WriteLine("DESCRIPCION:");
          sw.WriteLine("");
          sw.Write(Mensaje);
          sw.WriteLine("");                 
    }
}

Con esta instruccion System.Web.HttpContext.Current.Request.PhysicalApplicationPath encontramos el path fisico donde se encuentra nuestra aplicación web y por medio de Path.Combine vamos formando el path completo donde queremos dejar nuestro archivo.

Por medio del StreamWriter creamos el archivo si no existe (CreateText) y comenzamos a escribir(AppendText) en el mismo. En este ejemplo la variable Mensaje se pasa por parámetro al método con el texto que queremos dejar en nuestro Log.

4 ago 2009

Javascript desde C#

Hace poco necesitaba abrir una ventana emergente luego de dar clic en botón en una página aspx, he inmediatamente después re-direccionar la pantalla "padre" a otra dirección. Para cumplir estos objetivos se me ocurrió registrar un script en el evento del botón (obviamente después de ejecutar/procesar lo que tenía que hacer del lado del servidor) lo cual me quedó mas o menos así:
...

    StringBuilder script = new StringBuilder();
    script.Append(" < script language= ");
    script.Append(Convert.ToChar(34));
    script.Append("javascript");
    script.Append(Convert.ToChar(34));
    script.Append("> ");
    script.Append("window.open(");
    script.Append(Convert.ToChar(34));
    script.Append("PaginaPopup.aspx?Parametro1=");
    script.Append(intParametro1.ToShortDateString());
    script.Append("&Parametro2=");
    script.Append(intParametro2.ToString());  
    script.Append(Convert.ToChar(34));
    script.Append(",");
    script.Append(Convert.ToChar(34));
    script.Append(Convert.ToChar(34));
    script.Append(",");
    script.Append(Convert.ToChar(34));
    script.Append("Width: 400px; Height: 250px; scroll: no; status:yes;");
    script.Append(Convert.ToChar(34));
    script.Append(");");
    script.Append(" window.location=");
    script.Append(Convert.ToChar(34));
    script.Append("PaginaRedireccionar.aspx");
    script.Append(Convert.ToChar(34));
    script.Append(";");        
    script.Append(" < / script >");
        
    ClientScript.RegisterClientScriptBlock(this.GetType(), "popup", 
script.ToString());

...


En este ejemplo usé un StringBuilder para ir creando el script; se utiliza un window.open para abrir la página PaginaPopup.aspx con dos parámetros (Parametro1 y Parametro2) y especificamos las características de la ventana a abrir. Seguidamente usamos window.location para re-direccionar la ventana "padre" a la página PaginaRedireccionar.aspx

finalmente registramos este script por medio del metodo ClientScript.RegisterClientScriptBlock y misión cumplida!

23 jul 2009

¿Múltiples Webservices o un único con muchos Webmethods?

Mi amigo Natacuin, gran programador aunque últimamente más del lado de la administración, planteo hace poco esa pregunta: se debe utilizar un único webservices con muchos webmethods o es preferible por rendimiento partirlos en varios webservices con menos webmethods.

El mismo Natacuin buscó su respuesta planteándose un escenario y una serie de pruebas reseñables las cuales se encuentran en esta entrada de su blog para consulta y mayor detalle.

La conclusión a la que llegó es que "Las diferencias existen pero no son abismales, lo que significa que para que el rendimiento sea un factor a tomar en cuenta, los request por segundo al sistema deben ser miles ". Y que la recomendación es que es preferible usar múltiples webservices, lo cual también puede redundar en otros beneficios como en un mayor orden ya que se pueden agrupar en un webservice los webmethod afines, logrando asu vez facilidad de mantenimiento e incluso de programación por cuanto se pueden atender varios webmethods por varias personas sin pensar en la consistencia del código en el caso de que no se contase con una herramienta que lo controle por nosotros.

11 jul 2009

OLEDB para cargar archivos de excel

Recientemente debíamos cargar un archivo al servidor y cargar sus celdas en una base de datos. Ademas debíamos cumplir el requerimiento de no instalar ningún componente de MS Office en los servidores.

Como sugerencia del departamento de sistemas del cliente se nos indicó que utilizáramos Dtsx para realizar esa operación y de hecho llegamos un solución con paquetes SSIS. Sin embargo se nos complicó por una cuestión de permisos. Finalmente optamos por hacer una solución basada en OleDB más sencilla y más fácil para darle mantenimiento.

¿Y el rendimiento? pues ninguna diferencia porque resulta que los Dtsx para manejar excel utiliza OleDb. He aquí parte de la solución con .Net y OleDB

Primeramente recordar usar este using:
 using System.Data.OleDb;

Todo el secreto esta en la conexión
   OleDbConnection cnnOle = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:Pruebas\test.xls;Extended Properties=\"EXCEL 8.0;HDR=NO;IMEX=1\";");
   cnnOle.Open();  

Aqui hay varios aspectos a tomar en cuenta:
- Primeramente el Data Source puede ser tanto una carpeta local, como en este caso, o bien una carpeta compartida o DFS (p.e. \\DFS\Pruebas\test.xls)

- Lo que vamos a hacer es una consulta SQL del Excel por lo que si en Extended Properties indicamos que HDR=YES, estamos diciendo que el primer valor de las celdas es el nombre con el que se conoceran las columas. Asi si tenemos un excel en el primer valor de cada columna, o encabezado, es PRODUCTO, CANTIDAD, PRECIO entonces podriamos hacer:
SELECT PRODUCTO, CANTIDAD, PRECIO FROM [Sheet1$]
Pero si usamos HDR=NO, usamos el nombre generico (F1, F2.,..) de las columnas, incluyendo, obviamente, el primer valor de cada columna como valores que nos devolvera la consulta

-Ademas debemos tener en cuenta que el IMEX=1 en Extended Properties significa que se tomaran los valor tal y como se FORMATEAN en las celdas, esto es muy importante porque por ejemplo si el valor de la celda es un número, supongamos 1000000 y se encuentra formateado como monto (1,000,000.00) es posible que sea mejor eliminar el tag IMEX del todo para usar el valor real de la celda en lugar del ya formateado para evitar errores de conversión de tipos.

Seguidamente hacemos la consulta:
DataTable schemaTable = cnnOle.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });

OleDbCommand cmdOle = new OleDbCommand("SELECT F1,F2,F3  FROM [" + schemaTable.Rows[0]["Table_Name"].ToString() + "]", cnnOle);

OleDbDataAdapter daOle = new OleDbDataAdapter(cmdOle);
dt = new DataTable();
daOle.Fill(dt);


La primera instrucción lo que hace es extraer en un DataTable el schema del excel para poder sacar el nombre de las hojas, esto es importante porque en el si Excel esta en español las hojas se denominan Hoja1$, Hoja2$, etc.. y si esta ingles Sheet1$, Sheet2$, etc ademas puede tener un nombre personalizado y con esta instrucción podemos desentendernos de este aspecto.

Las demás instrucciones realizan la consulta usando OleDbCommand y OleDbDataAdapter para dejar la información que necesitamos en un DataTable y a partir de que lo podemos manipular como mejor nos convenga

Gracias una vez más a Pigo Sama por su inmensa sabiduría.

18 jun 2009

Ubuntu puesta al día

Por febrero del presente año, de nuevo había escuchado el llamado...Entonces comencé con el Ubuntu 8.10 Intrepid, dejándome un grato sabor de boca.
Hoy cinco meses después toca una puesta al día de mi ubuntesca incursión. Comencemos por el cambio, Sí, cambié de 8.10 intrepid a Ultimate 2.0. ¿La razón? La desconexión.

Como no pude hacer que Ubuntu reconociera mi winmodem, pues no me podía conectar a Internet, como no me podía conectar pues las actualizaciones eran un dolor de cabeza. Navegando por Internet me encontré con el Ubuntu Ultimate Gamers Edition para ser exactos. Desinstalé mi intrepid e instalé la nueva adquisición y "voila!" TODOS los codec de vídeo (lo que más necesitaba) estaban listos y armados. Nada de andar buscando paquetes adicionales ni dependencias. Perfecto!


Después me di cuenta que mi hacía falta los necesarios para ver video rmv pero era un mal menor que puede superar rápidamente. Ahorita puedo ver todos mis capítulos de anime,escuchar mis mp3, tengo mi suite de ofimática (OpenOffice), tengo máquinas virtuales de windows montadas sobre VirtualBox para mi trabajo en .Net todas comunicándose por virual networking, instalados los drivers Nvidia, juego ocasionalmente con el gridwars o Chromium y hasta ocurrió el milagro de poder instalar mi nuevo winmodem (el anterior pasó a mejor vida) este post lo hice desde Ubuntu!

Conclusión: Aunque el cambio es algo brusco y no muy fácil, voy aprendiendo, ya se me va quitando el miedo a la terminal, aunque a veces tengo que hacer una pausa para pensar ¿que estoy haciendo? ya que no se trata de copiar y pegar en la consola si no tratar de entender que estoy haciendo. Sin embargo en términos generales estoy muy satisfecho con el Ultimate, facilita bastante esa transición, aunque aún tengo Windows XP instalado para jugar el COD Modern Warfare :-)