Buscar este blog

miércoles, 27 de octubre de 2010

Comprimir Web Services

Llamar un web service de manera que la respuesta nos llegue comprimida es muy sencillo pero de entrada nos podemos tardar un poco en encontrar la forma de hacerlo de hacerlo por eso publico esta entrada.
Es muy sencillo solo tenemos que poner la propiedad EnableDecompression de nuestra instancia cliente a verdadero y listo tendremos nuestro web service comprimido (siempre y cuando la compresión este habilitada en IIS por supuesto).

WSInstance client = WSClient.Client();
client.EnableDecompression = true;

viernes, 10 de septiembre de 2010

Añadiendo controles a un control de usuario heredado de otro control de usuario

Este problema me tuvo parado un rato.
Usando visual studio tenemos un control de usuario al que le añadimos un contenedor, por ejemplo un panel, hacemos otro control de usuario que hereda del primero y tratamos de añadir controles en el área libre del panel anterior visual studio no lo permite.
La solución es simple pero no muy intuitiva solo debemos marcar como publico o protegido el panel que añadimos en el control base, esto se hace en la ventana de propiedades del panel en la sección que dice diseño.

domingo, 18 de abril de 2010

Threads en Windows.Forms usando el componente BackgroudWorker

Usar threads en Windows.Forms se simplifica mucho usando el componente BackgroundWorker que nos permite llevar a cabo una tarea en el fondo sin preocuparnos de tareas como la administración del thread o el acceso a controles desde un thread diferente al del form.
Les presento este pequeño tutorial que nos presenta una tarea muy sencilla que llevaremos a cabo en un trhread.

Primero que nada crearemos el formulario añadiendo los siguientes componentes:

Un NumericUpdown llamado hasta
un botón llamado inicio
un botón llamado fin
un BackgroundWorker llamado thread, con las propiedades SupportCancellation y ReportProgress en verdadero
una ProgressBar llamado progreso
una etiqueta llamada status

El formulario se vera como en la imagen:



Lo primero que hacemos es añadir el código para comenzar la tarea como no deseamos que el usuario pueda cambiar los parámetros del mismo mientras se ejecuta deshabilitaremos los controles adecuados, también noten que pasamos un parámetro al proceso esto es necesario ya que en el thread no podemos accesar los controles del formulario o tendremos un error:

private void inicio_Click(object sender, EventArgs e) {
            inicio.Enabled = false;
            fin.Enabled = true;
            hasta.Enabled = false;
            thread.RunWorkerAsync(hasta.Value);
        }

Podemos cancelar el proceso en cualquier momento usando el método CancelAsync del BackwroundWorker:

private void fin_Click(object sender, EventArgs e) {
            thread.CancelAsync();
        }

El proceso simplemente desde cero hasta el número del NumericDown que recuperamos desde el argumento que pasamos al proceso, nos dentendremos un segundo entre cada número.
Para cancelar el proceso debemos verificar constantemente la propiedad CancelationPending cuando esta sea verdadera detendremos la cuenta.
Para reportar el progreso usamos el método ReportProgress que acepta un porcentaje entero y un argumento de tipo object en el que podemos incluir otra información relevante al progreso:

private void thread_DoWork(object sender, DoWorkEventArgs e) {
            decimal total = (decimal)e.Argument;
            for(decimal i = 0; i < total; i++) {
                if(thread.CancellationPending)
                    break;
                System.Threading.Thread.Sleep(1000);
                int porcentaje = (int)((i / total) * 100);
                thread.ReportProgress(porcentaje, porcentaje.ToString() + "%");
            }
        }
Para reportar el progreso usamos el evento ProgressChanged, noten el uso del argumento pasado anteriormente:

private void thread_ProgressChanged(object sender, ProgressChangedEventArgs e) {
            progreso.Value = e.ProgressPercentage;
            status.Text = (string)e.UserState;
        }

Cuando se termina el proceso podemos rehabilitar los controles y agregar directamente una notificación:

private void thread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
            inicio.Enabled = true;
            fin.Enabled = false;
            hasta.Enabled = true;
            status.Text += " Terminado";
        }

Finalmente igual que deshabilitamos los controles durante el proceso nos aseguramos que no se cierre la ventana durante el mismo:

private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
            if(thread.IsBusy) {
                MessageBox.Show("Deten el proceso antes de salir");
                e.Cancel = true;
            }
        }

