Nivel intermedio

Escribir ficheros XML mediante LINQ


Ayer veíamos la estructura de un fichero XML y cómo hacer uso del espacio de nombres System.Xml.Linq para generar un nuevo fichero XML. Anteayer, además aprendíamos de la versatilidad de LINQ, que nos permite iterar y filtrar sobre prácticamente cualquier cosa.

Hoy vamos a aunar los valores de ambos conceptos y vamos a generar (y consultar) un fichero XML a través de LINQ. Por ello es altamente aconsejable conocer previamente los conceptos explicados en los dos artículos anteriores.

Comenzaremos por el proceso de creación de un fichero XML. O más bien, de «cumplimentación». Hace ya unos añitos (¡cómo pasa el tiempo!) explicábamos en este mismo blog la forma de utilizar la reflexión para acceder a los elementos de un objeto (métodos, propiedades, atributos…). Hace unos días he actualizado ese artículo con información sobre cómo hacer uso de LINQ para realizar la misma operación que realizamos entonces (¡ah…! los tiempos del Framework 2.0…). Sin embargo, en este artículo iremos un poco más allá y aplicaremos esa misma funcionalidad para, a partir de un objeto, conseguir generar un fichero XML que desglose los elementos de cada miembro de un objeto.

Antes de meternos en harina con los ficheros XML, conviene centrarnos en la parte de LINQ. El objetivo es el siguiente: crear un fichero XML que almacene la información de todos los miembros de la clase de un objeto. La estructura objetivo será la siguiente:

  • <Clase>
    • <ConstructorMembers>
      • <Constructor name = «nombreConstructor» value=»void nombreConstructor()» />
    • <MethodMembers>
      • <Method name = «ToString» value = «System.String ToString()» />
      • <Method name = …

Es decir, desglosaremos la clase en secciones que, a su vez, contendrán elementos pertenecientes a esa sección (ConstructorMembers contendrá elementos Constructor y así sucesivamente), que a su vez contendrán dos atributos: name y value.

(más…)

Introducción a LINQ


LINQ (leído «link», pese a que mucha gente lo denomina «lin-quiú») es una biblioteca de la plataforma .NET que proporciona acceso a datos de forma nativa a C# o VB.NET.

Basa su existencia en las denominadas expresiones de consulta, que recuerdan a las sentencias SQL pero extienden su funcionalidad de consulta a otros elementos como listas, arrays, clases enumerables, o documentos XML.

Operadores de consulta

LINQ hace uso de un conjunto de operadores, definidos en el espacio de nombres System.Linq, que permiten realizar consultas sobre cualquier conjunto de objetos enumerables, es decir, IEnumerable<T>. Por ejemplo, imaginemos que tenemos un array (que implementa IEnumerable) como el siguiente:

    string[] juegos = {  "Carcassonne", "Bang", "Jungle Speed", "Los colonos de Catán", "Black stories", "Munchkin", "Zombies" };

    IEnumerable<string> consulta = from j in juegos
                                    where j.StartsWith("J")
                                    orderby j ascending
                                    select j;

    foreach( string elemento in consulta)
        Console.WriteLine(elemento);

Como podemos observar, si disponemos de conocimientos básicos de SQL, la consulta LINQ se parece bastante a una consulta SQL: cláusula select, where, from, orderby… Puede que lo único que altere un poco la paz de los que nunca hayan visto esta tecnología sea el orden en el que se declaran las sentencias.

(más…)

El Controlador en ASP.NET MVC 4 (III): Action Filters


Un Action Filter o filtro de acción es un atributo que puede asociarse a una acción de un controlador (o al controlador en su totalidad), modificando la forma en la que la acción se ejecuta. El Framework ASP.NET MVC proporciona unos cuantos, entre ellos:

Nombre Descripción
Authorize Restringe una acción para los roles o usuarios especificados.
HandleError Permite especificar una vista que se mostrará en caso de excepción no controlada.
OutputCache Almacena en caché la salida de un controlador
ValidateAntiForgeryToken Ayuda a evitar peticiones de falsificación de petición (pishing)
ValidateInput Desactiva las validaciones de petición. No es aconsejable hacer uso de este filtro salvo en ocasiones muy concretas, ya que pone en peligro la seguridad de la aplicación.

