Blog de tecnologia y desarrollo.

Typed DataSets y como asignar una propiedad a Null

February 24th, 2009

Los Typed Datasets son una herramienta muy util en .net. Nos permite tener DataTables, DataAdapter y DataRows con propiedades especificas a nuestro modelo de base de datos. Asi, podemos acceder a un registro, digamos asi:

EstudiantesDataRow fila= new estudiantes.NewGapsRow();

fila.Nombre = “Nombre”;

El problema es meter el valor null a un campo que lo admite, pues esto:

 fila.Nombre = DBNull.value;

Nos daria este mensaje de error:

Cannot implicitly convert type ‘System.DBNull’ to ‘String’

Y para resolver este problema, simplemente tendremos que hacer uso del metodo “setXXXNull()” que nos crea el typed DataSet. OJO: Esto solo funciona para valores que permiten null en la base de datos.

fila.SetNombreNull();

:-)

Aguas con el encoding al leer un archivo.

February 24th, 2009

Leer archivos de texto linea por linea es muy muy sencillo con .Net, con el viejo metodo ReadLine del StreamReader:

System.IO.StreamReader file = new System.IO.StreamReader(ruta);
linea = file.ReadLine()

Sin embargo, el dia de hoy me salio un problema con este método, pues tenia un archivo con el caracter à, que es escencialmente diferente del caracter á por el acento invertido. Resulto que el ReadLine me estaba truncando este caracter. Despues de un ratito de quebradero de cabeza, la solucion fue indicarle el encoding al StreamReader a la hora de abrir el archivo:

System.IO.StreamReader file = new System.IO.StreamReader(ruta,System.Text.Encoding.Default);

Definitivamente esta es una saludable práctica que incluiré a partir de hoy en mis desarrollos.∞

Usando Google Chart Api para graficas en ASP.Net

February 19th, 2009

Si son desarrolladores, seguramente han escuchado hablar de la API de Google Chart, que es basicamente una herramienta que Google nos regala como parte de su plan global para dominar al mundo, y que sirve para hacer graficas a partir de una URL con un formato especifico. Lo que basicamente significa es que esto:

http://chart.apis.google.com/chart?chl=A|B|C|E&chd=e:APAjAyBQ&chco=0000FF&cht=p3

Se puede ver como esto en nuestro sitio Web:

Es en realidad muy sencillo de usar, siempre y cuando podamos formatear correctamente los datos que querramos visualizar. Pero como normalmente no es necesario inventar la rueda, pues me di a la tarea de encontrar algun componente que me ayudara con esto. Asi que me encontre una pieza de codigo Llamada NGChart, que es basicamente una libreria que elegantemente implementa cada grafica como clase, y haciendo uso del metodo ToString() nos regresa la direccion de la grafica que queremos usar. Basicamente importando la libreria y escribiendo un codigo como el siguiente:

ChartData datosGrafica = new ChartData(datosInt);
PieChartLabels etiquetas = new PieChartLabels(TxtEtiquetas.Text.Split(’,'));
PieChart grafica = new PieChart(tipoGrafica, tamañoGrafica, datosGrafica, etiquetas);
grafica.Colors = new ChartColors(System.Drawing.Color.Blue);
Image1.ImageUrl = grafica.ToString();

Tendremos una bonita grafica en nuestra página de .Net.

Ahora mi problema es hacer que esto funcione como un web service (para que pueda interactuar con una aplicación en JSP), pero ademas, que pueda surtir las graficas a una red interna que esta detras de un proxy que no nos deja salir a Google. Es mi siguiente reto, y ya les platicare de el (si lo logro). en la siguiente entrega. ∞

Lidiando con errores de validación al renderear un control a HTML (reportes por Mail III)

October 14th, 2008

En el post anterior vimos lo facil que es hacer uso del Control.RenderControl() para exportar nuestras paginas a un formato HTML. Sin embargo, este metodo nos va a generar errores dependiendo del uso creativo que estemos empleando.

El primero es un error que ocurrirá al intentar hacer uso del metodo que ya vimos:

RegisterForEventValidation can only be called during Render()

Al parecer el problema es que estamos rendereando un control “fuera de tiempo” para ASP.Net. Para omitir este problema habra que deshabilitar la validación de los controles para esta pagina, poniendo en el encabezado la siguiente directiva:

<%@ Page Language=”C#” AutoEventWireup=”true” enableEventValidation =”false”….

Desconozco los efectos secundarios que puede tener deshabilitar la validación de eventos para la pagina, asi que recomiendo usarlo con cuidado, y en todo caso, tratar de aislar en la medida de lo posible el control a exportar.

El segundo problema viene al tratar de exportar mas de un control. Ya encarrerados, ¿por que no meter varios controles, digamos en un asp:Panel y al final renderear este ultimo?

Bueno, pues eso es precisamente lo que estaba intentado cuando me tope con este problema:

The control must be placed inside a form tag with runat=server

Al parecer, a ASP.Net no le gusta que rendereemos controles fuera de una forma. Y de esto se encarga un metodo de las formas llamado VerifyRenderingInServerForm.

La forma recomendada es simplemente sobreescribir este metodo. La forma mas sencilla y practica (aunque algo salvaje) de hacerlo, es simplemente crear nuestra propia clase que sobreescriba este metodo:

public class EmailReady : System.Web.UI.Page
{
public override void VerifyRenderingInServerForm(Control control)
{

}
}

De manera que el metodo ahora no hace nada (usese bajo su propio riesgo).

Para que esto funcione, tendremos que cambiar la herencia de la clase de nuestra pagina, de

public partial class Pagina : System.Web.UI.Page

a

public partial class Pagina : EmailReady

Y nuestro método estara funcionando sin problemas.¬¬

Exportando datos a Excel o a HTML (reportes por Mail II)

October 14th, 2008

En la antigua antiguedad, cuando queria exportar información a Excel  de una pagina Web, usaba el metodo de recorrer el control con los datos, escribir un csv en el servidor, y luego redireccionar al usuario al archivo recien creado (tenia incluso una rutina para hacer esto con GridViews, que se perdio en la base de codigo de mi antiguo trabajo). Un csv es un formato estandar que permite ser abierto en Excel, y aunque no tiene formato, pues muestra facilmente la información. Sin embargo, descubri que hay una forma mucho mas sencilla de lograr esto, con la ventaja de que podemos darle formato sin problemas.

Resulta que los controles de ASP.Net tienen la funcionalidad de poder escribirse a si mismos en formato HTML. Esto se logra con la funcion RenderControl. Esto nos da la posibilidad de ponernos creativos para exportar nuestros datos.

Si queremos que un control en particular sea descargable a Excel (que lee formato HTML) tendremos que hacer lo siguiente (lamento mucho no poder dar crédito al sitio donde encontre esta información, tiene que ser uno de estos):

Response.Clear();
Response.AddHeader(”content-disposition”, “attachment;filename=FileName.xls”);
Response.Charset = “”;

// If you want the option to open the Excel file without saving then
// comment out the line below
// Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.ContentType = “application/file.xls”;

System.IO.StringWriter stringWrite = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter htmlWrite = new HtmlTextWriter(stringWrite);
ControlAExportar.RenderControl(htmlWrite);

Response.Write(stringWrite.ToString());
Response.End();

Con un uso creativo del objeto Response, ni siquiera tenemos que guardar nuestra información como archivo en el servidor. Ahora bien, en nuestro objeto stringWrite lo unico que tenemos el HTML de nuestro control. Asi que, usando lo que aprendimos en el post anterior, nada nos impide enviar la misma información por correo en lugar de crear un archivo de Excel. Basta con omitir el uso del objeto Response del codigo mostrado.

Sin embargo, este metodo no funcionara como tal, pues el ASP.Net hace algunas validaciones que estamos violando, de manera que hay que hacer uso de un par de hacks. De estos hablare en el siguiente post.¬¬

Mandando mails con formato HTML desde ASP.Net (reportes por mail I)

October 14th, 2008

Recientemente me salio la necesidad de enviar mails con diversos tipos de datos desde una aplicación en ASP.Net, y me encontre con varios problemas interesantes para resolver, los cuales tratare en varias partes.

Primero esta el problema de mandar un correo. Por fortuna el .Net framework nos da herramientas para lograr esto de manera muy sencilla.

 MailMessage mail = new MailMessage();
mail.From = new MailAddress(Properties.Settings.Default.MailAddress);
mail.To.Add(To);
mail.CC.Add(CC);
mail.Bcc.Add(CCO);
mail.Subject = Subject;
mail.Body = Body;
SmtpClient SMTPsender = new SmtpClient(Properties.Settings.Default.MailServerAddress);
SMTPsender.UseDefaultCredentials = false;
SMTPsender.Credentials =
new System.Net.NetworkCredential(
Properties.Settings.Default.Usuario,
Properties.Settings.Default.Password,
Properties.Settings.Default.Dominio);
SMTPsender.Send(mail);

Esta solución tan sencilla nos deja enviar correo en formato de solo texto. Pero ¿que pasa si queremos darle mas formato?. Tenemos que recurrir al HTML. Para ello, solo tenemos que hacer dos cosas diferentes:

  1. Especificar que el cuerpo de nuestro correo tiene formato HTML
  2. mail.IsBodyHtml = true;

  3. Formatear la cadena que enviamos con las etiquetas correspondientes.

Pero, ¿que seria de nuestro correo con bonito formato Html si no tiene imagenes?

Para lograr imagenes dentro de un correo simplemente tenemos que usar el MIME. En nuestro codigo HTML vamos a usar la siguiente sintaxis:

<img alt=”Imageb” src=”cid:idDeLaImagen”/>

Asegurandonos que idDeLaImagen sea unica para este correo.

Posteriormente, vamos a agregar esa imagen a nuestro correo haciendo uso de los AlternateViews

//Agregamos como recurso ligado, el logo del proyecto.
LinkedResource lr = new LinkedResource([la ruta de nuestra imagen]);
lr.ContentId = “idDeLaImagen”;
//Incluimos la vista en HTML como vista del correo a enviar.
AlternateView av = AlternateView.CreateAlternateViewFromString
(body, null, System.Net.Mime.MediaTypeNames.Text.Html);
av.LinkedResources.Add(lr);
mail.AlternateViews.Add(av);

Esto nos permitira que los datos que adjuntamos se muestren como parte del correo y no como adjuntos.

Un par de aclaraciones pertinentes:

  1.  Las lineas que dicen Properties.Settings.Default… implican que esos datos los estoy obteniendo del archivo de configuración. Una forma muy util de guardar caracteristicas de nuestro sistema.
  2. Resulta que descubri que es legal usar como dirección para el SmtpClient la dirección del servidor Exchange de mi empresa. Desconozco la razon, pues se que Exchange no usa precisamente el mismo protocolo SMTP. Mi teoria es que los servidores Exchange (no se si por default) tienen ademas abierto el servicio SMTP. Por eso hago uso de las NetworkCredential, con cualquier usuario valido del dominio se puede enviar correos. Muy útil en ambientes empresariales con Exchange y ActiveDirectory.

Las siguientes partes se trataran de como enviar datos directo de una pagina web por correo, ya sea como HTML o como un archivo adjunto de Excel, y ademas, de como lograr que los metodos propuestos funcionen :-P ¬¬

El extraño caso de SQL server management studio y la pantalla azul

October 3rd, 2008

Pese a los detractores, yo soy un feliz usuario de windows XP (y estoy determinado a no usar Vista). Una de las razones es por su estabilidad. Dificilmente veo que mi equipo se congele, o peor aun, las tan populares “Blue screen of death” o BSOD. Sin embargo, desde que cambie de empleo, comenze a tener el problema de las pantallas azules cada vez que usaba el SQL Server Management Studio 2005.

En concreto, cada que habria una tabla (comando Open Table) era como jugar a la ruleta rusa. La pantalla azul aparecia, yo calculo que en uno de 3 intentos.

Intente muchas soluciones, desde actualizar, reinstalar, aplicar parches… pero nada funcionaba. Hasta que al fin, despues de husmear un poco en Google, encontre una pagina de Microsoft donde se leian las siguientes e insignificantes lineas:

 As workaround states, removing iPoint mouse driver should alleviate the problem.
But why? Why should a mouse driver cause a database management application to BSOD in the Win32 kernel ?!

Un poco incredulo, use las palabras correctas en Google, y BUM! resulto que es un problema mucho muy comun. En concreto: El software intellipoint (version 6.X.X) que sirve para controlar los apuntadores de Microsoft) al parecer tiene un bug que causa una pantalla azul al usar El SQL Server Management Studio en laptops con procesadores Intel de doble core.

No entiendo por que. Bueno, si entiendo, tiene que ver algo con el Kernell. Sin embargo me parecio una combinacion muy extraña. La bendita solucion es desinstalar Intellipoint. Sin embargo, a mi me gusta mucho mi mouse de Microsoft y la configuración de teclas que permite, de manera que no quiero desinstalarlo. Solución alterna: Mata el proceso ipoint.exe cada vez que vayas a usar el Management Studio. Un poco extraño, pero funciona :-)