A continuación esta el código completo:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ProbadorW {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }

        private void inicio_Click(object sender, EventArgs e) {
            inicio.Enabled = false;
            fin.Enabled = true;
            hasta.Enabled = false;
            thread.RunWorkerAsync(hasta.Value);
        }
        private void fin_Click(object sender, EventArgs e) {
            thread.CancelAsync();
        }
        private void thread_DoWork(object sender, DoWorkEventArgs e) {
            decimal total = (decimal)e.Argument;
            for(decimal i = 0; i < total; i++) {
                if(thread.CancellationPending)
                    break;
                System.Threading.Thread.Sleep(1000);
                int porcentaje = (int)((i / total) * 100);
                thread.ReportProgress(porcentaje, porcentaje.ToString() + "%");
            }
        }
        private void thread_ProgressChanged(object sender, ProgressChangedEventArgs e) {
            progreso.Value = e.ProgressPercentage;
            status.Text = (string)e.UserState;
        }
        private void thread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
            inicio.Enabled = true;
            fin.Enabled = false;
            hasta.Enabled = true;
            status.Text += " Terminado";
        }
        private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
            if(thread.IsBusy) {
                MessageBox.Show("Deten el proceso antes de salir");
                e.Cancel = true;
            }
        }
    }
}

Formateando codigo para Internet

Aquí les dejo la dirección de la página que uso para formatear el código que presento en este blog tiene un resultado muy vistoso y soporta varios lenguajes:

http://www.manoli.net/csharpformat/

Tamaño de la pantalla con Windows.Forms

Medir el tamaño de la pantalla con .Net es muy sencillo.
Para esto tenemos la clase Screen que nos provee de métodos para encontrar las dimensiones ya sea el tamaño total o del área de trabajo que hay que notar que no incluye el área ocupada por la barra de tareas, aquí esta el ejemplo:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace ProbadorConsola {
    class Program {
        static void Main(string[] args) {
            Rectangle wArea = Screen.GetWorkingArea(new Point(1, 1));
            Rectangle bounds = Screen.GetBounds(new Point(1, 1));
            Console.WriteLine("Area de trabajo "
                + "Superior: {0}, Izquierda: {1}, Alto: {2}, Abajo: {3}, "
                + "Ancho: {4} Derecha {5}",
                wArea.Top, wArea.Left, wArea.Height, wArea.Bottom, wArea.Width
                , wArea.Right);
            Console.WriteLine("Total "
                + "Superior: {0}, Izquierda: {1}, Alto: {2}, Abajo: {3}, "
                + "Ancho: {4} Derecha {5}",
                bounds.Top, bounds.Left, bounds.Height, bounds.Bottom,
                bounds.Width, bounds.Right);
            Console.ReadLine();
        }
    }
}

La salida es esta:
Area de trabajo Superior: 0, Izquierda: 249, Alto: 900, Abajo: 900, Ancho: 2631 Derecha 2880
Total Superior: 0, Izquierda: 0, Alto: 900, Abajo: 900, Ancho: 2880 Derecha 2880

miércoles, 31 de marzo de 2010

Parseando html con HtmlAgilityPack

Con la librería HtmlAgilityPack para .Net es muy sencillo cargar archivos de html y manejar sus objetos programáticamente. Es cierto que también se puede hacer con la clase HtmlDocument de las librerías base de .Net, pero esta clase tiene como ventaja que no necesita una ventana para funcionar por lo que puede usarse en una dll o un ejecutable de consola, además puedes bajar solo lo que necesitas y no el documento con todas sus imágenes y scripts.
Para usarla declaramos una variable de la clase y usamos el método LoadHtml para cargar el documento, el argumento debe ser una cadena conteniendo el html, de momento no se pueden cargar documentos directamente:

HtmlAgilityPack.HtmlDocument doc
                = new HtmlAgilityPack.HtmlDocument();
            doc.LoadHtml(htmlstring);

Una vez que tenemos cargado el html podemos usar sus objetos programáticamente, para encontrar el nodo base del documento (que podria ser html), tenemos la propiedad DocumentNode:

doc.DocumentNode

Para buscar un nodo especifico a partir de otro nodo tenemos el método SelectNodes que toma como argumento una cadena con una expresión de XPath, por ejemplo para encontrar una tabla con ancho de 100%:

doc.DocumentNode.SelectNodes("//table[@width='100%']")[0]

Nótese que tomamos el primer elemento, ya que el método obtiene una colección con todos los elementos que cumplen la condición, alternativamente el método SelectSingleNode que obtiene solo el primer elemento.
Para obtener un elemento en particular de un nodo también podemos usar la colección ChildNodes del nodo la cual contiene todos los elementos directos del nodo:


doc.DocumentNode.SelectNodes("//table[@width='100%']")[0].ChildNodes[1]

