Subir ficheros en ASP.NET

Actualización: ahora podéis subir ficheros con AJAX muy fácilmente con el FileUpload AJAX

Recuerdo mis viejos tiempos con ASP 3.0 en el que utilicé un algoritmo para subir ficheros... en total más de 500 líneas!!
Eso sí, el fichero lo subía muy bien . Es decir, comprobaba que era de cierto tipo específico (por ejemplo una imagen) que ocupaba menos de cierto tamaño, que no era un ejecutable, etc.

¡Pero el código era lo más zarrapastroso (== asqueroso == feo == realmente feo) que he visto en mucho tiempo!
Tanto es así, que en adelante usé PHP para esas cositas específicas, pues con muy pocas líneas se consiguen resultados muy buenos.

Pero como siempre ASP.NET nos lleva a un nivel de sencillez mucho mayor. Veamoslo

1.- El control FileUpload
El control FileUpload es el encargado de que todo sea tan sencillo. No tenemos más que arrastrarlo desde la caja de herramientas. Añadimos también un botón que apretaremos cuando queramos subir el fichero. Obtenemos:

    <asp:FileUpload ID="FileUpload1" runat="server" />
    <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />


2.- Subir el fichero de forma muuuy sencilla
La sencillez absoluta a la hora de subir un fichero es un simple

        FileUpload1.SaveAs(Server.MapPath("~/Upload"));

De ese modo el fichero se guardará en el directorio Upload.
¡¡Sobra decir que es estrictamente necesario tener permisos de escritura en el directorio de subida!!

3.- Funciones avanzadas
Pero si queréis llevar a cabo funciones más avanzadas como comprobar el tipo de fichero, su longitud, trabajar con el stream antes de guardar, etc... también lo tenéis muy fácil.

Hay varios modos de hacerlo con el FileUpload, pero yo os aconsejo recoger el objeto HttpPostedFile, pues desde éste podéis acceder a los elementos más importantes del fichero:

        HttpPostedFile mifichero = FileUpload1.PostedFile;

        // Longitud en Kb
        double Kb = mifichero.ContentLength / 1024;

        // Nombre del fichero
        string nombreFichero = mifichero.FileName;

        // El tipo mime
        string mimeType = mifichero.ContentType;

        // El FileStream correspondiente
        FileStream stream = (FileStream)mifichero.InputStream;

        // Y finalmente guardar el resultado
        mifichero.SaveAs(Server.MapPath("~/Upload"));


4.- HttpRuntime
Como era de esperar, ASP.NET ofrece un nivel extra de protección a la hora de permitir la subida de ficheros.
Los dos  parámetros de configuración  más importantes, definen la longitud máxima del fichero y el tiempo máximo que pasará tras el cual el motor de ASP.NET cortará la subida del fichero.

Por defecto la longitud máxima del fichero es de 4 Mbytes, y el tiempo máximos es de 90 segundos en ASP.NET 1.x y 110 en ASP.NET 2.0

Si queremos modificar esos valores por defecto, en nuestro Web.Config, dentro del elemento System.Web, ubicaríamos:

    <httpRuntime maxRequestLength="longitud kbytes" executionTimeout="segundos" />


Nota: como consejo personal, os pido que no abuséis de la subida de ficheros por parte de usuarios anónimos, pues es bastante sencillo tumbar un website si no se toman las medidas de precaución adecuadas.



Random: números aleatorios

De vez en cuando viene bien un número aleatorio, ¿no?

Si no somos nada rigurosos, porque no nos hace falta, valdría con el típico

        int aleat0 = DateTime.Now.Millisecond;

Y con la operación módulo (%) y alguna que otra suma podemos conseguir cualquier número en cualquier rango.

Por el contrario, si somos tremendamente rigurosos y queremos un número lo más aleatorio posible además de muy alto, por ejemplo para generar una clave criptográfica que codifique información muy importante, este no es tu artículo


Pero si estás entre la inmensa mayoría y quieres un número "respetablemente" aleatorio, vamos a ver cuán fácil es de conseguirlo con ASP.NET.

Con ASP.NET tenemos tres métodos que nos generan un número aleatorio, pero primero de todo tenemos que instanciar la clase random:

        // Creamos el objeto random, simplemente
        Random r = new Random();
       
        // O para los más puritamos,
        // añadimos un plus de aleatoriedad eligiendo una semilla con cierto grado de pseudoaleatoriedad
        Random r = new Random(DateTime.Now.Millisecond);