Además de los existentes, es posible crear filtros personalizados para fines definidos por el negocio (como por ejemplo, un sistema de autenticación personalizado).

Tal y como vimos brevemente en el artículo anterior con [HttpGet] y [HttpPost], las acciones pueden «condimentarse» con atributos que afectan a su funcionalidad. Los filtros se añaden a modo de atributo a las acciones, haciendo que su comportamiento varíe. Veamos un par de ejemplos.

(más…)

Instalar log4net en ASP.NET


Haremos una pequeña parada en el camino antes de proceder a explicar el funcionamiento de los Action Filters para aprender a configurar la herramienta de logging de Apache log4net. Esto se debe a que en el siguiente artículo crearemos un filtro personalizado que se encargará de trazar todas las operaciones realizadas por nuestros controladores, por lo que será requisito previo disponer de esta biblioteca instalada en nuestro proyecto.

Comenzaremos descargándonos log4net de la web de apache. Podemos obtenerlo desde aquí.

Hecho esto, abriremos el fichero .zip y nos dirigiremos al directorio que se corresponda con nuestra versión, en este caso, 4.0.


Localizaremos a continuación la biblioteca log4net.dll


(más…)

El Controlador en ASP.NET MVC 4 (II): Action Results


Hemos visto hasta ahora que nuestras acciones (recordemos que las acciones son los métodos públicos de un controlador) deben devolver un objeto de la clase ActionResult.

En ejemplos anteriores hemos utilizado los métodos View() y Content() para generar un objeto de este tipo, pero estos no son los únicos métodos que generan un resultado de una acción (ActionResult).

Dependiendo de la respuesta que queramos dar podremos hacer uso de los siguientes métodos, con sus correspondientes ActionResults, que generan desde texto plano (como Content()) hasta la lectura de un fichero (método File()) o la redirección a una nueva URL (método Redirect()):

MÉTODO ACTION RESULT DESCRIPCIÓN
Content() ContentResult Devuelve una cadena de texto.
EmptyResult (sin respuesta)
File() FileContentResult
FilePathResult
FileStreamResult
Devuelve el contenido de un fichero.
HttpUnauthorizedResult Devuelve un error de autorización (403)
JavaScript() JavaScriptResult Devuelve un fragmento de código JavaScript a ejecutar.
Json() JsonResult Devuelve datos en formato JSON.
Redirect() RedirectResult Redirecciona a una nueva URL.
RedirectToRoute()
RedirectToAction()
RedirectToRouteResult Redirecciona a otra acción.
View()
PartialView()
ViewResult
PartialViewResult
Traspasa el control a una vista.

A continuación echaremos un vistazo por encima a los elementos más importantes de esta tabla.

(más…)

El Controlador en ASP.NET MVC 4 (I): Enrutado


Anteriormente hemos aprendido el funcionamiento general de la arquitectura MVC de ASP.NET. Sin embargo, hay algunas dudas que se mantienen en el aire, como por ejemplo, cómo sabe MVC a qué controlador debe acudir cada vez que se recibe una petición HTTP.

Redireccionando las peticiones HTTP

Para bien o para mal, el enrutado no es una tarea que pertenezca al framework, sino que es ASP.NET quien debe encargarse de ello en última instancia. Previamente vimos que MVC 4 realiza una redirección hacia un controlador acorde a la ruta que se invoca: si se trataba de la ruta <servidor>/Home/About, comprobamos que se invocaba el método About() del controlador HomeController.

¿Dónde puede configurarse este comportamiento? La respuesta corta es: en el archivo de configuración global, global.asax.cs.

Este fichero contiene, entre otro código, las operaciones a realizar al levantar la aplicación, previas a cualquier petición que pueda realizarse. Entre esas operaciones se encuentra la posibilidad de indicarle a nuestra aplicación cómo se realizarán las redirecciones de las peticiones HTTP. Esto lo podremos observar en la siguiente línea de configuración:


RouteConfig.RegisterRoutes(RouteTable.Routes);

(más…)

Introducción a ASP.NET MVC 4


Aunque no hayas estudiado patrones de diseño, es altamente probable de que, si te dedicas a la programación, hayas oído hablar en alguna ocasión del Modelo-Vista-Controlador. Se trata de uno de los patrones de diseño más ubicuos y populares, que persigue la filosofía de crear un patrón de tres capas que diferencian las labores de la aplicación en:

  • MODELO: Gestiona la información que el usuario precisa, es decir qué información quiere el usuario.
  • VISTA: Muestra la información al usuario y permite que éste interactúe con ella, proporcionando datos, modificándolos, solicitando su modificación o simplemente, consultándolos. En resumen, cómo se muestra la información en pantalla.
  • CONTROLADOR: Actúa de intermediario entre los elementos anteriores y el usuario, atendiendo las peticiones HTTP (en el caso de ASP.NET), generando la información que el usuario requiere (modelo) y mostrándola por pantalla (vista).

Microsoft proporciona una implementación estándar de este patrón permitiendo crear un proyecto basado en web que genera automáticamente estos tres elementos, separando de una forma más clara la funcionalidad interna de la aplicación de la gestión de las peticiones y su visualización en pantalla.

(más…)

Persistencia en Android


Los tipos de persistencia en Android, por lo general, puede dividirse en tres grupos:

  • Preferencias compartidas: conjunto de pares clave-valor. Pueden ser privadas (únicamente accesibles desde la aplicación) o compartidas con otras aplicaciones.
  • Ficheros: una aplicación Android puede almacenar y consultar datos tanto de la carpeta privada de la aplicación como de la tarjeta SD.
  • Base de datos: cada aplicación puede disponer de una base de datos local en formato SQLite en la que realizar operaciones SQL como si de un SGDB normal y corriente se tratara.

A continuación pasaremos a explicar en qué consisten y cómo utilizar estos tres tipos de persistencia.

Estructura interna de la aplicación

Cada aplicación que se instala en el dispositivo crea una carpeta con el nombre de su paquete principal dentro de la ruta /data/data de la memoria interna del dispositivo. Dentro de esa carpeta privada (que no puede ser accedida por ningún otro proceso salvo que se disponga de un terminal de desarrollo o se «rootee» el dispositivo) se aloja una estructura en la que, entre otros, se encuentran las siguientes carpetas:

  • /shared_prefs: contiene un conjunto de ficheros XML que se corresponden a los nombres de las preferencias compartidas. Almacena un mapa con pares clave-valor.
  • /files: contiene los archivos del sistema, que pueden ser binarios o de texto.
  • /databases: contiene las bases de datos SQLite asociadas a la aplicación.
  • /cache: contiene los datos temporales de la aplicación

Directorio interno de la aplicación

A continuación veremos con un poco más de detalle el significado de estos directorios y la relación con los medios de persistencia que Android ofrece.

(más…)

Bluetooth (VI): Creando el hilo cliente


Concluiremos la codificación del ejemplo completo de una aplicación que realiza un intercambio de información a través de Bluetooth mediante una arquitectura comunicación cliente-servidor mostrando cómo realizar el hilo encargado de solicitar la conexión, es decir, el cliente.