En conclusión HtmlAgilityPack es una herramienta muy robusta y útil para lidiar con html, acepta html con errores y nos permite manejarlo de manera similar a Xml.

domingo, 21 de marzo de 2010

Propiedades automaticas

Una característica muy útil de C# es que nos permite declarar propiedades de clase casi sin escribir código simplemente escribimos el tipo de datos y el nombre de la propiedad y listo, si queremos que la  propiedad sea de solo lectura o solo escritura solo se pone como privado el accesor apropiado.
Es muy útil para declarar clases que solo almacenan datos.
Aquí esta el ejemplo:

public class Ejemplo {
        public string Prop1 {
            get;
            set;
        }
        public string Prop2 {
            get;
            private set;
        }
    }

martes, 9 de marzo de 2010

Accesando a un renglon o columna de un TableLayoutPanel

Es muy sencillo acceder a una columna o renglón específicos de un TableLayoutPanel simplemente se accede a ellos por la propiedad RowStyles o ColumnStyles, ambas son colecciones de columnas o renglones.

Por ejemplo para ocultar un renglón:

table.RowStyles[0].Height = 0;

lunes, 8 de marzo de 2010

Obteniendo el tamaño más apropiado para un Label

Los controles label de Windows.Forms tienen un método muy para determinar el tamaño que necesita el control para dibujarse, el método es GetPreferredSize, el método nos devuelve un objeto Size con el ancho y alto adecuados para el control.

Aquí les dejo el ejemplo:

label1.GetPreferredSize(new Size(0, 0));

sábado, 6 de marzo de 2010

Medir el ancho en pantalla de una cadena

Este pequeño truco nos da el ancho en pantalla de una cadena según se vería en un determinado control:

Graphics.FromHwnd(Control1.Hwnd).MeasureString(string1, Control1.Font);

viernes, 5 de marzo de 2010

Pruebas unitarias con Visual Studio

Desde Visual Studio 2005 en algunas versiones tenemos la opción de crear proyectos de pruebas unitarias, para crear un proyecto de este tipo vamos al menú archivo -> Add -> New Project y en el dialogo de nuevo proyecto seleccionamos Test Project como se ve en la imagen:

 
 

Una vez creado el proyecto nos crea una clase de prueba unitaria como ejemplo para usarla añadimos una referencia al proyecto que queremos probar en el que por ejemplo tenemos la siguiente clase:

public class Prueba {
        public int PruebaMiembro {
            get { return 1; }
        }
    }

Para probarla añadimos el siguiente código a la clase demostrativa que creo Visual Studio:

[TestMethod]
    public void TestMethod1() {
        Prueba p = new Prueba();
        Assert.AreEqual(1, p.PruebaMiembro);
    }

y listo.
Podemos correr las pruebas que tengamos, en modo normal o de depuración, y ver los resultados desde el menú de pruebas o desde el panel vista de pruebas (Test View) desde el cual podemos seleccionar solo algunas pruebas o todas como se muestra en la siguiente imagen:


Los resultados se muestran en el panel de resultado de pruebas podemos dar doble click y ver los detalles de la ejecución incluyendo la posición en el código en que fallo en caso de que esto ocurra y si ejecutamos en modo de depuración podemos establecer puntos de ruptura en los que se detiene la ejecución y podemos depurar normalmente.


Para aprender más acerca de las pruebas unitarias con .Net Framework visita:
Lista de artículos acerca de pruebas unitarias con .Net Framework

jueves, 4 de marzo de 2010

Elementos html de servidor

Como sabemos es posible usar cualquier elemento html en asp.net como un control de servidor añadiendo el atributo runat="server" en la etiqueta del control.
Lo que quizá no todos sabemos es que se puede utilizar el atributo InnerText en cualquier elemento de html al que convirtamos en control de servidor, aún cuando intelisense no nos marque el atributo como válido.
De esta forma podemos modificar el contenido del control programaticamente  o usando expresiones.
Aquí esta el ejemplo:

<h1 runat="server" InnerText="<%$ Resources:Labels, Ejemplo %>" />

miércoles, 3 de marzo de 2010

Deteccion de dispositivos mobiles en Asp.Net con libreria de www.51degrees.mobi