Unable to find the requested .Net Framework Data Provider

February 14th, 2008

Precisamente hablando del MySql Connector para .Net, resulta que cuando quiere uno instalar la aplicacion en un servidor, puede haber un error como el que sigue:

 System.ArgumentException: Unable to find the requested .Net Framework Data Provider. It may not be installed.

Despues de romperme un poco la cabeza, descubrí el origen del problema: El MySQL provider no esta agregado a los DBProviderFactories. Normalmente esto lo hace el instalador del MySql connector, y lo hizo en mi equipo de desarrollo, pero no en el de producción.

La solución mas inmediata es, pues instalarlo en el servidor. Sin embargo, si no quieres o no estas en la posibilidad de meterle mano al servidor, puedes agregar lo siguiente a tu web.config:

<system.data>
<DbProviderFactories>
<add name=”MySQL Data Provider” invariant=”MySql.Data.MySqlClient” description=”.Net Framework Data Provider for MySQL” type=”MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=5.1.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d” />
</DbProviderFactories>
</system.data>

Cuidando unicamente de que la version sea la que corresponda a la de nuestro connector.

También, no esta de mas checar que la dll de MySql.Data vaya en la carpeta bin ;-)

Conectar el .Net framework con MySql (con total soporte para ADO)

February 14th, 2008