Y una vez tenemos el objeto, utilizaremos uno de esos tres métodos.

1.- El método Next

Tiene tres sobrecargas:
        int aleat1 = r.Next();

        // Le imponemos un máximo
        int aleat2 = r.Next(100);

        // Le imponemos un rango, por ejemplo queremos un número de 3 cifras
        int aleat3 = r.Next(100, 999);


2.- El método NextDouble
        // Devuelve un double entre 0 y 1
        int aleat4 = r.NextDouble();


3.- El método NextBytes
        byte[] buffer = new byte[100];
        r.NextBytes(buffer);


¡¡Como veis, es muy sencillo!!
Por cierto, la clase Random está dentro del namespace System, por lo que no tenéis que recoger ningún namespace extraño



Cookies en ASP.NET

Las cookies son una parte muy importante en todas las aplicaciones Web.

Si bien nunca se recomienda basar una aplicación en el funcionamiento de las cookies (ya que el usuario siempre puede borrarlas y/o modificarlas), éstas nos ofrecen la posibilidad a los webmasters de dar muchos y buenos servicios a nuestros usuarios.

Y como siempre, si unimos la palabra webmaster con la de ASP.NET, nos da como resultado la facilidad. Y es que si trabajar con cookies ha sido siempre sencillo en antiguos lenguajes como ASP o PHP, con ASP.NET lo es mucho más, pero además se le une la orientación a objetos y el tipado de las cookies.

En ASP.NET las cookies se manejan con HttpCookie, que está dentro del namespace System.Web.

Pero vayamos al grano con los usos típicos que se les hace a las cookies:

1.- Crear una cookie
        // Creamos elemento HttpCookie con su nombre y su valor
        HttpCookie addCookie = new HttpCookie("subgurim", DateTime.Now.ToString());
       
        // Si queremos le asignamos un fecha de expiración: mañana
        addCookie.Expires = DateTime.Today.AddDays(1).AddSeconds(-1);
       
        // Y finalmente ñadimos la cookie a nuestro usuario
        Response.Cookies.Add(addCookie);


2.- Recoger una cookie
        // Recogemos la cookie que nos interese
        HttpCookie cogeCookie = Request.Cookies.Get("subgurim");

        // O a la antigua usanza, que es lo mismo pero me gusta menos
        // HttpCookie cogeCookie = Request.Cookies["subgurim"];

        // O mostramos todas las cookies por pantalla
        foreach (HttpCookie cookie in Request.Cookies)
        {
            Response.Write(cookie.Name + ":" + cookie.Value + "<br />");
        }



3.- Modificar una cookie
        // Puede darse el caso que lo que queramos es modificar una cookie
        // Por ejemplo vamos a cambiar el tiempo de expiración de la cookie que creamos al principio
        HttpCookie modificaCookie = Request.Cookies.Get("subgurim");
        modificaCookie.Expires = DateTime.Now.AddDays(7);
        Response.Cookies.Set(modificaCookie);


4.- Borrar una cookie
        // Borrarla es realmente sencillo
        Response.Cookies.Remove("subgurim");

        // O si quieres borrarlas todas...
        Response.Cookies.Clear();


5.- Cookies multidimensionales
Sí, ya lo sé, una sóla cookie puede contener varios valores... pero ASP.NET nos lo sigue poniendo muy sencillo. Veamos cómo creamos una cookie multidimensional y cómo la recogemos. Por extensión sabemos ya modificar esa cookie así como borrarla.

5.1 - Crear cookie multidimensional
        HttpCookie addMultiCookie = new HttpCookie("subgurimMultidimensional");
        for (int i = 0; i < 10; i++)
        {
            // Mi modo preferido
            addMultiCookie.Values.Add(i.ToString(), "Elemento " + i.ToString());
            
             // Modo antiguo y que no me gusta
            //addMultiCookie[i.ToString()] = "Elemento " + i.ToString();
        }
        Response.Cookies.Add(addMultiCookie);


Como observamos, la única diferencia es que accedemos a la colección Values (System.Collections.Specialized.NameValueCollection), y en ella podemos ejecutar lo mismo que en cualquier otro tipo de colección.

