asp.net, c#, java, windows forms, sql server, php, ajax, javascript, linux, software libre, servidores, dicom, biomedicina, ...
N-Idea de muchos temas... o eso pensamos.
miércoles, enero 29, 2014
Posts in Page: un plugin muy versátil y potente para WordPress
Puedes ver la entrada completa en mi sitio http://www.nidea-soluciones.com/index.php/posts-page-un-plugin-muy-versatil-y-potente-para-wordpress/
Gracias por seguir mis posts.
jueves, enero 16, 2014
Script de códigos BIC / Swift para SQL Server
Para aquellos que estén con la adaptación a la normativa SEPA, aquí os dejo un script de SQL Server para la creación de una tabla y la inserción de los códigos BIC de los bancos que operan en España según la relación publicada en el BOE del 25 de Octubre del 2013.
Ver la entrada completa en Script de códigos BIC / Swift para SQL Server
miércoles, enero 08, 2014
Desactivar la comprobación de la lista de revocación de certificados de la FNMT en IIS
Ver la entrada completa en http://www.nidea-soluciones.com/index.php/desactivar-la-comprobacion-de-la-lista-de-revocacion-de-certificados-de-la-fnmt-en-iis/
martes, enero 07, 2014
Internacionalización en asp.net con c#
Ver la entrada completa en mi sitio (Internacionalización en asp.net con c#)
Cálculo del IBAN en c#
Ver la entrada completa en mi sitio (Cálculo del IBAN en c#)
viernes, enero 03, 2014
Cambio de sitio
Os anuncio que a partir de ahora, publicaré las nuevas entradas en mi página web (por fin me hice una) en la dirección http://www.nidea-soluciones.com en el apartado blog. Estáis todos invitados. Espero escribir con cierta periodicidad sobre temas interesantes.
Muchas gracias
viernes, noviembre 19, 2010
Acceder a controles creados dinámicamente desde servidor en ASP.net
Creación de Controles
Vamos a crear una página aspx con tres botones: uno que cree botones vía javascript, otro que cree cajas de texto desde javascript y otro que cree un textbox desde servidor:
La función javascript que crea los controles es la siguiente:
Unicamente creamos, en base al tipo, un input de tipo submit si es boton o un input de tipo text si el tipo es texto. Al ejecutar la página podemos crear tantos controles como queramos pulsando sobre los botones. El código del evento del botón botonCrearTexto se ejecuta en el servidor y crea un textbox dinámicamente:
La idea ahora es poder obtener los valores introducidos en los campos de texto y el botón que se ha pulsado:
Capturar el valor de los controles
El objetivo ahora es que al pulsar sobre cualquier botón podamos acceder a la información del botón pulsado y al contenido de los diferentes textBox que se hayan creado desde el servidor. El quid del meollo es la clase HttpContext, en la que se mantiene la información intercambiada entre el cliente y el servidor:
Dentro de la colección HttpContext.Current.Request.Form.AllKeys se encuentran todos los valores posteados desde el cliente, el control que realiza el post, el valor de los controles que disponen de valor, el viewstate de la página y el eventvalidation en el caso de controles de servidor. Podemos recorrer esta colección y acceder al valor de los input de tipo texto.
No tenemos en cuentra los controles que empiecen por __ porque son propios de asp.net.
El resultado es que al pulsar sobre cualquier botón, en pantalla mostramos los valores introducidos:
Conclusiones
Muchas veces nos vemos en el problema de controles dinámicos y no podemos resolverlo de forma fácil con asp.net. Con este artículo espero facilitaros la vida. Dependerá del desarrollador evolucionar esta solución para repintar los controles y asignarles el valor entre posts para que no desaparezcan.
Como siempre espero que os haya gustado esta pequeña aportación
lunes, octubre 11, 2010
Control de Usuario "Contador de filas de DataGridView" en C#
Podéis descargar el código de este control aquí.
El código
El quid del control es definir una propiedad pública en la que podamos definir el gridview y enlazar el evento DataBindingComplete.
La parte de diseño del control es la siguiente:
Insertar el control en el Formulario
Una vez creado el control lo insertaremos en el formulario, en la ubicación que queramos y especificaremos la propiedad GRIDVIEW para que el control obtenga el número de filas.
Podemos incluir tantos controles como queramos. En el momento en que se realice el evento databindingcomplete, el control actualizará el número de filas:
Conclusión
Este es un control muy sencillo pero que arregla una situación en la que habría que haber cambiado mucho código. Además, la utilización de controles de usuario permite un código sostenible y mejorable. En cualquier momento podemos asignarle más funcionalidades o cambiarle el aspecto y se aplicará a todas las pantallas sin tener que cambiar nada.
Como siempre, espero que os haya gustado y os sirva de utilidad.
martes, octubre 05, 2010
Plugin "Insertar HTML" para FCKEditor
Puedes descargar los códigos de este post aquí.
1. El Objetivo
El objetivo es conseguir lo siguiente, un botón en el editor que al pulsarse muestre la ventana de insertar HTML:
2. Ficheros necesarios
Lo primero es conocer la estructura para crear un plugin para FCKEditor. En realidad es muy simple, necesitaremos crear una carpeta en el directorio /editor/plugins (en este caso insertarHtml es el nombre de la carpeta) del FCKEditor que contenga los siguientes ficheros:
- fckplugin.js: fichero javascript en el que se definen las propiedades del plugin: formato de la ventana a mostrar, icono, nombre del plugin, ...
- insertarHtml.png: imagen para el icono del botón en el FCKEditor.
- insertarHtml.php: página que se muestra al pulsar el botón. En este caso es PHP pero puede ser perfectamente HTML o ASPX o lo que se quiera.
3. fckplugin.js
En este fichero se configuran los datos generales del plugin. Lo primero es registrar el comando:
FCKCommands.RegisterCommand( 'Insertar_Html', new FCKDialogCommand( 'Insertar código HTML', 'Insertar código HTML', FCKConfig.PluginsPath + 'insertarHtml/insertarHtml.php', 400, 400 ) ) ;
Indicamos qué página se abre en la nueva ventana, el tamaño de la ventana, el nombre que aparece en la ventana, etc. Lo siguiente es crear el botón:
var oHTMLItem = new FCKToolbarButton( 'Insertar_Html', 'Insertar código HTML en la posición del cursor' ) ;
oHTMLItem.IconPath = FCKConfig.PluginsPath + 'insertarHtml/insertarHtml.png' ;
y finalmente, registramos el elemento:
FCKToolbarItems.RegisterItem( 'Insertar_Html', oHTMLItem ) ;
4. insertarHtml.php
En el fichero insertarHtml.php es donde se genera la acción. Es la pantalla que se llama cuando el usuario pulsa sobre el botón. La página tiene una parte de presentación HTML y otra de código PHP. La primera parte es:
Es importante la parte inicial de javascript que es la que coge la referencia al FCKEditor que ha llamado a esta ventana. La parte de código es la que se ejecuta cuando se pulsa sobre el botón btnInsertar:
Lo que hacemos es generar el código javascript que inserta el código HTML en la posición del cursor y lo pasamos a la variable codigoJavascript, de la que se hace un echo en la parte HTML. Seguidamente, cerramos la ventana y volvemos a la pantalla del FCEditor.
5. fckconfig.js
Lo último es dar de alta el botón en la toolbar de nuestro FCKEditor y utilizarlo. Para ello tenemos que modificar el fichero fckconfig.js que se encuentra en el directorio raiz del FCKEditor. Lo primero que tenemos que hacer es añadir el plugin:
FCKConfig.Plugins.Add( 'insertarHtml' ) ;
y finalmente, incluir el comando en la toolbarset que estemos utilizando. Yo, p.e., he incluido el botón en la toolbarset default, al final:
FCKConfig.ToolbarSets["Default"] = [
['Source','DocProps','-','Preview','-','Templates'],
['Cut','Copy','Paste','PasteText','PasteWord','-','Print'],
['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'],
'/',
['Bold','Italic','Underline','StrikeThrough','-','Subscript','Superscript'],
['OrderedList','UnorderedList','-','Outdent','Indent','Blockquote','CreateDiv'],
['JustifyLeft','JustifyCenter','JustifyRight','JustifyFull'],
['Link','Unlink','Anchor'],
['Image','Flash','Table','Rule','Smiley','SpecialChar'],
'/',
['FontFormat','FontSize'],
['TextColor','BGColor'],
['FitWindow','ShowBlocks','-','Insertar_Html']
];
6. Conclusión
Este plugin es muy sencillo pero muy útil para aquellos proyectos en los que el usuario del FCKEditor no tiene conocimientos de HTML pero quiere incluir código de otras webs como pueden ser VIMEO, YouTube, Google Maps, Facebook. Cada día es más normal enlazar HTML en nuestras páginas y este plugin nos facilita la tarea.
Ejemplo: copio la localización de mi pueblo en google maps en la pantalla del plugin:
Al pulsar sobre Insertar HTML, se inserta el código donde tengo colocado el cursor:
Espero que os haya gustado este artículo. En breve más...
viernes, mayo 21, 2010
Control de acceso web "Dinámica de Tecleo"
Podéis descargar los códigos y el script de creación de base de datos aquí.
Antecedentes
A la hora de control el acceso a recursos compartidos, se utilizan tres técnicas distintas, basadas en tres premisas:
- Algo que el usuario sabe: esta es la premisa para el 99% de sitios, el usuario conoce un login y un password. Lógicamente, si un atacante consigue obtener esa información podrá suplantar la identidad. Este es, por norma general, el método más inseguro puesto que existen numerosas técnicas para robar las claves y, además, los usuarios no suelen usar claves alfanuméricas complejas porque son difíciles de recordar.
- Algo que el usuario tiene: esta es la segunda premisa en la que el usuario es poseedor de algo que solo tiene él. Los sistemas que se basan en esto son los que utilizan tarjetas de coordenadas o certificados digitales, por ejemplo. Este sistema es más complicado porque se suele combinar con el primero y el atacante tiene que, o bien obtener una copia de lo que el usuario tiene o robárselo, además de obtener el usuario y la contraseña.
- Algo que el usuario es: esta es la última premisa y es en la que se basa la seguridad biométrica. Las personas disponemos de rasgos o de actitudes que nos hacen únicos en el mundo. Usando esos rasgos físicos o esas actitudes o comportamientos que están impresos en nuestro cerebro se pueden generar patrones de seguridad que son mucho más complejos de romper que los dos anteriores. Usando este tipo de técnicas, el atacante, tendrá que copiar rasgos físicos (iris, retina, huella dactilar, forma de mano,...) o comportamientos (firma caligráfica, dinámica de tecleo,...) algo que en algunos casos es imposible y en otros en muy complicado.
Dinámica de Tecleo
La dinámica de tecleo es una técnica que se basa en el principio de que la acción de escribir en el teclado una palabra o frase (contraseña) muy frecuentemente hace que el acto de escribirla se convierta en algo inconsciente y automático. Esto provoca que ese gesto sea característico nuestro porque influyen tanto procesos mentales que se convierte en una especie de huella dactilar. Los parámetros que se tienen en cuenta a la hora de mesurar la dinámica de tecleo son dos, el tiempo de pulsación de cada tecla y el tiempo entre pulsaciones. En base a estos dos parámetros se pueden crear patrones de comportamiento que nos pueden decir si un usuario es o no es quién dice ser, independientemente de que la contraseña sea correcta o no.
Diseño del sistema de control de acceso
Lo que vamos a hacer es un sistema mixto de control. Por un lado, el usuario va a tener que introducir su usuario y contraseña, se validarán las credenciales y además se controlará la dinámica de tecleo de la contraseña. Dicho tecleo se comparará con un patrón del usuario para ver qué probabilidad hay de que sea realmente nuestro usuario y no un suplantador. Hay que tener en cuenta que cuando hablamos de biometría siempre consideramos probabilidades y no certezas. A la hora de configurar el sistema tendremos que elegir cuál es el umbral a partir del cuál consideraremos que el usuario es un suplantador. Cuanto mayor sea ese umbral, mayor será la seguridad pero más falsos negativos dará y cuanto menor sea el umbral, menor la seguridad pero menos falsos negativos. Cada uno modificará este umbral para que se adecue a sus necesidades y pruebas.
En nuestro sistema vamos a tener 3 módulos diferenciados:
- Módulo de captura de datos: es el encargado de capturar los datos de pulsación y tiempo entre pulsaciones en el lado del cliente. Este módulo estará implementado en Javascript.
- Módulo de entrenamiento: parte del sistema encargada de generar el patrón con el que se comparan las muestras a identificar.
- Módulo de autenticación: parte encargada de decidir si un usuario es quién dice ser o no.
Lo primero es la generación del patrón para cada usuario. Tomemos por ejemplo, la palabra MANOLO, para la dinámica de tecleo tenemos que tomar las siguientes muestras:
Tomaremos una muestre para el tiempo de pulsación de cada letra y el tiempo entre pulsaciones. Para generar nuestro patrón tomaremos N muestras de la palabra clave MANOLO escritas por nuestro usuario, cada una de las muestras tendrá 2*n-1 posiciones siendo n el número de caracteres de la palabra. En este caso cada muestra o vector que guardamos tendrá 11 posiciones:
Una vez que disponemos de las muestras, tendremos que obtener un vector con las medias de cada posición y otro con las varianzas de cada posición.
El patrón del usuario será, por lo tanto, un vector de 11 posiciones con la media de cada uno de los tiempos de pulsación y tiempo entre pulsaciones y otro con un vector de 11 posiciones con las varianzas de cada uno de los tiempos. Este patrón lo almacenaremos en una base de datos para, posteriormente, poder realizar la comparación en el control de acceso.
Función de Scoring
La función de Scoring es la encargada de determinar el grado de similitud entre la clave introducida por el usuario que se quiere autenticar y el patrón almacenado en la base de datos.
Una vez obtenido el vector de valores SCORE, realizamos una media entre ellos para obtener un solo valor a comparar:
Este valor se comparará con el valor de UMBRAL definido en el sistema y determinará si el usuario es o no es quién dice ser.
Diseño Real del Sistema
Vamos a ver cómo, podemos diseñar en la vida real un sistema de control de acceso de este tipo. El flujo del sistema es el siguiente:
Para la implementación del sistema vamos a utilizar ASP.net (c#) como lenguaje de servidor, SQL Server como gestor de base de datos y Javascript para el control del tecleo.
Modelo de Base de Datos
En nuestro sistema vamos a tener dos tablas, una para la información de las claves del usuario y otra para almacenar los patrones:
Interfaz Web
Para nuestro ejemplo, se ha unificado en una sola interfaz el entrenamiento del sistema junto con el acceso al mismo:
El usuario tendrá que introducir su usuario y contraseña y, además, la frase de control que se ha utilizado para generar el patrón. En la parte de entrenamiento, el usuario puede ir introduciendo nuevas muestras, cuantas más muestras se tengan mayor será el acierto del sistema.
Cuando se pulsa sobre el botón "Acceder", el sistema devuelve en una pantalla tres valores:
- Score Total: valor devuelto por la función de Scoring teniendo en cuenta tanto el tiempo de pulsación como el tiempo entre pulsaciones.
- Score Pulsación: valor teniendo en cuenta solamente el tiempo de pulsación.
- Score Entre: valor teniendo en cuenta solamente el tiempo entre pulsaciones.
En el lado del cliente, se ejecuta la lógica necesaria para capturar los datos de las muestras y enviarlos al servidor. Estas funciones se encuentran en Javascript (ver los códigos del proyecto) y preparadas para los exploradores más utilizados. El flujo de llamadas es el siguiente:
Para el caso de la comprobación del acceso al sistema, las llamadas Javascript son las siguientes:
Lógica del Servidor
Toda la lógica de la generación del patrón, la comprobación del usuario y la generación de la función de Scoring se realiza en el servidor. La comunicación entre el cliente y el servidor se realiza mediante llamadas a un servicio web llamado DinamicaTecleo.asmx ell cuál dispone de dos métodos públicos: RecibirMuestras y ComprobarAcceso.
El método RecibirMuestras es el encargado de recibir las muestras, formatearlas y guardarlas en base de datos:
El método ComprobarAcceso es el encargado de comprobar que el usuario es quien dice ser o no. Este método devuelve los tres valores que se muestran por pantalla:
Los datos del patrón se almacenan en la base de datos de la siguiente manera:
Se guardan las muestras de entrenamiento para cada usuario separadas por comas, en una columna los milisegundos de pulsación de cada tecla y en la otra los milisegundos entre pulsaciones.
Conclusión
Las conclusiones que se obtuvieron con los individuos que realizaron las pruebas fueron que, efectivamente, la dinámica de tecleo es una buena técnica complementaria al control mediante usuario y contraseña. Para que el sistema sea efectivo, la fase de entrenamiento debe ser extensa para disponer de muchas muestras. También es bueno eliminar aquellas muestras muy alejadas de la media.
El sistema funciona de forma óptima cuando la frase de control se compone de letras y números sin sentido puesto que es cuando el cerebro tiene que pensar qué teclas pulsar y tiene que mover las manos de su posición natural. En el caso de frases con sentido es más fácil la suplantación porque la posición de las manos y la cadencia es más natural.
Un fallo que no pude resolver en el sistema se produce cuando el usuario escribe tan rápido que antes de soltar una de las teclas ya ha pulsado la siguiente, generando un tiempo de pulsación negativo. Mediante javascript no fui capaz de controlar ese caso y obtenía un error. Si alguien lo corrige le agradecería que lo comentara.
En fin, creo que la dinámica de tecleo es un sistema fácil y barato de control biométrico, no necesitamos aparatos externos ni inversiones en dinero. Puede introducirse de forma transparente en un sistema ya establecido y puede aumentar el nivel de seguridad exponencialmente.
Espero que os haya gustado este artículo.
sábado, agosto 22, 2009
twitter desde línea de comandos
¿Y qué es lo que le preocupa a un usuario de GNU/Linux cuando conoce Twitter? ¿me quedaré enganchado a ésto por el resto de mis días? ¿seré hallado con 80 años muerto relatando mi propia agonía en 140 caracteres? ...
... pues no ...
... la verdadera pregunta es ... ¿se podrá hacer ésto desde línea de comandos? Y obviamente hay como otras 8000 personas a las que eso ya se les ocurrió antes, así que la respuesta a vuestras plegarias sale con un googleo simple.
Esta es una entrada chorra (tengo algunas más interesantes en mente y proyecto), así que sólo pondré las 2 formas que me han resultado más divertidas.
Fórmula 1 -- postear en twitter usando curl
Gracias al API de twitter, se puede usar curl para hacer un sencillo micro-post con un comando tan chorra como...
curl -u usuario:contraseña -d status="Tu mensaje" http://twitter.com/statuses/update.xml
Fórmula 2 -- Twitter Tools
Esta aplicación escrita en python es la que más me ha gustado para esta tarea (sólo he inspeccionado 4 o 5, tampoco es que tenga mucho criterio). Es sencillita y te permite ver tu twitter con sólo hacer...
¿Fácil no? Veamos 2 formas de instalarla.
La primera es la más sencilla, y consiste en instalar el paquete apropiado desde línea de comandos. Algo tan fácil como...
sudo aptitude install python-twitter
La otra forma consiste en irse a la página web (http://mike.verdone.ca/twitter/) y descargarse el código fuente (en tar.gz). Luego lo descomprimimos con...
tar -xvzf twitter-.tar.gz
ahora nos intalamos el paquete python-setuptools con...
sudo aptitude install python-setuptools
accedemos a la carpeta twitter dentro de la carpeta descomprimida y desde dentro hacemos...
sudo easy_install twitter
La ventaja de usar la versión descargada es que como es lógico, te descargas la última versión disponible que siempre va a estar por encima de la disponible en los repositorios. La desventaja, que no tienes la actualización automática que te dan los repositorios. Para algo con tan poco calado e importancia, yo personalmente recomiendo usar la instalación desde los repositorios.
La configuración
Para ahorrarnos el tener que poner el usuario y contraseña cada vez que vamos a consultar o escribir en nuestro twitter, podemos crear un fichero en ~/.twitter que tenga un contenido como el siguiente...
[twitter]...que hará que no tengáis que introducir usuario y clave, y además pondrá de colorines el resultado de las lecturas de forma que será más entretenido de leer :).
email: mi_usuario
password: mi_clave
format: ansi
prompt: '[cyan]twitter[R]'
El resultado
Y ahora el resultado. Un ejemplo...
twitter set "Python Twitter Tools mola, lo recomiendo realmente a todos/as"produciría un resultado que podríamos ver desde línea de comandos con el comando "twitter" como os pongo a continuación...

Y visto desde la web de twitter...

Y bueno, para quienes finalmente decidáis usar este sistema de microblogging ya iréis descubriendo que desde la Ptt (Python twitter tools) se pueden hacer muchas más cosas. Pero eso ya os lo dejo a vosotros/as.
Un abrazo a todos/as.
lunes, agosto 10, 2009
Códigos del motor de informes dinámicos en PDF
Podéis descargar el proyecto desde aquí. Espero que os sea de utilidad.
sábado, junio 27, 2009
Sistema de plugins en C# usando Reflexión
La idea es disponer de un sistema de plugins para un CMS (gestor de contenidos) de forma que cada plugin sea autogestionado y no haya que tocar nada del sistema a la hora de introducir un nuevo plugin, salvo lógicamente introducir su definición en base de datos. En el proyecto que implementé, los plugins eran elementos visuales que permitían realizar la maquetación de las páginas mostrando el contenido de base de datos de diferentes formas (contenido tabulado, histórico, contenido con scroll, publicidad, etc.).
No voy a entrar en cómo implementar toda la estructura del sistema de elementos visuales (será para un artículo posterior), lo importante es cómo podemos, acceder a clases de c# sin utilizar elementos tipados. Es decir, lo normal para instanciar un objeto es utilizar la siguiente nomenclatura:
TipoObjeto miObjeto = new TipoObjeto(parametros);
En el caso de un sistema dinámico de plugins, no podemos utilizar esa nomenclatura porque no sabemos a priori la clase del objeto a utilizar. En esta situación, la reflexión se nos ofrece como técnica perfecta.
Implementación del sistema de plugins
Los plugins se dan de alta en base de datos, cada proyecto puede utilizar su propia definición de tablas. En mi caso, creé dos tablas, una para guardar la definición del elemento y otra para almacenar las propiedades modificables del elemento. Por ejemplo, uno de los plugins era para introducir un bloque de código HTML directamente en la página. La definición de este elemento es:
y la definición de sus propiedades es:
Lo importante de los datos almacenados para cada elemento es el campo "clase" en el que se guarda la clase de código que implementa la funcionalidad de este elemento. En este caso, la clase es plugins.elementoHtml. Este campo se utiliza luego para la reflexión.
Interfaz de los plugins
Este paso no es necesario pero es bueno que todas las clases que se encarguen de plugin implementen una interfaz obligando a que el método público de acceso sea siempre igual y no haya fallos de parámetros. En mi caso, la interfaz definía los siguientes métodos:
La interfaz define dos métodos, uno para obtener el código html del plugin cuando se debe insertar en el centro de la página y otro para cuando se debe insertar en el lateral de la página. Los parámetros que se pasan son el id particular para cada elemento y un object extras con parámetros extras que hicieran falta en cada caso.
El quid de la cuestión
En cada proyecto, obtendremos referencias a nuestros plugins de la manera que queramos. El quid de la cuestión se encuentra en las líneas que utilizan la reflexión para acceder a los métodos de la clase de cada plugin:
Lo que hacemos es:
- Obtener el campo "clase" de la base de datos y llamar al método Type.GetType para obtener el tipo del elemento.
- A través de reflexión podemos obtener acceso al constructor e invocarlo pasándole los argumentos necesarios, en este caso null porque no hay argumentos.
- Obtener la información del método "Renderizar" que es el que utilizamos de cada clase y que define la interfaz.
- Invocamos el método pasándole el objeto inicializado mediante el constructor y le pasamos un vector de objects con los parámetros que el método está esperando.
- El resultado del método (en este caso un string), se obtiene haciendo un cast a string.
La reflexión es una herramienta muy potente dentro del lenguaje .net que permite llamar a métodos y objetos sin conocer previamente el tipo. Esto permite generar sistemas como el descrito de una forma eficiente. El problema estriba en que, inicialmente no es un tipo de programación sencilla y requiere un tiempo para acostumbrarse a cómo funciona.
Espero que os haya gustado este artículo y que os sirva esta idea para vuestros desarrollos. En mi caso, me ha sido de mucha utilidad.
domingo, junio 14, 2009
Problema de expiración de la sesión en ASP.net
Finalmente, por fin he encontrado un rato para escribir un post en el blog. Tenía en mente varios temas pero al fin me he decidido por éste que me parece bastante interesante y útil para aquellos que desarollamos aplicaciones en asp.net. Pongámonos en situación, cuando escribimos aplicaciones, una de las herramientas más utilizadas para mantener la persistencia de los datos es la sesión, almacenamos en sesión tablas con las que trabaja el usuario por pantalla, ids de filas, usuarios, variables, etc. todo ello para que cuando el usuario pulse algún botón y se realice un postback, podamos realizar las acciones correspondientes. Es decir, la sesión nos mantiene conectado con el usuario en un entorno desconectado. El problema viene cuando el tiempo de sesión expira, si el usuario no ha realizado ninguna acción pasados x minutos (5 por defecto), el servidor (IIS) elimina su sesión. En el momento en que el usuario pulse un botón y se vaya al servidor, nos encontraremos con que aquellos datos que habíamos guardado en la sesión ya no existen y (dependiendo de cómo controlemos esta situación) saltará una excepción en algún punto de nuestro código, echándonos fuera de la aplicación, o saltando una fantástica pantalla amarilla o algo parecido.
En aplicaciones en las que las operaciones se realicen en el servidor no vamos a tener problemas con la sesión porque cada vez que el usuario realice un postback, la cuenta de expiración de la sesión se reinicirá. En el caso que hagamos aplicaciones que hagan uso de la lógica del cliente, tipo blogs, editores wysiwyg, o que el usuario realice operaciones largas en el explorador sin tener que ir al servidor, el tiempo de expiración de la sesión se convierte en un gran problema para el programador y en una gran molestia para el cliente. Imaginaos escribiendo un post en un blog y que cuando lleváis 30 minutos escribiendo, habéis acabado el post le dais a guardar y salta una excepción, perdiendo todo el trabajo...
Posibles soluciones a este problema
Existen varias soluciones a este problema, que dependiendo de dónde esté alojada nuestra aplicación nos serán factibles o no.
Solución 1: Web.config
La solución más fácil es incorporar en nuestro web.config la etiqueta "sessionState" con el atributo "timeout" indicándole el número de minutos que deseamos que se mantenga la sesión (dentro de la sección system.web):
En este caso, hemos aumentado el tiempo de sesión a 60 minutos, antes de que el servidor la elimine. Sin embargo, me he encontrado alojamientos en los que, aunque en mi web.config tenga incluido este tag, el tiempo de sesión viene marcado por el servidor sin posibilidad de cambiarlo desde aquí.
Solución 2: Pool de aplicaciones
La segunda solución con la que contamos es la de crear un pool de aplicaciones en el IIS para nuestra aplicación. En dicho pool podemos especificarle el tiempo de sesión que queremos. Además, al crear un pool propio, se lanza un proceso en el sistema para nosotros solos. Esto es bueno en el caso de alojamientos compartidos en los que en el mismo proceso puede haber muchas aplicaciones ejecutándose. Siempre es aconsejable tener nuestro propio pool de aplicaciones, el cual se crea de la siguiente manera:
1. Desde el administrador de IIS, pulsamos con el botón derecho sobre "Grupos de aplicaciones" y seleccionamos un nuevo grupo:
2. Le damos un nombre al nuevo grupo de aplicaciones:
3. Lo siguiente es configurar las opciones de rendimiento para este grupo de aplicaciones, como la cantidad de memoria a asignar, el tiempo de reciclado del proceso o el tiempo de sesión para este grupo, entre otras opciones:
4. Por último, a un sitio o directorio web, le asignaremos este grupo de aplicaciones desde sus propiedades:
Solución 3: Servicio web de Echo
Para implementar las dos soluciones anteriores necesitamos tener control sobre el servidor (cosa que no siempre es así). En el caso que tengamos alojamientos compartidos, podemos utilizar esta opción (es la que utilizo ahora). Normalmente, un portal web dispone de dos partes, la pública (en la que normalmente se puede funcionar con cookies) y la privada en la que trabajaremos con sesiones. Es en la parte privada donde utilizaremos esta opción. La idea es implementar un servicio web que simplemente realice un eco, reciba un parámetro y lo devuelva. Habilitamos la sesión para el servicio web con lo que cada vez que se llame a este servicio, la cuenta de expiración de la sesión se reinicirá. Desde las página de gestión se llama, vía AJAX, periódicamente (yo lo tengo cada 50 segundos) a dicho servicio web para que no reinicie la cuenta. De forma esquemática, la solución es la siguiente:
El código del servicio web es el siguiente:
Tenemos que introducir el using System.Web.Script.Services para poder utilizar este servicio web vía AJAX. Además, la definición del servicio web incluye la sentencia [WebMethod(true)] indicando que se utilizará la sesión en ese método del servicio web. Para llamar a dicho método desde la página maestra (lo normal) o desde cualquier página de nuestra aplicación utilizaremos el siguiente código:
a. Incluir una referencia web al servicio web creado.
b. Dar de alta el servicio web mediante el ScriptManager de la página
En la propiedad Path pondremos la ubicación del fichero .asmx (servicio web). Si, al crear el servicio web, separados el código del fichero, se creará un fichero .asmx con la definición del servicio web donde le hayamos dicho y un fichero .cs con los códigos dentro de la carpeta App_Code.
c. Crear la función Javascript que llama al servicio web
d. Crear el temporizador para que se repita la llamada cada x segundos
Ponemos la función en el onload de la página para que se ejecute al iniciar la página. En este caso esta puesto que se repita la llamada cada 50 segundos (50.000 milisegundos)
Conclusión
Esta última es una solución sencilla que nos puede servir en cualquier entorno en el que trabajemos con aplicaciones asp.net. Utilizando el servicio de echo, nos aseguramos que la sesión del usuario no va a expirar independientemente del tiempo que esté sin hacer ningún postback. En el caso que el usuario cierre la ventana del explorador, se deja de llamar al servicio con lo que la sesión expirará en los 5 minutos correspondientes. Por supuesto, siempre podemos colocar el botón de cerrar que matará la sesión. Como siempre, espero que os sea de utilidad este post y gracias por leer este blog (ya sois un montón).
martes, abril 07, 2009
Traductor de Artilugios en ASP.NET
La página de demostración la podéis encontrar aquí.
El comprimido con los códigos del proyecto os lo podéis descargar de aquí.
Hacía tiempo que no escribía un post pero, finalmente, he conseguido un poco de tiempo. En este post lo que os voy a contar es un pequeño pero muy útil, por lo menos para mí, proyecto que hice en su día y que voy mejorando y modificando a medida que lo necesito. El proyecto se llama "Traductor de Artilugios" (un nombre raro, pero es que no tenía y se lo acabo de poner) y es un generador de objetos complejos para gestores de contenido.
Un generador de qué?
La idea la cogí de Wordpress, el cual permite introducir ciertos sinónimos en el editor de post que posteriormente son traducidos a un html más complejo (video y música). Es una forma muy sencilla de poder introducir componentes flash que precisan de etiquetas object o embed o código html elaborado.
Con esta idea me hice una pequeña clase TraductorObjetos.cs que generaba ese código en las páginas de forma dinámica. Inicialmente lo hice para video flash (flv en el servidor) y videos de youtube, luego le metí un reproductor mp3, galeria javascript, ventanas modales, galeria flash. A medida que voy necesitando algo lo voy metiendo.
Sí, muy bien, pero ¿cómo funciona?
El funcionamiento es el siguiente:
a. Desde un editor WYSIWYG (yo utilizo FCKEditor) se introduce el texto de la entrada y se incluye el sinónimo del artilugio. En este caso, voy a meter un video flash por lo que utilizo el sinónimo video. La cadena que utilizo es @video [urlVideo]=[Yeguada1.flv]@ indicando que la url donde se encuentra el video es yeguada1.flv.
b. Ese código se guarda en base de datos. A la hora de renderizar el código en pantalla, se llama a la función Traducir de la clase TraductorObjetos.cs para que rastree el código HTML guardado en base de datos en busca de artilugios. La definición de los artilugios se guarda en una tabla de base de datos con dos campo (nombre y código).
c. Una vez localizado el sinónimo en la cadena de HTML, se sustituye dicha cadena por el valor de base de datos, poniendo los parámetros en su lugar correspondiente. Los parámetros en base de datos se identifican por el símbolo @ (p.e. @urlVideo es un parámetro que será sustituido en tiempo de ejecución).
d. Finalmente, se devuelve el código traducido para que sea renderizado en pantalla.

Extensibilidad
Es muy fácil incluir más elementos en el proyecto, basta con insertar el código a traducir en la tabla con los parámetros correspondientes y listo. Tened en cuenta que todos los ficheros extras utilizados (javascript, flash, hojas de estilo,...) por lo artilugios se localizan en la carpeta "extras" y se deben cargar en la página para que funcionen correctamente.
Conclusión
Espero que este proyecto os sirva tanto como me sirve a mi en mis desarrollos. Con una simple línea, el usuario es capaz de generar códigos muy complejos que de otra forma no podría hacerlo. Os he dejado los códigos del proyecto así como una página de demo donde podéis probar con las diferentes cadenas de sinónimos que tengo puestas.