Recientemente me salio la necesidad de manipular algunos datos a una base de MySql en lugar del ya tradicional SQL Server. Mi primera opcion fue hacer mi desarrollo en PHP. Pero luego se me ocurrio buscar una forma limpia de conectar el ASP.Net con MySQL. Afortunadamente, si la hay. El MySql Connector/Net

La mas nueva version (5.1), ya esta perfectamente integrada con el Visual Studio 2005. Y manipular las bases de datos exactamente de la misma manera que ya estamos acostumbrados. Les recomiendo que lo prueben!

Un bonito y util ejercicio

December 12th, 2007

En días pasados, y por la época, me salio la necesidad de organizar un intercambio (si, esos en que se reúnen un grupo de amigos y/o conocidos y se intercambian regalos entre ellos). Como tenia la necesidad de que fuera secreto, decidí que la mejor solución (y la mas Geek), sería crear un programita que hiciera el sorteo por mi, y enviara correo a los interesados sin que yo me enterara de quien le dará a quien. El programita me represento algunos retos pequeños pero divertidos. Quiza lo mas divertido de aprender fue como funciona la clase Random y como podemos mandar Mails usando el SMTP de GMail.

No suena a demasiado dificil hacer un sorteo de intercambio programaticamente. Y en realidad, lo es. Solo que el generador de numeros aleatorios del .Net Framework no es realmente aleatorio. Veran.

Para usarlo empleamos una sentencia mas o menos asi:
Random rnd = new Random(int base)
Donde base es el limite superior para los aleatorios. Para generar un numero aleatorio de una serie (ojo, dije serie) usamos
rnd.Next();
El asunto esta en que, si siempre le damos la misma base, siempre obtendremos los mismos resultados. No podemos crear un objeto Random cada que lo queramos usar, tenemos que usar uno solo y dejar que solito “randomize” la serie. Despues de algunas aproximaciones, lo que termine por hacer es darle una base de los milisegundos de la hora.
Random rnd = new Random(DateTime.Now.Millisecond)
Y como necesitaba que los numeros aleatorios estuvieran dentro de un rango (el tamaño de la lista de participantes), simplemente use el modulo:
rnd.Next() % elQueDa.Count //elQueDa es un ArrayList con mi lista de participantes.
Una vez solucionado ese asunto, tenia que hacer que enviara los mails a los participantes. Para ello, use la bendita clase SmtpClient del framework. En realidad es muy facil de usar. Mi codigo se explica solo:
System.Net.NetworkCredential credential = new System.Net.NetworkCredential
(Properties.Settings.Default.SmtpUserName,Password);
SmtpClient senderClient = new SmtpClient(Properties.Settings.
Default.SmtpAddress,Convert.ToInt32(Properties.Settings.Default.SmtpPort));
senderClient.EnableSsl = Properties.Settings.Default.SmtpEnableSsl;
senderClient.UseDefaultCredentials = false;
senderClient.Credentials = credential;

MailMessage Mail = new MailMessage();
Mail.From = new MailAddress(Properties.Settings.Default.MailFromAddress);
Mail.Subject = Properties.Settings.Default.MailSubject;
senderClient.Send(Mail)
Unicamente hay que preocuparse de cachar las excepciones adecuadas. Por si les paso de noche, Properties.Settings.Default es la forma de acceder a las propiedades guardadas en el archivo de configuracion, asi que no busquen en la documentacion propiedades como SmtpEnableSsl por que yo las di de alta asi en los Settings.

Hay que recordar que GMail trabaja con SSL. Para ello la linea de
senderClient.EnableSsl = Properties.Settings.Default.SmtpEnableSsl;
Y tambien que hay que configurar el puerto (465 o 587, si uno da TimeOut, intentas con el otro).

Y ya, la verdad es que es muy facil hacer este tipo de cosas con el .Net Framework. Si le quieren echar un ojo, aqui encuentran el codigo. Y si les interesa descargarlo para su uso, pueden entrar a esta pagina (hacemos uso de las ventajas del Click Once Deployent). No me esforce demasiado en las validaciones, asi que asegurense de meter bien los datos.