5.2 Recoger cookie multidimensional
        HttpCookie cogeMultiCookie = Request.Cookies.Get("subgurimMultidimensional");   
        // Accedemos a cualquiera de los valores.
        // Por ejemplo, en este caso recogemos el valor de la cookie cuyo nombre es "5"
        string valorCualquiera = cogeMultiCookie.Values.Get("5");



Nota
: Fijaos en que siempre que recogemos una cookie, utilizamos Request, y cuando la modificamos o borramos, utilizamos Response.
Nota 2: El objeto HttpCookie sólo contiene a la cookie, si queremos darle valor a los cambios que le hagamos, siempre debemos utilizar el Response y el Request.



Leer los atributos de un elemento XML

Si no habéis trabajado demasiado con la lectura de ficheros XML, antes de comenzar con este artículo, sería conveniente que os leyerais el artículo de introducción al XmlTextReader.

Lo que en este artículo se va a tratar es una de esas cositas sueltas de las que no se suele escribir porque se considera poco importante, pero que llegado el momento suele hacer falta saber: leer los atributos de un elemento XML.

Si bien es cierto que hay métodos del XmlTextReader que leen atributos, no es menos cierto que éstos suelen dar muchos problemas si no tenemos muy clara la estructura del XML, abocándonos a bucles infinitos o consiguiendo un null por respuesta.

Vayamos pues al grano. Imaginemos que tenemos este fichero XML:

<raiz>
    <persona nombre="Juan" apellidos="Martínez Martínez">   
    <persona nombre="Bill" apellidos="Gates">
    <persona nombre="Napoleón" apellidos="Buenaparte">    ...
</raiz>


Vamos a crear una función donde se utilizarán listas genéricas en las que se almacerán elementos de la clase Persona tras leer el XML completo.

1. crear la clase persona
Con motivo de que el artículo sea completo, creamos una sencilla clase persona con sólo dos propiedades: nombre y apellidos:

public class Persona
{
    private string _nombre;
    public string nombre
    {
        get { return _nombre; }
        set { _nombre = value; }
    }

    private string _apellidos;
    public string apellidos
    {
        get { return _apellidos; }
        set { _apellidos = value; }
    }
}


2.- ¡Recordad importar los namespace correspondientes!
Que son el namespace en el que encontramos todas las clases que manejan XML y el de las colecciones genéricas.

using System.Xml;
using System.Collections.Generic;


3.- Creamos el algoritmo de lectura
Veamos el código comentado:
    public List<Persona> leemosAtributos()
    {
        // Creamos la lista genérica de Personas
        List<Persona> personas = new List<Persona>();

        string url = "Path o Url de nuestro XML";
        // Abrimos el elemto XmlTextReader usando la sentencia using,
        // que se encargará de cerrar todos los recursos que use el objeto
        using (XmlTextReader reader = new XmlTextReader(url))
        {

            // Con estas dos sentencias, no situamos en el primer elemento
            // de nuestro fichero XML (raíz)
            reader.MoveToContent();
            reader.ReadStartElement();

            // Ahora viene el típico bucle del que sólo saldremos cuando se termine
            // el fichero XML
            while (reader.Read())
            {
                // Si el reader está en un elemento y ese elemento se llama "persona"
                // (en nuestro ejemplo todos los elementos se llaman persona)
                if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "persona"))
                {
                    // Creamos un objeto del tipo persona
                    Persona persona = new Persona();

                    // Aquí viene el alma de nuestro algoritmo
                    // Viajamos desde el primer al último atributo
                    for (int i = 0; i < reader.AttributeCount; i++)
                    {
                        // Nos movemos al atributo que nos corresponde.
                        // Es muy importante observar que siempre se mueve de los atributos previos a los
                        // posteriores, pues el XmlTextReader sólo sabe ir hacia delante.
                        reader.MoveToAttribute(i);
                        {
                            // Según sea el nombre del atributo, colocamos su valor en una u otra
                            // propiedad de nuestro objeto Persona
                            switch (reader.Name)
                            {
                                case "nombre":
                                    persona.nombre = reader.Value;
                                    break;
                                case "apellidos":
                                    persona.apellidos = reader.Value;
                                    break;
                            }
                        }
                    }

                    // Finalmente añadimos el objeto Persona al listado genérico
                    personas.Add(persona);
                }
            }
        }

        // Devolvemos el listado genérico
        return personas;
    }