Hace unos días que estoy trabajando en la detección de dispositivos móviles con el api que se encuentra disponible en: http://www.51degrees.mobi/Products/NETMobileAPI.
El objetivo es mandar a tus visitas de dispositivos limitados a una pagina diseñada para las características  de un dispositivo reducido.
A primera vista estas librerías se ven muy buenas: son fáciles de usar y ofrecen un soporte muy amplio.
Sin embargo a la hora de ponerlas en producción fallan rotundamente frecuentemente detectan Internet Explorer 6 como móvil y mas frecuentemente ocurre lo mismo con Safari.
Como conclusión en Marzo de 2010 esta api no tiene la robustez necesaria para hacer el trabajo que propone, espero que este articulo le ahorre tiempo a quien este evaluando una api de estas características.

martes, 2 de marzo de 2010

Cómo terminar la sesión de un usuario del Membership provider de asp.net

Para terminar la sesión de un usuario logueado mediante el Membership provider de asp.net, utiliza el siguiente código:

       FormsAuthentication.SignOut()
       Response.Redirect(FormsAuthentication.LoginUrl)


La segunda línea simplemente redirige a la página establecida como inicio de sesión en el archivo web.config de la aplicación.
Otra manera simple de hacerlo es simplemente colocar el tag LoginStatus que automáticamente añade un vínculo para cerrar la sesión.

domingo, 28 de febrero de 2010

Linea de guía en Visual Studio

Una linea guia es una linea vertical en el editor de texto de cualquier lenguaje que sirve para que marques un limite de columnas de texto del que no te quieres pasar, si te pasas de la linea puedes presionar enter y comenzar una linea nueva como se ve en la imagen:

Linea guia

Para obtener esto en Visual Studio 2003 en adelante se debe abrir el registro de windows con regedit y llegar a la siguiente clave HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\Text Editor y añadir una nueva clave de tipo cadena llamada Guides con el valor RGB (256,0,0), 80.

La primera parte indica el color (en rgb) y la segunda parte indica la columna en que se vera la linea.

Estos son las claves del registro donde se deben poner las guias en diferentes versiones de Visual Studio:

2003: HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\7.1\Text Editor

2005: HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\8.0\Text Editor

2008: HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\Text Editor

2008 Express: HKEY_CURRENT_USER\Software\Microsoft\VCExpress\9.0\Text Editor

Al parecer también funciona en SQL Server 2005 y otras versiones

Desde Visual Studio 2010 hay un complemento que permite obtener estas guias sin modificar el registro:
Productivity Power Tools
Solo pones el cursor en la columna donde quieres la guia das click derecho y escoges Add Guideline.

viernes, 26 de febrero de 2010

Como funciona el DataPager