Comenzaremos creando la clase dentro de nuestro BluetoothService. Este hilo tendrá dos atributos privados: el dispositivo al que se quiere conectar y el socket que el dispositivo remoto abrirá para realizar la conexión.


	// Hilo encargado de solicitar una conexion a un dispositivo que este corriendo un
	// HiloServidor.
	private class HiloCliente extends Thread
	{
		private final BluetoothDevice dispositivo;
		private final BluetoothSocket socket;

		public HiloCliente(BluetoothDevice dispositivo)
		{
			BluetoothSocket tmpSocket = null;
			this.dispositivo = dispositivo;

			// Obtenemos un socket para el dispositivo con el que se quiere conectar
			try {
				tmpSocket = dispositivo.createRfcommSocketToServiceRecord(UUID_SEGURO);
			}
			catch(IOException e) {
				Log.e(TAG, "HiloCliente.HiloCliente(): Error al abrir el socket", e);
			}

			socket = tmpSocket;
		}

(más…)

Bluetooth (V): Creando el hilo servidor


Siguiendo con la serie de artículos dedicados al Bluetooth que dejamos aquí, vamos a continuar desarrollando la clase BluetoothService añadiéndole el hilo encargado de hacer las funciones de servidor.

Tal y como hicimos con el servidor destinado a mantener la conexión, declararemos socket como atributo privado constante. En esta caso será de tipo BluetoothServerSocket, que a diferencia del BluetoothSocket tradicional, se encarga de mantenerse en escucha en un puerto y abrir un socket (esta vez sí, de la clase BluetoothSocket ) cuando detecta una conexión entrante. Comenzaremos codificando el constructor:


	// Hilo que hace las veces de servidor, encargado de escuchar conexiones entrantes y
	// crear un hilo que maneje la conexion cuando ello ocurra.
	// La otra parte debera solicitar la conexion mediante un HiloCliente.
	private class HiloServidor extends Thread
	{
		private final BluetoothServerSocket serverSocket;

		public HiloServidor()
		{
			BluetoothServerSocket tmpServerSocket = null;

			// Creamos un socket para escuchar las peticiones de conexion
			try {
				tmpServerSocket = bAdapter.listenUsingRfcommWithServiceRecord(NOMBRE_SEGURO, UUID_SEGURO);
			} catch(IOException e) {
				Log.e(TAG, "HiloServidor(): Error al abrir el socket servidor", e);
			}

			serverSocket = tmpServerSocket;
		}
	}

(más…)

Bluetooth (IV): Creando el hilo de conexión


Como vimos en anteriores artículos, los elementos necesarios para realizar una comunicación entre dos dispositivos a través de Bluetooth van a ser:

  • Cliente
  • Servidor
  • Conexión

Codificaremos cada uno de estos elementos como hilos independientes encargados de centrarse exclusivamente en su tarea. Así, el hilo servidor se encargará de escuchar conexiones entrantes, aceptarlas y establecer la conexión, mientras que el hilo cliente será el encargado de solicitar la conexión y establecerla una vez que haya sido aceptada por el servidor. Por lo tanto, el hilo encargado de establecer la conexión será lanzado tanto por el cliente como por el servidor.

Comenzaremos codificando el hilo encargado de establecer la conexión. Crearemos una clase específica que contendrá los tres hilos, de modo que la funcionalidad entre interfaz de usuario y lógica de la aplicación se mantenga separada.

Crearemos la clase añadiéndole unas cuantas constantes para definir los posibles estados y mensajes a manejar por el handler y un par de atributos privados para almacenar el estado actual de la conexión, el socket de la conexión y el handler que se encargará de comunicar los datos a la interfaz de usuario.

(más…)

Widgets en Android: creando una linterna


Todos los usuarios de Android conocemos los widgets, pequeñas aplicaciones que por lo general, corren y/o se sitúan en la pantalla principal (Homescreen).

A diferencia de una aplicación tradicional, un widget no necesita una actividad para vivir, sino que se hace uso de la clase RemoteViews para su ejecución. Esta clase implementa un layout (fichero xml con elementos de interfaz) que contiene una o más vistas (View) y tiene la peculiaridad de poder ser ejecutado por otro proceso con los mismos permisos que la aplicación original.

Como introducción a los widgets crearemos una aplicación completa que consistirá en un widget consistente en un ImageButton con el dibujo de una lámpara que cambiará su imagen cuando el usuario lo pulse, haciendo que se encienda y apague la linterna en un dispositivo que cuente con cámara con flash.

Los elementos que necesitaremos para crear este widget serán los siguientes, describiéndolos descendentemente, desde la capa más externa (interfaz) hasta la más interna (receptor de las acciones generadas al pulsar el widget).

  • res/layout/flashlight_layout.xml: Fichero XML que contendrá el layout del widget, es decir, la interfaz del widget en sí, compuesta en este caso por un ImageButton.
  • res/xml/flashlight_widget_provider.xml: Fichero XML que contendrá la descripción del widget provider. Contendrá el layout inicial (que será el fichero anterior) y el tamaño mínimo del widget.
  • FlashLightWidgetProvider.java: Clase que heredará de AppWidgetProvider y se encargará de generar los Intents al producirse algún evento sobre el widget y actualizar las instancias del widget.
  • FlashLightBroadcastReceiver.java: Clase que heredará de BroadcastReceiver y se encargará de detectar las acciones generadas por el elemento anterior. Al detectar la acción, ejecutará la lógica de la aplicación y regenerará la interfaz del widget.

(más…)

Bluetooth (III): El esquema cliente-servidor


Hasta ahora hemos sido capaces de activar y desactivar el Bluetooth, hacer visible nuestro dispositivo y detectar los dispositivos visibles que encuentren en las proximidades. Es hora de intercambiar información por medio del protocolo Bluetooth, para lo cual necesitaremos unas pequeñas nociones básicas de la arquitectura cliente-servidor.

En primer lugar, el protocolo Bluetooth no se diferencia gran cosa de otros protocolos como TCP. El funcionamiento es básicamente el siguiente:

  • El servidor crea un socket de tipo BluetoothServerSocket y lo pone a la escucha de peticiones de conexión.
  • El servidor se mantiene en espera ocupada atendiendo solicitudes de conexión mediante el método accept(). Este método bloqueará el hilo hasta que una conexión entrante sea recibida.
  • El cliente instancia un dispositivo Bluetooth (BluetoothDevice) a partir de la dirección del dispositivo.
  • El cliente abre un nuevo socket de tipo BluetoothSocket a partir del dispositivo que obtuvo previamente.

Instanciación del socket cliente a partir del dispositivo (más…)

Bluetooth (II): Descubriendo dispositivos


Una vez que sabemos cómo funciona el proceso de activación y desactivación del Bluetooth, es hora de buscar dispositivos cercanos que nos permitan establecer una conexión. Para entender los ejemplos mostrados en este artículo se recomienda leer el artículo anterior, Bluetooth (I): Activando y desactivando el Bluetooth en Android.

Como vimos, para que se realice una conexión Bluetooth es necesaria la siguiente secuencia de pasos:

  1. El dispositivo B se configura como servidor, aceptando conexiones entrantes.
  2. El dispositivo A solicita la conexión al dispositivo B. Para ello, es necesario que A conozca la dirección física de B.
  3. En el caso de que A no conozca la dirección de B, la conexión no podrá llevarse a cabo.

Dado que las direcciones no se conocen a priori, es necesario un mecanismo que permita a un dispositivo Bluetooth «encontrar» a otro. Este proceso se denomina descubrimiento o discovery.

Para que el dispositivo A descubra al dispositivo B, es necesario que B, además de tener activado el Bluetooth, cambie su estado a «visible». Esto lo hacíamos solicitándoselo de forma explícita al usuario, tal y como vimos en el artículo anterior.


	Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
	startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);