Nota: el algoritmo propuesto es simplemente una base, en ningún momento se comprueba que los datos sean válidos o que existan; ni tal siquiera si el propio XML es válido.




Firefox: recomendado para webmasters en general y ASP.NET en particular

Como todos sabéis, en los últimos tiempos se ha estado librando una batalla de navegadores.

Todo comenzó con Netscape, del que seguro que todos hemos tenido una versión, y poco después apareció el Internet Explorer.

Aunque parezca mentira, Netscape fue líder indiscutible en navegadores Web, pero cuando Microsoft decidió instalar por defecto el Internet Explorer en su sistema operativo, el IE subió como la espuma para llegar a manejar el 97% del mercado.

En los últimos tiempos, parece que el IE se ha dormido y han nacido fuerte competidores como Opera y sobretodo Firefox.

Firefox no es sólo un "navegador con pestañas", ni "un navegador más seguro", sino un navegador de código abierto y del que cualquiera puede hacer una extensión. Eso es el poder más fuerte de Firefox: las extensiones.

Personalmente opino que son dos las extensiones más importantes del Firefox: la barra de google (imprescindible para cualquier internauta) y la Web Developer (imprescindible para webmaster).

La extensión Web Developer del Firefox es pura magia, y repito: es totalmente imprescindible para cualquier webmaster que se precie, y para los que programamos en ASP.NET todavía más. No en vano, ha sido nombrada la mejor extensión para developers del año pasado (2005), y a este paso también lo será de 2006

Con un simple clic de ratón, puedes extraer e interactuar cualquier tipo de información de cualquier página:
- Puedes ver todo lo referente a las cookies, borrártelas, incluso añadirlas!
- Puedes ver todo tipo de información sobre css: los estilos css, los ficheros css adjuntos, la "class" o "id" css de cualquier elemento en particular... incluso puedes modificar el código css para ver "cómo quedaría"!!!
- Con el HTML lo mismo: puedes modificarlo en el propio navegador para ver cómo quedarían los cambios!!!
- Puedos redimensionar la ventanita del navegador para pre-ver cómo se vería con tal o tal resolución (olvidaos ya de tener que cambiar la resolución del monitor!)
- Puedes extraer todo tipo de info de la página, cabeceras http, informe con los colores de tal página.

Bueno, para ya de decir cosas, porque ni tal siquiera he dicho las más útiles... es que son todas útiles!! Lo menos que podéis hacerlo es probarlo, tanto el navegador como la extensión "Web Developer".

Para instalaros el Firefox con la barra de Google preinstalada (la descarga es directa desde los servidores de Google, por lo que está completamente libre de virus):



Y para instalaros la extensión del web developer: https://addons.mozilla.org/firefox/60/





Actualizada la sección "Mis Webs"

A falta de tiempo para escribir artículos (pronto pondré más y muy jugosos), os informo de que he actualizado la sección de "Mis Webs", que podréis encuentrar en la parte inferior del menú izquierdo.

De ese modo podréis conocer todos los proyectos (públicos) en los que estoy trabajando



Nueva versión de es-ASP.NET

El portal de ASP.NET en castellano acaba de estrenar su nueva cara.

Ahora es mucho más profesional y competitivo, y se encuadra como uno de los portales líderes de ASP.NET en castellano.

Es totalmente imprescindible echarle un vistazo porque tiene gran cantidad de utilidades, destacando su foro, donde expertos en ASP.NET responderán rápidamente tus dudas, y sobretodo sus tutoriales traducidos al castellano que periódicamente van renovando y mejorando.

Upload/es-asp-net_(2).jpg



Control de GoogleMaps para ASP.NET

Acaba de nacer un nuevo control de usuario: GoogleMaps para ASP.NET.

Y es que ASP.NET es lo que tiene, que con sólo arrastrar desde la caja de herramientas hasta nuestra página podemos disponer de complejos controles sin apenas código!

Y esto es lo que ocurre con este nuevo control, que dispone además de una completísima web con ejemplos, instrucciones de instalación, sección de descarga con las diferentes versiones y mucho más... todo en castellano, y por supuesto gratuito!!

La web es googlemaps.subgurim.net.

Upload/googlemaps-preview.jpg