Jan 29 2009

C# Comprimir y descomprimir un String (GZipStream)

Category: ProgramacionIndigo @ 11:05 PM

La verdad es que hace tiempo que no escribo nada en el blog, pero es que he estado bastante liado. Una de las últimas cosas que he tenido que hacer es comprimir un xml antes de guardarlo a disco ya que este ocupaba más de 5 megas y no era cuestión de tener ese espacio ocupado “inútilmente”. Aunque visto al precio que esta el MB o el GB podría evitarme estas molestias. La primera idea sería usar un compresor externo vía línea de comandos para comprimir esa cadena de texto. Como es lógico esta opción es muy poco viable. Otra solución sería implementar nosotros mismos un algoritmo de compresión y descompresión. Esta opción sería bastante interesante si quisiéramos pasar algo de tiempo aprendiendo sobre algoritmos de compresión, pero como no es el caso, también queda descartada. Ya sólo nos queda la opción de buscar algo dentro del framework de .NET y como suele ocurrir casi siempre, el framework nos trae una clase para esta tarea. En concreto es la clase GZipStream de la cual podemos leer mas información aquí.
Continue reading “C# Comprimir y descomprimir un String (GZipStream)”

Tags: , , ,


Nov 23 2008

C# Reproducir un fichero wav (SoundPlayer)

Category: ProgramacionIndigo @ 4:54 PM

Uno de los motivos por lo que he estado tanto tiempo sin actualizar el blog es porque he estado metido en una puesta de producción dondo todo lo que ha podido ir mal, ha ido mal (siempre se cumplen la leyes de Murphy). Una de las cosas que se cambiaron a última hora, fueron unas notificaciones sonoras en muchas partes del programa. Yo tenía un código relativamente antiguo para reproducir un sonido.

[sourcecode language="csharp"]public int SND_ASYNC = 0×0001; // play asynchronously
public int SND_FILENAME = 0×00020000; // use file name
public int SND_PURGE = 0×0040; // purge non-static events

[System.Runtime.InteropServices.DllImport("WinMM.dll")]
public static extern bool PlaySound(string fname, int Mod, int flag);

private void button1_Click(object sender, EventArgs e)
{
PlaySound(”tada.wav”, 0, SND_FILENAME | SND_ASYNC);
}[/sourcecode]

Este código funciona perfectamente, pero nunca me ha gustado usar este tipo de codigo usando liberirías externas. Mirando en la MSDN encontré otra solución que me parece muchísimo mejor. Resulta que desde .NET 2.0 tenemos la clase SoundPlayer en el espacio de nombre System.Media que nos ayuda perfectamente a reproducir un sonido. El código para ésto es así de fácil

[sourcecode language="csharp"]private void button2_Click(object sender, EventArgs e)
{
System.Media.SoundPlayer soundPlayer = new System.Media.SoundPlayer();
soundPlayer.SoundLocation = “tada.wav”;
soundPlayer.Play();
}[/sourcecode]

Tenemos más información sobre esta clase en http://msdn.microsoft.com/en-us/library/system.media.soundplayer(VS.80).aspx

Tags: ,


Oct 23 2008

C# Enviar correo electronico desde .NET

Category: ProgramacionIndigo @ 10:05 AM

ara enviar un correo electrónico tenemos que usar los siguientes espacios de nombres

[sourcecode language='csharp']using System.Net;
using System.Net.Mail;[/sourcecode]

Con esto tendremos a nuestra disposición una serie de clases que nos harán la vida muy fácil para conseguir nuestro objetivo. Para enviar un correo electrónico necesitamos la siguiente información

  • Servidor smtp
  • Puerto (normalmente 25)
  • Nombre de usuario y contraseña en caso que el servidor requiera autencación.

El código es tan simple como este

