lunes, 22 de diciembre de 2014

Contenido de DevExpress Round Panel en Razor

Si ya han usado el Round Panel de Developer Express para MVC, habrán notado lo tedioso que es poner el contenido de este, ya que según el ejemplo que brindan en la documentación oficial, debe establecerse mediante una cadena de caracteres:

@Html.DevExpress().RoundPanel(settings => {
       settings.Name = "roundPanel";
       settings.ShowHeader = true;
       settings.HeaderText = "ASP.NET MVC";

       settings.SetContent(@"<h4>Lorem Ipsum</h4>
<p><span class="inicio">Lorem ipsum</span> dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</p>");
    }).GetHtml()

Esto deja de lado las facilidades que brinda Razor como motor de vista, que permite integrar el código HTML con C# de forma fácil y legible. Además, se vuelve más complicado a medida necesitamos añadir más componentes, o controles más complejos dentro de él. Sin embargo, existe una solución práctica para esta situación: el uso de helpers.

La sintaxis @helper permite crear métodos de ayuda re-usables dentro de las vistas, los cuales permiten encapsular código fuente y HTML utilizando la sintaxis de Razor.

Mediante la sintaxis @helper, podemos colocar el contenido del panel dentro de una función helper separada;
@helper ContenidoPanel() {
    <h4>Lorem Ipsum</h4>
    <p><span class="inicio">Lorem ipsum</span> dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</p>
}
Y luego renderizarlo dentro del panel, siempre en la misma vista, así:
@Html.DevExpress().RoundPanel(settings => {
       settings.Name = "roundPanel";
       settings.ShowHeader = true;
       settings.HeaderText = "ASP.NET MVC";
       settings.SetContent(ContenidoPanel().ToHtmlString());
    }).GetHtml()
O así:
@Html.DevExpress().RoundPanel(settings => {
       settings.Name = "roundPanel";
       settings.ShowHeader = true;
       settings.HeaderText = "ASP.NET MVC";
       settings.SetContent(() => ContenidoPanel().WriteTo(ViewContext.Writer));
    }).GetHtml()

Esto facilita la legibilidad del código, y además permite definir un contenido mucho más complejo, utilizando todas las facilidades que Razor puede brindar.

martes, 9 de diciembre de 2014

Aplicaciones híbridas para móviles

Hace poco más de un año empecé a desarrollar aplicaciones móviles, y por mi experiencia previa con sitios web, opté por el desarrollo de aplicaciones HTML híbridas en lugar de nativas, para hacer el desarrollo más rápido. Pero veamos...

¿Qué son las aplicaciones híbridas?

Las aplicaciones móviles comúnmente conocidas como híbridas son aplicaciones desarrolladas utilizando tecnologías web del lado del cliente (HTML, Javascript, CSS), pero que se instalan en los dispositivos móviles, y pueden acceder a las funcionalidades de hardware de este a través de APIs provistas por frameworks especiales (como Phonegap/Cordova, Sencha).
Estas aplicaciones usualmente se muestran en un componente visor de web provisto nativamente por el sistema operativo del móvil, los cuales proveen las funcionalidades de un navegador web relativamente moderno (soporte para HTML5 y CSS3).

¿Cuáles son sus ventajas?

La principal ventaja de las aplicaciones híbridas es que se basa en tecnologías web ampliamente conocidas, las cuales existen desde hace largo tiempo y han crecido y mejorado a lo largo de su desarrollo. Esto proporciona una sola interfaz de programación para multiples plataformas, a través del uso de frameworks especiales como Phonegap/Cordova, que porporcionan la infraestructura necesaria para crear de forma automática las respectivas aplicaciones nativas que encapsulan el contenido web, además de proveer APIs que estandarizan y simplifican el acceso a las funcionalidades del dispositivo.
El uso  de tecnologías web también ahorra la curva de aprendizaje de los desarrolladores que ya poseen conocimiento en el área, lo que puede facilitar y agilizar el desarrollo de aplicaciones móviles. También permite reducir el costo de contratar personal especializado en el área móvil para cada sistema operativo móvil del mercado (iOS, Android, Windows 8, Tizen, etc.), ya que cada plataforma hace uso de distintas herramientas y lenguajes de programación.
Adicionalmente, y como apreciación personal, el desarrollo de interfaces de usuario es más fácil, personalizable y escalable con el uso de HTML5 y CSS3, que son tecnologías especializadas para la presentación de la información. Y la disponibilidad de media queries en CSS facilitan el diseño responsivo, que permite adaptar la vista a la gran variedad de pantallas y resoluciones de dispositivos que existen en el mercado.

¿Existen desventajas?

Hasta acá todo parecía felicidad, ¿verdad? Lo cierto es que como en toda tecnología, existen desventajas que hay que tomar en cuenta. La principal desventaja que presentan las aplicaciones híbridas es la capa extra de virtualización que existe: la aplicación en realidad está corriendo sobre una aplicación nativa, en última instancia. Esto se traduce en una disminución en el desempeño de la aplicación, en contraparte de las aplicaciones nativas, lo cual se hace más notorio a medida disminuyen las características del hardware.
Sumado a esto está el hecho de que se depende del componente visor de web disponible en la versión del sistema operativo, lo cual puede disminuir aún más el desempeño, y disminuir el soporte de componentes HTML5 e instrucciones CSS. Además, hay que recordar que los desarrolladores del visor web no tenían como objetivo inicial perfeccionarlo para la ejecución de aplicaciones híbridas.
También, a pesar de que los frameworks especiales como Phonegap/Cordova, Sencha Touch y otros cuentan con una extensa API y plugins para el acceso al hardware (cámara, GPS, bluetooth, etc.) y funciones especiales del sistema operativo (acceso a archivos, identificación, almacenamiento, etc.), aún hay partes para los cuáles no existe un soporte completo (como servicios de fondo asíncronos entre otros).
Finalmente, hay que tomar en cuenta también el aspecto de la seguridad. En agosto de este año (2014) se emitió un comunicado por parte de Apache Cordova informando de vulnerabilidades en su framework, que obligaron al lanzamiento de una nueva versión menor de este para solucionar estas debilidades. Con esto no quiero decir que las aplicaciones híbridas sean inseguras, ni que las nativas sean seguras, ya que en realidad toda pieza de software puede presentar vulnerabilidades, mientras hayan humanos que las hagan y ataquen. Simplemente es que al existir una capa de abstracción más entre las aplicaciones, se abre la posibilidad a más puntos de ataque que hay que defender.

¿Ser o no ser?

Vamos a la pregunta del millón: ¿desarrollo una aplicación nativa o híbrida?. Creo que hay muchas respuestas posibles y válidas para esta pregunta, pero al menos personalmente, estos son los aspectos que tomo en cuenta para decidir si desarrollar una aplicación híbrida o no:
  • ¿Es una aplicación intensamente gráfica? Si lo es demasiado, es mejor utilizar la tecnología que presente un mejor desempeño, y en este caso, al menos hasta el momento, la mejor alternativa es una aplicación nativa. Pero si es una aplicación no tan gráfica, como por ejemplo una app informativa, o incluso hasta un juego ligero en 2D, entonces una aplicación híbrida puede ser una buena opción.
  • ¿El sistema operativo y hardware objetivo es viejo o reciente? A medida es más nuevo, se brinda un mayor soporte a las tecnologías web y aplicaciones híbridas. Si es más viejo, habría que evaluar si soporta o no las características que tengamos en mente para nuestra aplicación.
  • ¿Puedo acceder a todas las funcionalidades que necesito? Tomando como base que una aplicación nativa puede acceder al 100% de funcionalidad disponible, habría que investigar y evaluar si el framework que utilizaré para mi aplicación posee las funciones que requiero, o aunque no las posea, es posible desarrollarlas y añadirlas (y por supuesto cuento con el tiempo para hacerlo).
  • ¿Tengo poco tiempo y solo conozco tecnologías web/nativas? Creo que es el punto de menor relevancia de los mencionados, pero lo suficientemente importante para tener en consideración. ¿Por qué? Porque tanto el desarrollo de aplicaciones nativas como el uso de frameworks para aplicaciones híbridas posee su curva de aprendizaje. Además, el desarrollo de aplicaciones híbridas requiere siempre cierto conocimiento de las herramientas nativas subyacentes, principalmente para la preparación del entorno de desarrollo (SDKs, dispositivos de prueba, depuración, etc.). Y por qué no, esta prodría ser una buena oportunidad de aprender una tecnología y alternativa de desarrollo que no conocía, ya sea nativa (si viene del entorno web) o híbrida (si ya posee experiencia en el desarrollo nativo).

jueves, 6 de noviembre de 2014

WP - SQL Server Snippets – Tablas con columna autonumérica

Este primer snippet consiste en una consulta para obtener las tablas de la base de datos en uso (es decir, la base de datos seleccionada actualmente), que poseen una columna autonumerada (IDENTITY), incluyendo el nombre de dicha columna.

La consulta en T-SQL es la siguiente:

USE [BASE_DATOS]
GO
 
SELECT
TABLA.object_id                                    AS object_id,
SCHEMA_NAME(TABLA.schema_id) + '.' + TABLA.name    AS tabla,
COLUMNA.name                                    AS columna_identity
FROM sys.tables TABLA
INNER JOIN sys.columns COLUMNA ON COLUMNA.object_id=TABLA.object_id
WHERE TABLA.type='U'
AND TABLA.name NOT LIKE 'sys%'
AND COLUMNA.is_identity = 1
ORDER BY SCHEMA_NAME(TABLA.schema_id), TABLA.name

A modo de una pequeña descripción, básicamente lo que se hace es consultar las tablas del sistema sys.tables (que contiene información de las tablas), y sys.columns (que contiene información de las columnas). Ambas tablas se unen a través del object_id de la tabla.

Luego, en la cláusula WHERE se filtran los resultados para solamente incluir tablas creadas por el usuario (tipo “U” y que no inicien con “sys”, para descartar la tabla sys.diagrams), y de dichas tablas solamente tomar las columnas con la propiedad IDENTITY (is_identity = 1). Cabe señalar que una tabla en SQL Server puede tener solamente una columna IDENTITY, por lo que la consulta no devolverá más de una fila por tabla.

Nótese además que se obtiene el nombre del esquema de la tabla, a través de la función SCHEMA_NAME, y se concatena con el nombre de la tabla, para obtener el nombre completo de la tabla dentro de la base de datos.

Finalmente, y de forma opcional, se ordenan los resultados por esquema y nombre de tabla, para que se muestren de la misma forma que se muestran en el explorador de objetos del SQL Server Management Studio.

Hasta donde he probado, el script funciona para SQL Server 2005 – 2012.

Espero que les sea de utilidad. Saludos, y como dicen por allí, “happy coding!”.

WP - Atributo de MVC para filtrar acciones para solicitudes AJAX

Esta entrada ha sido reposteada por error, pero utilizando Gists para mejor legibilidad del código, acá: http://itsouvenirs.blogspot.com/2018/01/wp-atributo-de-mvc-2-para-filtrar.html

Ya llevo un par de meses trabajando con ASP.NET MVC Framework 2, y debo decir que me ha encantado. Y sé que van por la versión 4, pero en el trabajo contamoscon Visual Studio 2008, así que hay que aprovechar lo que se tiene, y debo decir que en realidad no es poco.

En esta ocasión quiero mostrar una forma de crear un atributo de filtrado para acciones que deben ser ejecutadas solamente mediante solicitudes Ajax. Esto es útil para acciones que deseamos utilizar exclusivamente para estas solicitudes, y que queremos que el usuario común tenga acceso a ellas solamente a través de esta forma, mediante alguna interacción con la interfaz de usuario (UI), por ejemplo.

Primero, es necesario encontrar una forma de identificar que el tipo de solicitud es XML HTTP request, que es la clase de solicitudes que se hacen mediante AJAX. El objeto HttpRequest del que disponemos en una aplicación ASP.NET no cuenta con un método propio para identificar este tipo de solicitud, por lo que es necesario trabajar un poco en esta parte. Para ello, crearemos un método de extensión que se encargue de verificar esto. El método que presento a continuación es prácticamente una copia de la respuesta de Charlino a la pregunta de StackOverflow titulada How to check if request is ajax or not in codebehind – ASP.NET Webforms, que a su vez se basa en el código fuente del MVC Framework (que es open source, o código libre, por cierto).

using System;
using System.Web;
 
namespace MiProyectoMVC.Extensiones
{
    public static class HttpRequestExtensions
    {
        public static bool IsAjaxRequest(this HttpRequest request)
        {
            if (request == null)
            {
                throw new ArgumentNullException("Request es nulo");
            }
 
            return (request["X-Requested-With"] == "XMLHttpRequest") || ((request.Headers != null) && (request.Headers["X-Requested-With"] == "XMLHttpRequest"));
        }
    }
}
Como puede observarse, el método revisa directamente el encabezado del request, para verificar el tipo de solicitud. Si el tipo de solicitud es XMLHttpRequest, devuelve verdadero, y falso en caso contrario.

Actualización: Existe un método de extensión para la clase HttpRequestBase en el espacio de nombres System.Web.Mvc, con el mismo nombre y funcionalidad que el del método propuesto (IsAjaxRequest). Podría usarse este en vez de crear una nueva extensión, solamente incluyendo el espacio de nombres System.Web.Mvc.

Teniendo este método disponible, podemos proceder a crear el atributo de filtro. Este es un atributo de filtro convencional, por lo que será descendiente o derivado de la clase ActionFilterAttribute. Como se observa a continuación, el atributo es bastante simple:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using MiProyectoMVC.Extensiones;
 
namespace MiProyectoMVC.Controllers.Atributos
{
    public class XmlHttpRequestAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (!filterContext.HttpContext.Request.IsAjaxRequest())
            {
                //Si no es solicitud Ajax, mostramos a una página de error completa
                filterContext.Result = new ViewResult() { ViewName = "Error" };
            }
            base.OnActionExecuting(filterContext);
        }
    }
}
Como puede observarse, todo el proceso de verificación se realiza sobrecargando el método OnActionExecuting, que se ejecuta justo antes de proceder a ejecutar la acción. Acá hacemos uso del método de extensión para verificar si la solicitud (request) es de tipo Ajax, y si no lo es, devolvemos como resultado una vista completa, que bien puede ser una página de error personalizada. Cabe mencionar que digo vista completa porque el resultado a generar es un ViewResult. Dado que sabemos que no es una solicitud Ajax, lo común no sería devolver una vista parcial, sino una página completa (.aspx). También, en vez de devolver de una sola vez la página de error, podríamos redireccionar hacia otra acción que consideremos conveniente, a través de un RedirectResult.