Partiendo de la base de que el dispositivo B se encuentra visible con el Bluetooth activo, ¿cómo hacemos que el dispositivo A le «descubra»? (más…)

Bluetooth (I): Activando y desactivando el Bluetooth en Android


El primer paso a la hora de desarrollar una aplicación que haga uso de la comunicación mediante Bluetooth es comprobar si éste está activado o no en el dispositivo y, en caso de que no sea así, solicitar al usuario permiso para activarlo.

En primer lugar, si vamos a hacer uso del Bluetooth será requisito indispensable añadir los permisos adecuados para ello en el fichero AndroidManifest.xml:


    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

Pese a que la tecnología Bluetooth está ampliamente extendida, es de obligado cumplimiento la comprobación de que el servicio está disponible en el dispositivo. Para realizar esta operación haremos uso de la clase android.bluetooth.BluetoothAdapter. Declararemos una referencia como atributo dentro de nuestra Activity y a continuación codificaremos un método, al que llamaremos configurarAdaptadorBluetooth(), que se encargará de detectar si el dispositivo puede hacer uso del Bluetooth y si éste se encuentra activo o no.

(más…)

Redimensionar un control de texto con el tamaño de su contenido


En ocasiones, trabajando con WinForms, nos encontramos con un control contenedor de un texto variable en el que, o nos sobra espacio o nos falta. La clase Graphics de System.Drawing nos proporciona un método tremendamente útil para saber el tamaño, en píxels, de una cadena de texto.
Veremos a continuación cómo redimensionar de forma dinámica un control dependiendo del tamaño del texto contenido. Para ello crearemos, por ejemplo, un TextBox al que llamaremos txtPrueba, y en el que albergaremos un texto, por ejemplo «Más vale pájaro en mano, que ciento volando».