[sourcecode language='csharp']try
{
SmtpClient smtpClient = new SmtpClient(”Servidor SMTP”, 25);

// Si tu servidor necesita autenticación
if ((_userName != string.Empty) && (_password != string.Empty))
{
NetworkCredential networkCredential = new NetworkCredential(”username”, “passwor”);
smtpClient.UseDefaultCredentials = false;
smtpClient.Credentials = networkCredential;
}

string body = string.Empty;
if (_isBodyHtml)
body = “Tu mensaje en html.”;
else
body = “Tu mensaje en texto plano.”;

MailMessage mailMessage = new MailMessage(”from”, “to”, “subject”, body);
mailMessage.IsBodyHtml = _isBodyHtml;

if (_sendAsync)
smtpClient.SendAsync(mailMessage, null);
else
smtpClient.Send(mailMessage);
}
catch
{
throw;
}

[/sourcecode]

  • Al principio creamos una instancia del objeto SmtpClient para lo cual necesitamos una dirección del host y el puerto de conexión.
  • Despues, es caso de que nuestro servidor requiera autenticación, creamos la credenciales que se usar al conectar con nuestro servidor de correo.
  • Despues construimos el mensaje, en base a la variable _isBodyHtml que nos dirá si el mensaje irá en texto plano o en html.
  • Posteriormente creamos el mensaje de correo, con un from (de), to (para), subject(asunto) y el mensaje.
  • Y para finalizar se envia el correo de manera síncrona o asíncrona dependiendo de _sendAsync.

Como vemos es realmente fácil. En caso que el envio te falle ten en cuenta

  1. Comprueba que los datos del host, nombre de usuario y contraseña sean correctos.
  2. Tengas acceso a la red y no salgas a Internet a través de un proxy.
  3. Comprobar si el antivirus te está bloqueando el envio del correo. A mi con el McAfee activado no puedo enviar correos.

Saludos.

Tags: ,


Oct 21 2008

C# Añadir icono RSS en la barra de direcciones de nuestro navegador (rss feed icon)

Category: ProgramacionIndigo @ 2:06 PM

Completando mi artículo anterior sobre generar RSS en nuestra pagina ASP.NET ahora veremos que tenemos que añadir nuestra página para que nuestro navegador detecte que se puede sindicar contenido rss.

Para hacer esto tan sólo debemos añadir la siguiente linea a nuestra pagina

[sourcecode language='html'] type="application/rss+xml" rel="alternate">
[/sourcecode]

Si lo quisieramos hacer desde nuestro código, lo haríamos de la siguiente manera