Finalmente, decoramos la acción que deseamos filtrar con el atributo que hemos creado, de la siguiente manera:

//...
 
namespace MiProyectoMVC.Controllers
{
    public class EjemploController : Controller
    {
        // ...
 
        [XmlHttpRequest]
        public ActionResult IndexPartial()
        {
            //...
            return PartialView("IndexPartial");
        }
 
        //...
    }
}
Acá les dejo un enlace que encontré por allí, que tiene varios ejemplos de atributos de filtro de acciones bastante interesantes, que puede que les sean de utilidad: Creating Custom Action Filters in ASP.NET MVC


NOTA: Aunque este atributo fue elaborado y probado en MVC Framework 2, de igual forma es aplicable para las versiones 3, 4 y 5 (posiblemente) del framework.


Cualquier comentario será bien recibido, y como dicen por allí, Happy coding!

martes, 4 de noviembre de 2014

WP - Resposive Web Design

La ventaja y objetivo de los diseños responsivos (Responsive Web Design, RWD) es que la página web se pueda ver bien desde dispositivos con casi cualquier resolución (smartphones, tablet, netbooks, PCs, televisores). He de comentar que desde hace algunos años quise hacer algo así sin éxito, pero no conocí este término de RWD hasta que hace un par de meses leí un post de  en TechRepublic, titulado "How to get started with Responsive Web Design". Les recomiendo los artículos de este señor sobre desarrollo web, ya que incluyen nuevos conceptos y ejemplos prácticos en este ámbito. Que Dios les bendiga.