txtPrueba.Text = "Más vale pájaro en mano que ciento volando";

A continuación, declararemos dos variables enteras, una para el alto y otra para el ancho.

// Declaramos una variable entera para almacenar el nuevo ancho y el nuevo alto
int nuevoAncho = 0;
int nuevoAlto = 0;

Es ahora donde instanciaremos la clase Graphics a partir del control TextBox, y extraeremos la fuente que está utilizando.

// Creamos un objeto de tipo Graphics a partir del TextBox
Graphics g = txt.CreateGraphics();

// Extraemos la fuente del TextBox
Font fuente = txt.Font;

Obtenemos, a partir del objeto Graphics, su alto y ancho a partir del método MeasureString, que no hace otra cosa que medir, en pixels, el tamaño que ocupa la cadena con la fuente indicada.


nuevoAncho = (int)g.MeasureString(txt.Text, fuente).Width;
nuevoAlto = (int)g.MeasureString(txt.Text, fuente).Height;

Por último, asignamos los nuevos valores de alto y ancho y refrescamos el control.


txt.Width = nuevoAncho;
txt.Height = nuevoAlto;

txt.Refresh();

A partir de estos conceptos básicos, se pueden encontrar multitud de utilidades a este proceso, como por ejemplo, redimensionar el desplegable de un ComboBox al tamaño del mayor de sus elementos.

Crear un campo autoincrementable en ORACLE


Para los que nos iniciamos en los Gestores de Bases de Datos con SQL Server, la transición a ORACLE resulta siempre más dura que cuando se realiza el camino inverso. Realizando una analogía simple, en mi caso podría decir que T-SQL es a PL/SQL lo que C# es a C++. Más complicación, más potencia… y un sistema más «tiquismiquis» que los desarrollados por Microsoft.
SQL Server proporciona una forma muy sencilla de crear campos autonuméricos, generalmente utilizados en los IDs de las claves primarias de las tablas. Para crear un campo autoincrementable, lo único que teníamos que hacer era editar las propiedades de la columna que queríamos convertir en autoincrementable, acceder a sus propiedades y seleccionar la opción [Especificación de Identidad] marcando la casilla (Identidad) e informando del número de inicio del índice (Inicialización de identidad) y el número de unidades que se incrementará cada vez que se intente insertar un registro (Incremento de identidad).

Oracle nos pone las cosas un poco más difíciles, obligándonos a realizar dos pasos para realizar el mismo procedimiento: crear una secuencia y crear un trigger.

(más…)

Utilizar la Base de Datos como repositorio de imágenes (II)


En un artículo anterior aprendimos a almacenar una imagen en nuestra base de datos SQL Server. Ahora vamos a obtener la imagen que almacenamos previamente utilizando como dirección de la imagen un formulario aspx al que le pasaremos el identificador de la imagen a través de la QueryString.