[sourcecode language='csharp']HtmlGenericControl link = new HtmlGenericControl(”LINK”);
link.Attributes.Add(”title”, “Ultimas artículos”);
link.Attributes.Add(”href”, “http://www.microcode.es/feed”);
link.Attributes.Add(”rel”, “alternate”);
link.Attributes.Add(”type”, “application/rss+xml”);
this.Controls.Add(link);[/sourcecode]

Como vemos es bastante fácil…

Tags: , , ,


Oct 20 2008

C# Generar RSS en nuestra pagina ASP.NET (rss feed)

Category: ProgramacionIndigo @ 2:56 PM

Según la wikipediaRSS es un sencillo formato de datos que es utilizado para redifundir contenidos a suscriptores de un sitio web. El formato permite distribuir contenido sin necesidad de un navegador, utilizando un software diseñado para leer estos contenidos RSS (agregador). A pesar de eso, es posible utilizar el mismo navegador para ver los contenidos RSS. Las últimas versiones de los principales navegadores permiten leer los RSS sin necesidad de software adicional.”

El código para generar rss es realmente sencillo y tan sólo debemos escribirlo en el Page_Load de nuestra página:

[sourcecode language='csharp']protected void Page_Load(object sender, EventArgs e)
{
Response.Clear();
Response.ContentType = “text/xml”;
XmlTextWriter xmlTextWrite = new XmlTextWriter(Response.OutputStream, Encoding.UTF8);
xmlTextWrite.WriteStartDocument();
xmlTextWrite.WriteStartElement(”rss”);
xmlTextWrite.WriteAttributeString(”version”,”2.0″);
xmlTextWrite.WriteStartElement(”channel”);
xmlTextWrite.WriteElementString(”title”, “indigo blog rss example.”);
xmlTextWrite.WriteElementString(”link”, “http://www.microcode.es/index.php”);
xmlTextWrite.WriteElementString(”description”, “Ultimas noticias.”);
xmlTextWrite.WriteElementString(”copyright”, “(c) 2008, microcode blog.”);
xmlTextWrite.WriteElementString(”ttl”, “5″);

// Este bucle es el encargado de generar los item del rss. Aquí podríamos a nuestra base de datos para obtener los elementos
// que se quieres mostrar en el rss.
for (int i = 0; i < 5; i++)
{
xmlTextWrite.WriteStartElement(”item”);
xmlTextWrite.WriteElementString(”title”, string.Format(”Title-{0}”, i));
xmlTextWrite.WriteElementString(”description”, string.Format(”Description-{0}”, i));
xmlTextWrite.WriteElementString(”link”, string.Format(”http://www.microcode.es/index.php#{0}”, i));
xmlTextWrite.WriteElementString(”pubDate”, DateTime.Now.ToString(”dd/MM/yyyy HH:mm”));
xmlTextWrite.WriteElementString(”guid”, string.Format(”http://www.microcode.es/index.php#{0}”, i));
xmlTextWrite.WriteEndElement();
}

xmlTextWrite.WriteEndElement();
xmlTextWrite.WriteEndElement();
xmlTextWrite.WriteEndDocument();
xmlTextWrite.Flush();
xmlTextWrite.Close();

Response.End();
}

[/sourcecode]

Saludos.

Tags: , ,


Oct 15 2008

VB Mostrar la fecha en otra cultura

Category: ProgramacionIndigo @ 4:16 PM

En un de los foros que visito el otro día preguntaron como mostrar una fecha en otro cultura, o sea, nuestra cultura es español (es-ES) y queremos mostrar la fecha en ingles (en-US por ejemplo). Me acordé que eso ya lo había tenido que buscar y que costó encontrar una solución, aunque después la solución fuera realmente simple. El código para hacer esto es el siguiente

[sourcecode language='csharp']Dim ci As Globalization.CultureInfo = New Globalization.CultureInfo(”en-US”)
Date.Now.ToString(”MMMM”, ci)
[/sourcecode]

Este código muestra el més en inglés (en-US)

Hay más información de este tema en la página Formatting Date and Time for a Specific Culture de la MSDN.

Tags: , , ,


Oct 14 2008

C# Codificar la url (UrlEncode y UrlDecode)

Category: ProgramacionIndigo @ 10:19 AM

Supongamos que hemos desarrollado nuestro propio sistema de blog o de noticias, y que siguiendo las normas básicas de posicionamiento hemos hecho que nuestras url sean amigables.

Si nuestra entrada en el blog fuera “este es mi primer post”, nos gustaría que la url fuera “~/post/este es mi primer post” pero esta url no es válida porque contiene espacios en blanco. Para evitar esto podemos usar los método UrlEncode y UrlDecode.

Para el caso anterior obtendríamos la dirección “~/post/este+es+mi+primer+post” que ya es una dirección valida.

Para poder utilizar los métodos UrlEncode y UrlDecode desde una aplicación windows debeís usar la clase HttpUtility que se encuentra en el espacio de nombres System.Web. En aplicaciones web, estos métodos los podeís encontrar en la clase Server.

Tags: , , ,


Oct 13 2008

C# Ejecutar un procedimiento de almacenado (store procedure)

Category: ProgramacionIndigo @ 10:20 AM

Una característica de muchos gestores de bases de datos como Sql Server, es que permiten guardar las consultas para poder ejecutarlas desde nuestro código. Asi conseguimos abstraer nuestra lógica de datos de nuestra lógica de negocio. En Sql Server estas consultas se llaman procedimientos de almacenado. Un ejemplo de esto es

[sourcecode language='sql']SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE dbo.sp_test
– Add the parameters for the stored procedure here
@IdFoo int
AS
BEGIN
SELECT
*
FROM
Foo
WHERE
IdFoo = @IdFoo
END
GO[/sourcecode]

Este procedimiento recibe como parametro el entero @IdFoo, y busca en la tabla Foo, un registro que tenga el campo IdFoo igual al parametro de entrada @IdFoo. Para llamar este procedimiento de almacenado desde nuestro código tan sólo debemos hacer lo siguiente

[sourcecode language='csharp']public void ExecuteStoreProcedure(int idFoo)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand())
{
connection.Open();

command.Connection = connection;
command.CommandType = System.Data.CommandType.StoredProcedure;
command.CommandText = “sp_test”;
command.CommandTimeout = 10;

command.Parameters.AddWithValue(”@IdFoo”, idFoo);

SqlDataReader reader = command.ExecuteReader();
}
}
}[/sourcecode]

Como vemos es muy fácil, creamos una conexión, y un comando. A este comando le decimos que ejecutará el procedimiento sp_test y le pasamos el parametro idFoo como @IdFoo. El resultado de la consulta se guarda en un SqlDataReader. Ahora podremos recorrer este SqlDataReader para devolver algún dato o pasar la información a un objeto de negocio.

La principales ventajes de los procedimientos de almacenado son

  • Evita en parte los molestos ataques por inyección sql (sql injection).
  • La velocidad de la consulta es mayor.
  • Toda la logica de acceso a datos se encuentra en la base de datos.

Tags: , ,


Oct 10 2008

C# Ejecutar consulta sql

Category: ProgramacionIndigo @ 9:41 AM

Pese a que no recomiendo escribir las consultas sql en c# para luego lanzarlas contra nuestro gestor de base de datos, en algún momento no puede ser útil, sobre todo en la primeras fase de desarrollo. Para ejecutar una consulta sql tan solo debemos hacer lo siguiente

[sourcecode language='csharp']public void ExecuteSql(int idFoo)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand())
{
connection.Open();

command.Connection = connection;
command.CommandType = System.Data.CommandType.Text;
string sql = string.Format(”SELECT * FROM Foo WHERE IdFoo = {0}”, idFoo);
command.CommandText = sql;
command.CommandTimeout = 10;

SqlDataReader reader = command.ExecuteReader();
}
}
}[/sourcecode]