Publicado originalmente el 20/09/2012, en http://itsouvenirs.wordpress.com/type/aside/
Como dato curioso, esta entrada la publiqué al cambiar el tema de mi blog de Wordpress a uno responsivo, llamado "Twenty Eleven".

lunes, 3 de noviembre de 2014

Extraer archivo de base de datos desde dispositivo Android

Para extraer los archivos de base de datos (y en realidad cualquier otro archivo), podemos hacerlo utilizando las herramientas del SDK de Android, ya sea desde la línea de comandos, o haciendo uso del File Manager proporcionado por el Android Device Monitor.

Extraer base de datos desde línea de comandos

Para extraer archivos desde un dispositivo conectado a la computadora o emulador activo, se hace uso del comando adb pull. Si hay un solo dispositivo conectado, se hace de la siguiente manera:

adb pull /data/data/[mi.paquete.app]/databases/[mibasedatos.db] C:\ruta\destino

En donde el primer parámetro es la ruta complete del archive a extraer del dispositivo, que en este caso es la base de datos; y el segundo parámetro es la ruta destino dentro de la computadora. El segundo parámetro es opcional, y si no se especifica, el archivo extraído se guarda en el directorio actual.

Si hay varios dispositivos Android conectados a la computadora, debe especificarse adicionalmente el serial del dispositivo, de la siguiente manera:

adb -s [serial] pull /data/data/[mi.paquete.app]/databases/[mibasedatos.db] C:\ruta\destino

En donde [serial] corresponde al serial específico del dispositivo. Cabe mencionar que para consultar los seriales de los dispositivos conectados, se puede hacer ejecutando el comando:

adb devices

El serial del dispositivo aparece en la primera columna a la izquierda, al ejecutar el comando.

Extraer base de datos usando el Android Device Monitor

Para extraer el archivo de base de datos usando el File Explorer del Android Device Monitor, basta con seleccionar el dispositivo en la barra de dispositivos del monitor, ubicar y seleccionar el archivo en la ficha del File Explorer, y presionar el botón  (Pull a file from the device), ubicado en la parte superior derecha de la ficha.



Luego de esto se nos muestra una ventana de diálogo en la que solamente hay que indicar el nombre del archivo y el directorio destino.

Aunque esta forma parezca la más fácil, puede resultar no serlo, debido a que en algunos casos la carpeta data no puede ser vista desde el File Explorer, debido a que no posee los permisos necesarios.

miércoles, 15 de octubre de 2014

Encontrar base de datos SQLite en dispositivo android

Cuando se está trabajando en una aplicación de Android que hace uso de una base de datos SQLite, puede resultar necesario buscar el archivo de esta dentro del sistema de archivos del dispositivo en el que se están realizando pruebas, ya sea para verificar si esta se creó correctamente, si los datos se están almacenando, entre otras cosas.

