Un método bastante utilizado cuando desarrollamos aplicaciones web en ASP.NET es el método MapPath. Este método puede ser llamado de la siguiente manera
string path = HttpContext.Current.Server.MapPath("~");
Llamado así este método nos devuelve la ruta física de la raiz de la aplicación web. Es útil para localizar directorios y así, por ejemplo, poder abrir ficheros de configuración propia. Pero ¿qué ocurre si llamamos a este método en un delegado?. La llamada fallará porque el object HttpContext no está creado. La solución es llamar al método de la siguiente forma
string path = HostingEnvironment.MapPath()
La clase HostingEnvironment la tenemos en el espacio de nombre System.Web.Hosting, en el ensamblado System.Web.dll. Tenemos mas información de está clase en la MSDN al igual que del método MapPath.
Tags: asp.net, c#, mappath
Para poder obtener la fecha de compilacion de un ensamblado, tendremos que hacer dos cosas
1.- Modificar las líneas AssemblyVersion y AssemblyFileVersion del fichero AssemblyInfo.cs
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("0.1.*")]
[assembly: AssemblyFileVersion("0.1.1.0")]
Del AssemblyVersion obtendremos la fecha de compilación mientras que la línea AssemblyFileVersion es de donde sacamos la versión del programa (aquí se puede usar cualquier numeración). Para esto usamos el siguiente código
Assembly assembly = Assembly.GetExecutingAssembly();
FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(assembly.Location);
DateTime assemblyDate = new DateTime(2000, 1, 1)
.AddDays(assembly.GetName().Version.Build)
.AddSeconds(assembly.GetName().Version.Revision * 2);
version = string.Format("{0}.{1}.{2} del {3}",
versionInfo.ProductMajorPart,
versionInfo.ProductMinorPart,
versionInfo.ProductBuildPart,
assemblyDate.ToString("dd/MM/yyyy"));
Tags: assembly, assemblyfileversion, assemblyversion, c#
El otro día el Visual Studio me dio el siguiente error de compilación
Error 8 Could not find an implementation of the query pattern for source type
'System.Data.Linq.Table<Model.Provincia>'. 'Select' not found.
Are you missing a reference to 'System.Core.dll' or a using directive for 'System.Linq'?
La verdad es que el error es bastante raro y no deja muy claro a que se refiere. Una búsqueda por google y tras un ratillo leyendo respuestas encontré la solución. Tan sólo hay que añadir la referencia a System.Linq.
Tags: c#, linq
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í.
El código para comprimir es el siguiente
1: public static string Zip(string text)
2: {
3: byte[] buffer = Encoding.UTF8.GetBytes(text);
4: MemoryStream ms = new MemoryStream();
5: using (GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true))
6: {
7: zip.Write(buffer, 0, buffer.Length);
8: }
9:
10: ms.Position = 0;
11: MemoryStream outStream = new MemoryStream();
12:
13: byte[] compressed = new byte[ms.Length];
14: ms.Read(compressed, 0, compressed.Length);
15:
16: byte[] gzBuffer = new byte[compressed.Length + 4];
17: System.Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length);
18: System.Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4);
19: return Convert.ToBase64String(gzBuffer);
20: }
y el código para descomprimir es muy parecido
1: public static string UnZip(string compressedText)
2: {
3: byte[] gzBuffer = Convert.FromBase64String(compressedText);
4: using (MemoryStream ms = new MemoryStream())
5: {
6: int msgLength = BitConverter.ToInt32(gzBuffer, 0);
7: ms.Write(gzBuffer, 4, gzBuffer.Length - 4);
8:
9: byte[] buffer = new byte[msgLength];
10:
11: ms.Position = 0;
12: using (GZipStream zip = new GZipStream(ms, CompressionMode.Decompress))
13: {
14: zip.Read(buffer, 0, buffer.Length);
15: }
16:
17: return Encoding.UTF8.GetString(buffer);
18: }
19: }
Como vemos el código es bastante simple y nos sirve para evitar que nuestros ficheros auxiliares crezcan de manera incontrolada.
Saludos y nos vemos en la próxima entrega.
Tags: c#, comprimir, descomprimir, gzipstream
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: c#, soundplayer
En el PDC 2008 (Professional Developers Conference) de este año se están presenta muchísimas cosas. En este post hablaré de las novedades de C# 4.0. En una presentación de Anders Hejlsberg (Technical fellow en Microsoft, uno de los padres de la criatura y arquitecto principal) y tras una pequeña introducción sobre la evolución de C #, y antes de dejar encandilada a la audiencia, Anders ha realizado un pequeño repaso de las tendencias actuales en cuanto a lenguajes de programación:
- Programación más declarativa.
- Programación dinámica.
- Programación concurrente (multicore), ya que como todos sabéis, la tendencia actual (una vez que la ley de Moore podemos decir que se ha parado) es añadir más y más procesadores…¿Cómo construimos aplicaciones para este nuevo escenario en el que la concurrencia es necesaria? En plataforma .NET la respuesta la tenemos en las Parallel Extensions para .NET, que formarán parte de la nueva versión de Visual Studio (VS 2010) y de .NET Framework (4.0).
Para la programación dinámica ello, C# 4.0 tendrá una serie de características dinámicas que permitan:
- Objetos tipados de manera dinámica. La clave estará en una nueva palabra clave que aparece en escena: dynamic.
- Mejorada la interoperabilidad COM.
- Optinal and named parameters.
- Co-and Contra-Variance.
Tendremos un nuevo runtime para C# 4.0 que nos habilitará esta programación dinámica sobre la base de innovaciones ya existentes como los árboles de expresión y las expresiones lambda de C# 3.0, pero añadiendo nuevas innovaciones:
- Dynamic trees.
- Dynamic Dispatch invocer.
- Call Site Caching.
Sobre este nuevo runtime, tendremos los lenguajes de programación tradicionales de .NET, C# y VB.NET, pero también lenguajes dinámicos como IronRuby y IronPhyton, y por supuesto cualquier otro lenguaje que cumpla la correspondiente CLS (Common Language Specification). Pero además, podremos hacer desde cualquier lenguaje comentado un binding con otro de los lenguajes, es decir, podremos llamar de manera sencilla código Phyton desde C# y utilizarlo. Tendremos bindings para .NET (Object), para JavaScript (Silverlight), para Phyton, Para Ruby y otros.
Dejaré para otros post otras novedades como Visual Studio 2010, el nuevo Windows Azure o la presentación del Windows 7.
Tags: c#, novedades, pdc
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) &amp;&amp; (_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
- Comprueba que los datos del host, nombre de usuario y contraseña sean correctos.
- Tengas acceso a la red y no salgas a Internet a través de un proxy.
- Comprobar si el antivirus te está bloqueando el envio del correo. A mi con el McAfee activado no puedo enviar correos.
Saludos.
Tags: c#, email
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: c#, server, urldecode, urlencode