Como vemos es bastante fácil.

Tags: , ,


Oct 09 2008

C# El uso de transacciones con SqlTransaction

Category: ProgramacionIndigo @ 9:34 AM

¿Qué pasa si en alguna en un procesos de actualización de datos de una base de datos falla a la mitad? Lo normal en la mayoría de los casos es deshacer todo lo que se ha hecho y dejar la base de datos como estaba. Este proceso sería muy complicado hacerlo a mano, por no decir imposible. Para esto están las transacciones, que de una manera muy fácil nos ayudan a resolver este tipo de problemas.

Esta forma de trabajar con las bases de datos, podemos hacerlo desde nuestro código o directamente en la base de datos (en procedimientos de almacenado). En este artículo sólo explicaré como hacerlo desde nuestro código.

El código para utilizar una transacción es el siguiente

[sourcecode language='csharp']public void ExecuteTransaction()
{
// Usamos la clase SqlConnectionStringBuilder para construir la cadena de conexión
SqlConnectionStringBuilder _connectionStringBuilder = new SqlConnectionStringBuilder();
_connectionStringBuilder.DataSource = @”.\SQLEXPRESS”;
_connectionStringBuilder.InitialCatalog = “prueba”;
_connectionStringBuilder.IntegratedSecurity = true;

// Creamos la conexión
using(SqlConnection _connection = new SqlConnection(_connectionStringBuilder.ConnectionString))
{
// Abrimos la conexión
_connection.Open();

// Abrimos una transación en la conexión abierta
SqlTransaction _transaction = _connection.BeginTransaction();

// Creamos el objeto SqlCommand y asignamos los datos
// a los parámetros
SqlCommand _command = new SqlCommand();
_command.Connection = _connection;
_command.CommandType = CommandType.StoredProcedure;
_command.CommandText = “ProcedimientoAlmacenado”; // Aqui va el nombre del procedimiento de almacenado

// Añadimos los parametros
_command.Parameters.AddWithValue(”@Par1″, “Par1″);
_command.Parameters.AddWithValue(”@Par2″, “Par2″);

// Asignamos la transacción al comando
_command.Transaction = _transaction;

try
{
// Ejecutamos el comando
_command.ExecuteNonQuery();

// Si todo ha ido bien hacemos un “Commit” de la transacción
_transaction.Commit();
}
catch(Exception ex)
{
// Si se produce un error, desahacemos la transaccion (Rollback)
_transaction.Rollback();
}

// No se hace falta cerrar la conexión porque está dentro de un “using”
_connection.Close();
}
}[/sourcecode]