La base de datos de cada aplicación se ubica en la siguiente ruta dentro del dispositivo:

/data/data/[mi.paquete.app]/databases/

En donde [mi.paquete.app] es el nombre del paquete principal de nuestra aplicación Android. En dicho directorio se almacena el archivo de la base de datos en sí, que posee el nombre especificado en el constructor de la clase SQLiteOpenHelper. También puede contener el “rollback journal” de la base de datos, que posee el mismo nombre, pero añadiendo el prefijo “-journal”. Por ejemplo, si la base de datos se llama “BDPrueba.db”, entonces los archivos que encontraremos serían “BDPrueba.db”, y posiblemente “BDPrueba.db-Journal”.



¡La carpeta data está vacía!

Si estamos usando el File Explorer del Android Device Monitor/DDMS para consultar los archivos del dispositivo Android, en algunos casos puede resultar que el directorio /data en apariencia no posee ningún contenido. Sin embargo, esto sucede debido a que esta carpeta no posee los permisos necesarios para ver su contenido.



Si esto sucede, lo que hay que hacer es otorgar los permisos necesarios para acceder a los archivos. Esto se puede hacer en dispositivos rooted y emuladores a través del ADB Shell, para entrar en modo terminal a nuestro dispositivo.

Para iniciar el ABD Shell, se ejecuta el siguiente comando en la terminal:

adb shell

Si hay varios dispositivos conectados, es necesario indicar el serial del dispositivo, de la siguiente forma:

adb -s [serial] shell

En donde [serial] es el serial del dispositivo deseado.

El serial del dispositivo se puede obtener ejecutando el comando adb devices
El serial del dispositivo aparece en la primera columna a la izquierda, al ejecutar el comando.
El serial del dispositivo aparece en la primera columna a la izquierda, al ejecutar el comando.

Una vez estando en la terminal del dispositivo, se deben iniciar modo super-usuario (usuario root):

$ su

Luego, hay que ejecutar el siguiente comando, para otorgar permiso completo de acceso a la rama de carpetas y archivos para todos los usuarios:

# chmod 777 /data /data/data /data/data/[mi.paquete.app] /data/data/[mi.paquete.app]/databases /data/data/[mi.paquete.app]/databases/*

Finalmente, para salir de la terminal:

#exit
$exit

Puede que no sea necesario otorgar control total sobre las carpetas, habría que probar cuáles serían los permisos mínimos dependiendo de lo que se necesite hacer con los archivos.
Con la tecnología de Blogger.