Comenzaremos creando un nuevo formulario, al que llamaremos showImage.aspx. En el formulario, crearemos un nuevo método al que llamaremos ObtenerImagen, que recibirá como parámetro un entero (el ID de la imagen) y devolverá una secuencia de bytes (un byte[]).

byte[] ObtenerImagen(int idImagen)
{
}

Lo primero que hará este método será declarar una cadena de conexión y una sentencia SELECT que devuelva la imagen cuyo ID le pasamos. Para ello, declararemos ambas cadenas de texto.


string selectCommandText = "SELECT Fichero FROM Imagen WHERE IdImagen = " + Convert.ToString(idImagen);
string ConnectionString = @"Data Source=DANIGARCIASQLSERVER2005;Initial Catalog=TestDB;Persist Security Info=True;User ID=dani;Password=c0ntr4s3n14";

A continuación podemos hacer dos cosas: crear un SqlCommand y ejecutar la sentencia SELECT, o bien declarar un DataSet y un SqlDataAdapter y dejar que sea éste último objeto el que nos proporcione los datos. Optaremos por la segunda opción, que pese a ser menos óptima, resulta mucho más cómoda 🙂


// Declaramos un DataSet y un SqlDataAdapter
DataSet ds = new DataSet();
SqlDataAdapter adapter = new SqlDataAdapter(selectCommandText, selectConnectionString);

// Rellenamos el DataSet con la consulta y la cadena de conexión anteriores
adapter.Fill(ds);

Llegados a este punto, ya deberíamos tener almacenada en el DataSet la imagen que estábamos buscando. Por lo tanto, lo único que deberemos hacer será serializarla y devolverla, realizando las comprobaciones pertinentes:


if ((ds != null) && (ds.Tables.Count > 0) && (ds.Tables[0].Rows.Count > 0))
{
if (!ds.Tables[0].Rows[0].IsNull("Fichero"))
{
return ((byte[])(ds.Tables[0].Rows[0]["Fichero"]));
}
}

return null;

Llegados a este punto, codificaremos el contenido del Page_Load de nuestro aspx, comprobando la QueryString y pasándole el parámetro a nuestra función ObtenerImagen, declarando, en primer lugar, un array de Bytes para almacenar el resultado:


protected void Page_Load(object sender, EventArgs e)
{
byte[] bImagen = null;

if (!string.IsNullOrEmpty(Convert.ToString(Request.QueryString["id"])))
{
bImagen = ObtenerImagen(Convert.ToInt32((Convert.ToString(Request.QueryString["id"]))));
}

Si el resultado obtenido no es nulo, modificamos la respuesta para que sea de tipo imagen, haciendo lo siguiente:


if(bImagen != null)
{
Response.Clear();
Response.Buffer = true;
Response.ContentType = "image/jpeg";
Response.BinaryWrite(bImagen);
Response.End();
}
}

Con lo cual, si invocamos la ruta a través del ID, obtendremos directamente una imagen:


Esto es una prueba <br />
<img src="../aspx/showImage.aspx?id=1" />

Utilizar la Base de Datos como repositorio de imágenes (I)


En cierto proyecto necesitaba mostrar una serie de imágenes que el usuario debía insertar desde su equipo local. En un principio pensé enviar al servidor las imágenes, guardar la ruta relativa en Base de Datos y, cuando fuese necesario acceder a las imágenes, utilizar dicha ruta para acceder a la imagen. Pero no era tan sencillo. Por desgracia, no teníamos permiso de escritura en el disco duro, por lo que tenía que juguetear con las imágenes sin que éstas existieran físicamente. ¿Cómo? Almacenando y recuperando las imágenes de base de datos.

Guardando una imagen en SQL Server

Para empezar, veremos cómo almacenar en base de datos una imagen. Crearemos, desde el SQL Server Management Studio, una nueva tabla que tendrá tres campos:

  • Un Id único entero y autoincrementable (IdImagen)
  • Un nombre para la imagen nvarchar(50) (NombreImagen)
  • Una secuencia de bytes, variable de tipo image (Fichero).

