Archive for October, 2008

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

Tuesday, 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)

Tuesday, 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)

Tuesday, 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

Friday, 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 :-)