Lo primero que hacemos es crear una cadena de conexión y abrir una conexión con ésta. Con esta conexión abierta creamos la transacción (con el método “BeginTransaction”) y ejecutamos nuestro procedimiento de almacenado. Si todo ha ido bien, hacemos un “Commit” de la transacción y si algo ha fallado hacemos un “Rollback”. Es importante hacer un ”Commit” ya que si no, el sistema hará un “Rollback” automáticamente al cerrar la conexión.

Tal y como está el código sólo estamos haciendo una llamada la base de datos, pero modificando el código ligeramente podemos ver su verdadero potencial. Supongamos que tenemos la siguiente clase

[sourcecode language='csharp']public class Article
{
public int Id = 0;
public string Content = string.Empty;
}
[/sourcecode]

Y tenemos un método que recibe una lista de artículos que tenemos que actualizar. Este método creará una transacción y la utilizará para actualizar cada artículo. El código sería como este

[sourcecode language='csharp']public void UpdateArticles(List

articles)
{
SqlTransaction _transaction = CreateTransaction();
try
{
foreach (Article article in articles)
{
UpdateArticle(_transaction, article);
}
_transaction.Commit();
}
catch
{
_transaction.Rollback();
throw;
}

}

public void UpdateArticle(SqlTransaction transaction, Article article)
{
try
{
// Creamos el objeto SqlCommand y asignamos los datos
// a los parámetros
SqlCommand _command = new SqlCommand();
_command.Connection = transaction.Connection;
_command.CommandType = CommandType.StoredProcedure;
_command.CommandText = “UpdataArticle”; // Aqui va el nombre del procedimiento de almacenado

// Añadimos los parametros
_command.Parameters.AddWithValue(”@Id”, article.Id);
_command.Parameters.AddWithValue(”@Content”, article.Content);

// Asignamos la transacción al comando
_command.Transaction = transaction;

// Ejecutamos el comando
_command.ExecuteNonQuery();
}
catch
{
throw;
}
}

public SqlTransaction CreateTransaction()
{
try
{
// Usamos la clase SqlConnectionStringBuilder para construir la cadena de conexión
SqlConnectionStringBuilder _connectionStringBuilder = new SqlConnectionStringBuilder();
_connectionStringBuilder.DataSource = @”.\SQLEXPRESS”;
_connectionStringBuilder.InitialCatalog = “prueba”;
_connectionStringBuilder.IntegratedSecurity = true;

// Creamos la conexión
SqlConnection _connection = new SqlConnection(_connectionStringBuilder.ConnectionString);

// Abrimos la conexión
_connection.Open();

// Abrimos una transación en la conexión abierta
SqlTransaction _transaction = _connection.BeginTransaction();

return _transaction;
}
catch
{
throw;
}
}[/sourcecode]

Cómo hemos visto el uso de transacciones desde .NET es muy fácil y hace nuestras aplicaciones más robustas. Pero, ¿qué pasa cuando entran en juego varias bases de datos, o incluso varios gestores de base de datos (varios Sql Server)? Para eso tenemos el TransactionScope, que podemos ver en http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspx, pero esto lo dejo para otro momento.

Tags: , , ,


« Previous PageNext Page »