El control DataPager nos permite añadir paginación a controles que muestran conjuntos de datos, sin embargo para que el control DataPager funcione con un control este debe implementar la interfaz IPageableItemContainer y hasta el .Net framework 3.5 el único control que implementa esta interfaz es el control ListView, por lo tanto es el único control con el que funcionara el DataPager sin modificaciones.
Para usar un DataPager con un ListView se puede usar ya sea dentro del mismo o control o colocándolo después e indicando cual es el control que se va a paginar.
Es muy sencillo a continuación se muestran los dos ejemplos:
Para usar el control dentro del ListView en que lo vamos a usar (se pone el DataPager en el LayoutTemplate:
<asp:ListView ID="ListView1" runat="server" DataSourceID="companyDS" 
            onitemcreated="ListView1_ItemCreated" >
        <LayoutTemplate>        
            <table runat="server" cellspacing="0" border="1" style="border-collapse:collapse;">
                <tr>
                    <th runat="server"><asp:Literal ID="Literal1" runat="server"
                        Text="<%$ Resources:Labels, CompanyName %>" />
                    </th>
                    <th runat="server"><asp:Literal ID="Literal2" runat="server"
                        Text="<%$ Resources:Labels, State %>" />
                    </th>
                    <th runat="server"><asp:Literal ID="Literal3" runat="server"
                        Text="<%$ Resources:Labels, Industry %>" />
                    </th>
                </tr>
                <tr runat="server" id="itemPlaceholder" />
            </table>
        <asp:DataPager ID="DataPager1" runat="server" QueryStringField="pageNumber"
            PageSize="20">
            <Fields>
                <asp:NextPreviousPagerField ButtonType="Link"
                    FirstPageText="<%$ Resources:Labels, First %>" 
                    LastPageText="<%$ Resources:Labels, Last %>"
                    NextPageText="<%$ Resources:Labels, Next %>"
                    PreviousPageText="<%$ Resources:Labels, Previous %>" 
                    ShowFirstPageButton="True" ShowNextPageButton="False" 
                    ShowPreviousPageButton="False" />
                <asp:NumericPagerField />
                <asp:NextPreviousPagerField ButtonType="Link"
                    FirstPageText="<%$ Resources:Labels, First %>" 
                    LastPageText="<%$ Resources:Labels, Last %>"
                    NextPageText="<%$ Resources:Labels, Next %>"
                    PreviousPageText="<%$ Resources:Labels, Previous %>" 
                    ShowLastPageButton="True" ShowNextPageButton="False" 
                    ShowPreviousPageButton="False" />
            </Fields>
        </asp:DataPager>
        </LayoutTemplate>
        <ItemTemplate>
            <tr runat="server">
                <td>
                    <asp:HyperLink ID="nameOutput" runat="server"
                        Text='<%# Bind("Name") %>'
                        NavigateUrl='<%# "Company.aspx?CompanyName=" + Server.UrlEncode((String)Eval("Name")) %>' />
                </td>
                <td>
                    <asp:Label ID="Label2" runat="server"
                        Text='<%# Bind("State") %>' />
                </td>
                <td>
                    <asp:Label ID="Label3" runat="server"
                        Text='<%# Bind("Industry") %>' />
                </td>
            </tr>
        </ItemTemplate>
    </asp:ListView>

O con el DataPager fuera del control, solo indicamos el control a paginar con el atributo PagedControlID:
<asp:ListView ID="ListView1" runat="server" DataSourceID="companyDS" OnItemCreated="ListView1_ItemCreated">
        <LayoutTemplate>
            <table runat="server" cellspacing="0" border="1" style="border-collapse: collapse;">
                <tr>
                    <th runat="server">
                        <asp:Literal ID="Literal1" runat="server" Text="<%$ Resources:Labels, CompanyName %>" />
                    </th>
                    <th runat="server">
                        <asp:Literal ID="Literal2" runat="server" Text="<%$ Resources:Labels, State %>" />
                    </th>
                    <th runat="server">
                        <asp:Literal ID="Literal3" runat="server" Text="<%$ Resources:Labels, Industry %>" />
                    </th>
                </tr>
                <tr runat="server" id="itemPlaceholder" />
            </table>
        </LayoutTemplate>
        <ItemTemplate>
            <tr runat="server">
                <td>
                    <asp:HyperLink ID="nameOutput" runat="server" Text='<%# Bind("Name") %>' NavigateUrl='<%# "Company.aspx?CompanyName=" + Server.UrlEncode((String)Eval("Name")) %>' />
                </td>
                <td>
                    <asp:Label ID="Label2" runat="server" Text='<%# Bind("State") %>' />
                </td>
                <td>
                    <asp:Label ID="Label3" runat="server" Text='<%# Bind("Industry") %>' />
                </td>
            </tr>
        </ItemTemplate>
    </asp:ListView>
    <asp:DataPager ID="DataPager1" runat="server" QueryStringField="pageNumber" PageSize="20"
        PagedControlID="ListView1">
        <Fields>
            <asp:NextPreviousPagerField ButtonType="Link" FirstPageText="<%$ Resources:Labels, First %>"
                LastPageText="<%$ Resources:Labels, Last %>" NextPageText="<%$ Resources:Labels, Next %>"
                PreviousPageText="<%$ Resources:Labels, Previous %>" ShowFirstPageButton="True"
                ShowNextPageButton="False" ShowPreviousPageButton="False" />
            <asp:NumericPagerField />
            <asp:NextPreviousPagerField ButtonType="Link" FirstPageText="<%$ Resources:Labels, First %>"
                LastPageText="<%$ Resources:Labels, Last %>" NextPageText="<%$ Resources:Labels, Next %>"
                PreviousPageText="<%$ Resources:Labels, Previous %>" ShowLastPageButton="True"
                ShowNextPageButton="False" ShowPreviousPageButton="False" />
        </Fields>
    </asp:DataPager>

Nótese el uso de la propiedad QueryStringField si no se usa los botones del paginador usan postbacks y con la propiedad establecida se usan links normales la diferencia es muy importante si se se esta optimizando para buscadores (que por lo general) no siguen los postbacks pero en una aplicación privada no es necesaria esa optimización.
También en los ejemplos vemos que se puede cambiar la apariencia y funcionamiento del DataPager con los controles Field que se colocan en el Template Fields, en el ejemplo se muestran Fields para un paginador numérico  y controles de página anterior y siguiente a los lados, si quisiéramos solo el paginador numérico por ejemplo solo usaríamos el Field NumericPagerField.
Hay que notar que el DataPager al utilizarse dentro del ListView prácticamente no se puede modificar gráficamente después de crearlo por lo que lo mejor es modificarlo a mano en el html de la pagina.

Para aprender más sobre el control DataPager busca en la lista de artículos sobre el control DataPager en este blog.

jueves, 25 de febrero de 2010

Optimizando Asp.Net con la eliminación del ViewState

En Asp.Net las páginas usan el ViewState como una forma de mantener el estado entre postbacks, sin embargo el ViewState se manda junto con la página usando un campo de tipo input hidden y suele ser de un tamaño considerable.
Una buena técnica para reducir el tamaño de la página generada por Asp.Net es eliminar el ViewState de los controles siempre que se pueda, esto es posible con las siguientes condiciones entre otras:
1.- La página no generara postbacks, se puede eliminar el ViewState de la página por completo.
2.- El contenido de un control se carga desde una base de datos y se puede eliminar el ViewState del control.

Una forma sencilla de comprobar si necesitamos el ViewState es eliminarlo de la página y ver cómo se comporta la página sin el mismo, si algo no funciona bien lo reactivamos en la página y lo vamos desactivando en los controles individuales (contenedores primero) hasta tener el resultado esperado.

Se puede eliminar el ViewState declarativamente o prográmaticamente por medio del atributo booleano EnableViewState o la propiedad booleana también EnableViewstate aquí vemos como quitar el ViewState de la página por completo lo que incluye todos los controles en ella y como quitarlo de un solo control:

ASP:

   1:  <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="PruebaW._Default" EnableViewState="false" %>
   2:   
   3:  <asp:Label ID="Label1" runat="server" EnableViewState="false" Text="hola" />
C#


   1:  EnableViewState = false;
   2:  Label1.EnableViewState = false;

Es de notarse que los controles aparte del ViewState tienen el ControlState el cual se almacena el mismo Input que el ViewState y no se puede eliminar por lo que nunca podremos eliminar el ViewState por completo pero si podemos reducirlo en forma bastante significativa.

miércoles, 24 de febrero de 2010

Cómo leer un ConnectionString del web.config mediante código

Existen varias maneras de guardar y usar cadenas de conexión en el web.config aquí mencionare las que conozco, si conocen otras no duden en enviarlas para incluirlas.

La primera es la más recomendada para aplicaciones sencillas ya que es la que proporciona el mismo Asp.Net para guardar las cadenas de conexión, se guarda la cadena en la sección connectionStrings del web.config, esta sección va directo en la sección configuration que es la raíz del web.config.


   1:  <connectionStrings>
   2:      <add connectionString="Data Source=Servidor\INSTANCIASQL;Initial Catalog=MiBaseDeDatos;Persist Security Info=True;User ID=NombreDeusuario;Password=xxxxxxxxxx" name="MiConnectionString" providerName="System.Data.SqlClient"/>
   3:  </connectionStrings>

y se usa de la siguiente manera:


   1:  string SuperSecreto = System.Web.Configuration.WebConfigurationManager.ConnectionStrings["MiConnectionString"].ConnectionString;

También podemos usar la sección appSettings, pero no es tan recomendado pues esta sección esta reservada para configuraciones sin categorizar, en realidad es cuestión de gusto:


   1:  <appSettings>
   2:      <add key="ConnectionString"
   3:                   value="Data Source=Servidor\INSTANCIASQL;Initial Catalog=MiBaseDeDatos;Persist Security Info=True;User ID=NombreDeusuario;Password=xxxxxxxxxx"/>
   4:  </appSettings>

La ultima forma es creando secciones de configuración personalizadas, esta es mas recomendable cuando creamos una ddl reutilizable que queremos configurar desde el web.config o el app.config y usamos esa dll desde nuestra aplicación web.
En esta entrada solo mostrare como se ve esta opción en el web.config y no mostrare su uso y creación ya que es mas complicada y prefiero mostrar el ejemplo completo en otra entrada.
Así se usa en el web.config, añadimos un sectionGroup en la seccion configSections del web.config y en la seccion configuration añadimos la sección que acabamos de configurar:


   1:  <configSections>
   2:      <sectionGroup name="miaplicacion">
   3:          <section name="connectionStrings" type="MiAplicacion.ConnectionStringsSection" allowLocation="true" allowDefinition="Everywhere"/>
   4:      </sectionGroup>
   5:  </configSections>
   6:  <miaplicacion>
   7:      <connectionStrings
   8:          ConnectionString="Data Source=Servidor\INSTANCIASQL;Initial Catalog=MiBaseDeDatos;Persist Security Info=True;User ID=NombreDeusuario;Password=xxxxxxxxxx">
   9:      </connectionStrings>
  10:  </miaplicacion>

martes, 23 de febrero de 2010

Obtener el nombre de un elemento de Enum

Aquí les dejo un truco rápido para obtener una cadena con el nombre de un elemento de un Enum:

   1:  class Program {
   2:      enum PruebaEnum {
   3:          Enum1,
   4:          Enum2
   5:      }
   6:      static void Main(string[] args) {
   7:          string enumName = Enum.GetName(typeof(PruebaEnum), PruebaEnum.Enum2);
   8:          Console.WriteLine("Nombre de elemento de Enum: {0}", enumName);
   9:          Console.ReadLine();
  10:      }
  11:  }

La clase Enum también tiene otros métodos muy prácticos: obtener todos los nombres del enum, leer un enum desde una cadena obtener todos los miembros del enum en un arreglo.
Aquí esta el ejemplo completo:

   1:  class Program {
   2:      enum PruebaEnum {
   3:          Enum1,
   4:          Enum2
   5:      }
   6:      static void Main(string[] args) {
   7:          string enumName = Enum.GetName(typeof(PruebaEnum), PruebaEnum.Enum2);
   8:          Console.WriteLine("Nombre de elemento de Enum: {0}", enumName);
   9:          PruebaEnum parsed = (PruebaEnum)Enum.Parse(typeof(PruebaEnum), enumName);
  10:          string[] names = Enum.GetNames(typeof(PruebaEnum));
  11:          Console.WriteLine("Todos los elementos del Enum");
  12:          foreach(string i in names) {
  13:              Console.WriteLine(i);
  14:          }
  15:          Console.WriteLine("Desde GetValues");
  16:          Array enums = Enum.GetValues(typeof(PruebaEnum));
  17:          for(int i = 0; i < enums.Length; i++) {
  18:              Console.WriteLine("Valor {0}", Enum.GetName(typeof(PruebaEnum)
  19:                  , (PruebaEnum)enums.GetValue(i)));
  20:          }
  21:          Console.ReadLine();
  22:      }
  23:  }

lunes, 22 de febrero de 2010

Leyendo y Escribiendo XML con Linq en c#

En este ejemplo uso Linq para crear XML desde un árbol de objetos y después poder leer de nuevo el XML con Linq y crear de nuevo los objetos.
Por supuesto para correr los ejemplos hay que crear los tipos de datos necesarios, todas las colecciones son de tipo List<>
Escribir (Linq a XML):


   1:  List<Pelicula> peliculas = new PeliculaTA().Retrieve();
   2:  var xmlArch =
   3:      new XElement("Peliculas",
   4:      from m in peliculas
   5:      select new XElement("Pelicula",
   6:          new XElement("Titulo", m.Titulo),
   7:          new XElement("Director", m.Director),
   8:          new XElement("Estrenado", m.Estrenado),
   9:          new XElement("Actores",
  10:              from a in m.Actores
  11:              select new XElement("Actor",
  12:                  new XElement("Nombre", a.Nombre),
  13:                  new XElement("Nacimiento", a.Nacimiento),
  14:                  new XElement("Roles",
  15:                      from r in a.Roles
  16:                      select new XElement("Rol",
  17:                          new XElement("NombrePelicula", r.Pelicula),
  18:                          new XElement("NombreRol", r.NombreRol)))))));
  19:  File.WriteAllText("peliculas.xml", xmlArch.ToString());

Leer (XML a Linq):


   1:  XElement xmlArch = XElement.Load("peliculas.xml");
   2:  var peliculas =
   3:      from m in xmlArch.Descendants("Pelicula")
   4:      select new Pelicula {
   5:          Titulo = (string)m.Element("Titulo"),
   6:          Director = (string)m.Element("Director"),
   7:          Estrenado = (DateTime)m.Element("Estrenado"),
   8:          Actores = (from c in m.Elements("Actores").Descendants("Actor")
   9:                     select new Actor {
  10:                         Nombre = (string)c.Element("Nombre"),
  11:                         Nacimiento = (DateTime)c.Element("Nacimiento"),
  12:                         Roles = (from r in c.Elements("Roles").Descendants("Rol")
  13:                                  select new Rol {
  14:                                      Pelicula = (string)r.Element("NombrePelicula"),
  15:                                      NombreRol = (string)r.Element("NombreRol")
  16:                                  }).ToList()
  17:                     }).ToList()
  18:      };

El resultado de el último ejemplo es un Enumerable<pelicula> el cual hay que recorrer por ejemplo con foreach para obtener resultados.

Para aprender mas acerca de Linq visita:
Lista de artículos acerca de Linq

Para aprender más sobre el uso de XML en .Net Framework visita:
Lista de artículos acerca del uso de XML en .Net Framework

sábado, 20 de febrero de 2010

Arreglos de tipos anónimos en Visual Basic .Net

En una edición anterior vimos el uso de arreglos de tipos anónimos en C# en esta edición anexamos el ejemplo con Visual Basic, la síntaxis es muy parecida:


        Dim arreglo() = {New With {.Miembro1 = "hola", .Miembro2 = 10}, _
          New With {.Miembro1 = "mundo", .Miembro2 = 5}}
        For Each i As Object In arreglo
            Console.Out.WriteLine("Miembro1: {0}, Miembro2: {1}", i.Miembro1, i.Miembro2)
        Next

viernes, 19 de febrero de 2010

Tipos anónimos en Visual Basic .Net

En una edición anterior hablamos sobre los tipos anónimos y su uso en c sharp en esta edición solo completamos el ejemplo en Visual Basic, la sítaxis es muy parecida aunque es un poco más sencilla en c sharp.
En fin aquí esta el ejemplo:

        Dim tipo = New With {.Miembro1 = "hola mundo", .Miembro2 = 10}
        Console.Out.WriteLine("Miembro1: {0}, Miembro2: {1}", tipo.Miembro1, tipo.Miembro2)

jueves, 18 de febrero de 2010

Arreglos de tipos anónimos

En la última edición vimos como usar los tipos anónimos de .Net pero que pasa si queremos usarlos en un arreglo?. Basta declarar la variable del arreglo como y sin tipo de dato para los elementos del arreglo, tambien debemos declarar los elementos del arreglo en el inicializador del arreglo cuidando que todos usen la misma forma. Despues podemos pasar a usar el arreglo siempre con el tipo de datos var.
Aqui esta el ejemplo:

            var arreglo = new[] { new { Miembro1 = "hola", Miembro2 = 10 },
                new { Miembro1 = "mundo", Miembro2 = 5 } };
            foreach(var i in arreglo) {
                Console.WriteLine("Miembro1: {0}, Miembro2: {1}", i.Miembro1, i.Miembro2);
            }

miércoles, 17 de febrero de 2010

Tipos Anónimos

Una de las nuevas caracteristicas de .Net Framework es que podemos declarar tipos en el mismo lugar en que se van a utilizar y de una forma simplificada de tal modo que si necesitamos un tipo que se va a utilizar solo temporalmente en una zona de codigo muy corta podemos usar un tipo anónimo y listo:
Aqui esta el ejemplo:


var tipo = new { Miembro1 = "hola", Miembro2 = 10 };
Console.WriteLine("Miembro1: {0}, Miembro2: {1}", tipo.Miembro1, tipo.Miembro2);

martes, 16 de febrero de 2010

SEO con el control DataPager

Usando Asp.Net es fácilisimo hacer sitios Web en muy poco tiempo, sin embargo estos sitios frecuentemente no son amistosos con los buscadores de Internet, es decir no nos ayudan con el SEO, ya que generan links que navegan con javascript o botones con postback los cuales no pueden ser seguidos por los robots de los buscadores.

Este es el caso de los controles GridView y ListView que cuando estan configurados para paginar generan ligas de página que funcionan ya  sea con javascript o postback.

Por fortuna en el caso del control DataPager (que se utiliza con el control ListView) podemos indicarle que genere ligas normales es decir que genera peticiones GET y pueden ser seguidas fácilmente por los robots siendo así una gran ayuda para el SEO.

Para indicar este comportamiento en el control DataPager basta incluir el atributo QueryStringField en el tag del DataPager:

<asp:DataPager ID="DataPager1" runat="server" PageSize="4" QueryStringField="pageNumber">

con esto el control generara ligas que incluyan el valor pageNumber en el querystring indicando la pagina del ListView que se desea ver.

El control DataPager solo funciona de momento con el control ListView pero en otra entrada veremos como hacer que el control GridView modificando el comportamiento del mismo.

Como nota final hay que decir que hay que tener cuidado cuando se usa la propiedad QueryStringField ya que cuando el querystring de la pagina incluye una variable sin valor algo como /pagina.aspx?foo el mismo generara una excepción sin importar que la variable foo no tenga nada que ver con el DataPager, solo hay que cuidar el no tener querystrings con variables sin valor.

Para aprender más sobre el control DataPager busca en la lista de artículos sobre el control DataPager en este blog.

Bienvenidos a Solo Net

En primer les quiero dar la bienvenida a este nuevo blog.
Este espacio se crea para publicar tips de Net Framework

Mi intención es convertir este blog en un punto de encuentro donde todos aprendamos de todos, y así consigamos enriquecernos mutuamente.