09111201 Creada la tabla, crearemos una página que, a partir de la ruta de la imagen, la inserte en base de datos. Podemos utilizar un Input File o un control similar para indicarle la ruta, pero aquí indicaremos únicamente el código necesario para subir la imagen dada su ruta física. Lo que haremos a continuación será lo siguiente:

  • Crear una conexión a Base de Datos a partir de una cadena de conexión
string ConnectionString = @"Data Source=DANIGARCIASQLSERVER2005;Initial Catalog=TestDB;Persist Security Info=True;User ID=dani;Password=c0ntr4s3n14";
  • Crear una cadena de texto con la sentencia INSERT.
string CommandString = "INSERT INTO Imagen(NombreImagen, Fichero) VALUES (@NombreImagen, @Fichero)";
  • A continuación necesitaremos convertir nuestra imagen en un objeto que podamos manejar, por ejemplo un array de bytes. Para ello, a partir de la ruta física de la imagen crearemos un objeto de tipo System.Drawing.Bitmap que guardaremos en un MemoryStream que, a su vez, convertiremos en un array de bytes (byte[]).
  byte[] bImagen = null; System.IO.MemoryStream ms = new System.IO.MemoryStream();  System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(@"C:TEMPinicio.jpg"); if (bmp != null) { bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); bImagen = ms.ToArray(); ms.Close(); }  
  • Instanciar un objeto de tipo SqlCommand a partir de la  conexión y de la sentencia INSERT.
  SqlConnection conexion = new SqlConnection(ConnectionString);  SqlCommand command = new SqlCommand(CommandString, conexion);  
  • Añadiremos ahora los SqlParameters necesarios al objeto SqlCommand con los datos a insertar en la base de datos. Estos serán, en nuestro caso, el nombre de la imagen y el array de bytes con la imagen.
  SqlParameter nombre = new SqlParameter("@NombreImagen", "inicio.jpg"); SqlParameter imagen = new SqlParameter("@Fichero", bImagen);  
  • Por último, abrimos la conexión, ejecutamos la sentencia mediante ExecuteNonQuery() y cerramos la conexión. Hecho esto, tendremos nuestra imagen almacenada en base de datos.
  conexion.Open();  command.Parameters.Add(nombre); command.Parameters.Add(imagen); command.ExecuteNonQuery();  conexion.Close();  

Hecho esto insertaremos una imagen en una tabla de la base de datos. 09111202 Más adelante aprenderemos cómo recuperarla y referenciarla directamente a través de una URL con extensión aspx, es decir, invocar una ruta de tipo getImage.aspx?Id=xxx.

Enviar un e-mail desde .NET utilizando una cuenta SMTP de GMail


En mi proyecto de fin de carrera implementé un sistema automatizado de reservas que avisaba por e-mail del estado de las mismas. Para mi desgracia, olvidé mencionarlo durante la defensa, por lo que a nivel institucional fue una pérdida de tiempo, pero no así a nivel didáctico (que es, a fin de cuentas, lo importante).

Para implementarlo, utilicé los espacios de nombres System.Net y System.Net.Mail y una cuenta de Gmail a la que previamente le había activado el acceso POP/SMTP. Mandar un mail desde .NET es relativamente sencillo.

Si pensamos en la composición de un mail en términos de objetos, veremos que en realidad, enviar un mail es muy, pero que muy sencillo. Imaginemos que tenemos una cuenta en Gmail, por ejemplo ‘estoesunapruebademail25@gmail.com‘, cuya contraseña es ‘inteligible43‘. Queremos mandar un correo. ¿Qué información necesitamos?

  • Un mensaje, que implementará la clase MailMessage.
  • Un cliente de correo (SmtpClient) que se encargue de la autenticación y envío del mensaje.

A su vez, el mensaje necesitará:

  • Uno o varios destinatarios.
  • Un remitente.
  • Un asunto (subject).
  • El texto del mensaje.

Mientras que el cliente del correo necesitará saber:

  • Servidor SMTP al que conectarse y puerto.
  • Nombre de usuario y contraseña.

(más…)