April 2012 - Artículos
Una de las consultas que me han hecho es ver como se puede cambiar el cursor del mouse en una página web, tal cual lo hacen el Cut the Rope , el excelente juego hecho en HTML5 bajo IE9, si , como escuchas IE9
, puedes verlo en http://www.cuttherope.ie/
Vamos a copiar los cursores de la app cuttherope, para eso voy a ocupar el depurador de IE9, que obtenemos presionado f12

Busqué los archivos cur y obtuve los archivos handcursor.cur y cursor.cur

<!DOCTYPE html>
<html>
<head>
<title>Ejemplo de Cursor</title>
<style type="text/css">
body{
cursor:url(cursor.cur);
}
#cara{
cursor:url(handcursor.cur);
}
</style>
</head>
<body>
<h1>Trabajo con Cursor </h1>
<img id="cara" src="cara1.png" />
</body>
</html>
Se ve que eo body tiene el cursor (cursor.cur) y la imagen el cursor handcursor. Ahora bien, al momento de ejecutar la página en un servidor web (no localmente como archivo html), vemos el resultado que presento en el siguiente video.
Espero que te sirva!, y de repente , quien sabes, te animas a hacer un juego 
Saludos!!
@chalalo
Hola que tal, otro tips más para el desarrollo sobre Windows Phone. Les cuento a manera de historia lo que me paso.
Tenía la necesidad de guardar en una lista de objetos los resultados obtenidos en el Pseudo juego del que estaba hablando en los post anteriores, los cuales puedes ver acá:
La pantalla de “Logros” es la siguiente:

El tema es el siguiente, para guardar una par key-value, funcionaba impecable, revisemos como se guardar un valor y como podemos recuperarlo posteriormente. Primero para guardar un valor lo podemos hacer de la siguiente manera:
IsolatedStorageSettings.ApplicationSettings["clave"] ="algun valor";
o que es lo mismo:
IsolatedStorageSettings.ApplicationSettings.Add("clave", "algun valor");
Lo que se guardar, como decíamos es un par key-value, en donde el value puede ser un objeto.
Para recuperar el dato almacenado, primero debemos preguntar si existe la clave en la colección ApplicationSettings, lo podemos hacer de la siguiente manera:
if (IsolatedStorageSettings.ApplicationSettings.Contains("clave"))
{
var valor =IsolatedStorageSettings.ApplicationSettings["clave"];
}
Recuerda que el objeto que se retorna no es tipado, por lo que vas a tener que hacer el cast explícito al lo que desees obtener.
Todo funcionaba perfecto, pero cuando quería guardar una lista de objetos, funcionaba en el emulador sin problemas, pero en el dispositivo no se almacenaban los datos, y yo que pensaba que mi aplicación estaba a minutos de poder ser publicada, asi que comencé la búsqueda de mi error.
La lista de objetos almacenaba puntajes, que tiene la siguiente estructura:

Que como vez, ocupo la propiedad cara para tener el nombre de la imagen que muestro, el constructor sirve para determinar mediante el puntaje que ruta de imagen se va a almacenar el cara. Además solo quería guardar los 10 últimos puntajes.
public void guardaResultados(int cont)
{
List<Puntaje> puntajes = new List<Puntaje>();
Puntaje p = new Puntaje(DateTime.Now.ToString("dd/MM/yyyy hh:mm tt"),
Convert.ToString(cont));
if (IsolatedStorageSettings.ApplicationSettings.Contains("puntajes"))
{
puntajes = (List<Puntaje>)IsolatedStorageSettings.ApplicationSettings["puntajes"];
}
puntajes.Insert(0,p);
if (puntajes.Count > 10)
{
puntajes.RemoveAt(10);
}
IsolatedStorageSettings.ApplicationSettings.Remove("puntajes");
IsolatedStorageSettings.ApplicationSettings.Add("puntajes", puntajes);
IsolatedStorageSettings.ApplicationSettings.Save();
}
Como se ve mi función en sencilla, en donde primero creo la lista de Puntaje, instancio el Objeto Puntaje , luego pregunto si ya existía una lista en el ApplicationSettings, si no existe es que se estaba jugando por primera vez, si no la recuperarnos para ingresarle el nuevo objeto p, insertamos en la primera posición, y si hay más de 10, la removemos.
Luego remuevo lo que estaba ya en la colección ApplicationSettings ,esto lo hice por que me levanto una excepción al querer guardar algo que ya tenia la clave, entonces, luego guardo la lista. El método Save no lo estaba ocupando, lei en la documentación que era el método que debía ocupar para guardar la lista, así que lo utilicé pero se levantaba una excepción que indica lo que estaba pasando, debía serializar las propiedades de mi objeto.
Así que rápidamente agregué en la clase Puntaje el namespace:
using System.Runtime.Serialization;
Luego agregué el atributo a la clase Puntaje:
[DataContract]
public class Puntaje …
y a las propiedades el respectivo DataMember
[DataMember]
public string cara { set; get; }
Ejecuté ahora mi aplicación en el teléfono y super! ya estaban funcionando la lista de puntajes de manera persistente, ya no se borraban en cada ejecución, justo lo que necesitaba.
Espero que te sirva este tip.
Saludos
@chalalo

¿Quieres ganar una Xbox 360 con Kinect?
Tienes hasta el 29 de Abril para publicar al menos una aplicación de Windows Phone 7 en nuestro Marketplace.
Recuerda que como Estudiante tienes la posibilidad de registrarte en el Marketplace y utilizar las herramientas absolutamente sin costo.
¡Es muy sencillo programar y publicar aplicaciones! Sólo sigue los siguientes pasos:

Vamos muchachos, a participar!!!
@chalalo.
Hola, como ya les había comentado , voy a estar compartiendo algunos tips que me sirvieron bastante al momento de comenzar a desarrollar algunas funcionalidades.
Abrir ventana del Browser
Una de las funcionalidades que tiene la app que hice, aunque sea muy poco visible , es que al hacer tap sobre @chalalo, voy a abrir una ventana del explorador a la versión móvil de de la pagina de twitter apuntando a mi cuenta 

Entonces primero importamos:
using Microsoft.Phone.Tasks;
Para luego asociar al texto TextBlock su handler:
private void tx_chalalo_Tap(object sender, GestureEventArgs e)
{
WebBrowserTask webbrowser = new WebBrowserTask();
webbrowser.Uri = new Uri("http://mobile.twitter.com/chalalo");
webbrowser.Show();
}
Y listo!
Compartir en redes sociales
Una de las funcionalidades que quería era compartir los logros en las redes sociales, primero comencé a revisar el código para ver alguna API de conexión hacia Twitter, después de leer me di cuenta el sdk de WP7 provee todo lo necesario para poder conectarnos a todas las redes sociales que están registradas en el teléfono.

Entonces, fue muuuy sencillo, primero importamos:
using Microsoft.Phone.Tasks;
Para luego asociar al botón el handler
private void Button_Click_2(object sender, RoutedEventArgs e)
{
ShareStatusTask shareStatusTask = new ShareStatusTask();
shareStatusTask.Status = "He obtenido " + cont + " puntos! en el Juego Dead Dedo para Windows Phone 7, hell yeah!";
shareStatusTask.Show();
}
Vemos que la propiedad Status el texto que se va a compartir.,
Luego aparecerá la pantalla para compartir el mensaje

Ten en cuenta que no va aparecer en el emulador, pero en el dispositivo físico no hay problema
, genial!, muy fácil.
Ahh! y que no se me olvide, la primera vez que subí una app al store, fue rechazada por que los screenshot que tomé tenían los datos de debug, (que son los números que están al lado derecho del emulador), lamentablemente estos números aparecen en las imágenes.

Para desactivar estos números simplemente vas al archivo App.xaml.cs y comentas la siguiente línea:
//Application.Current.Host.Settings.EnableFrameRateCounter = true;
Y listo! ahora si podemos subir los screenshot sin que los rechacen!
Saludos!
En breve, más tips
@chalalo
Hola a todos, que tal? Acabo de subir mi sexta aplicación al Maket Place, ninguna es una gran maravilla, pero fueron parte de mi aprendizaje en el desarrollo de aplicaciones para wp7. Quiero compartir los tips y funcionalidades que anduve buscando en la documentación para poder hacerlo. Me gustaría también en el futuro, y si es que prende la idea en los lectores de este blog, hacer comparaciones entre el desarrollo de Android y WP7. (ya que antes de WP7, desarrollaba y aún desarrollo para Android)
En este proceso de aprendizaje, he creado un pseudo- juego que tiene que ver cuantas veces eres capaz de apretar una calavera en 33 segundos, la app aún está en etapa de evaluación, las funcionalidades son obvias, dentro de los plus son:
- Compartir tu puntaje en las redes sociales registradas en el teléfono.
- Agregar sonido en Silverlight
- Hacer deploy con tipo de letra personalizado
- Guardar listas de objetos IsolatedStorageSettings
- Abrir IE desde la aplicación
Claro que estas son funcionalidades básicas, pero para los que estamos partiendo creo que serán de gran ayuda 
Estos son parte de los screenshot de la aplicación, como dije antes, la hice para aprender y poder enseñar, así que de hoy en adelante, aparte de ASP.NET estaré compartiendo los tips 




Esto de hacer apps por jugar ha sido el mejor método que he tenido para aprender a desarrollar para una plataforma.
Nos vemos!!
@chalalo

Hola, últimamente he estado utilizando MongoDB , estoy muy entusiasmado con este tipo de repositorios, y buscando información acerca de como decidir si usar un RDBMS o un enfoque NoSQL encontré un interesante artículo que es parte de DZone NoSQL Portal. El artículo original está en inglés, voy a intentar traducirlo lo mejor posible.
--- Cualquier persona que no vive en una caverna sabe que NoSQL es una tendencia en aumento para dar soluciones de almacenamiento a gran escala. Sin embargo una pieza que falta en todo esto, es una especie de guía sobre como determinar si la mejor solución es NoSQL o un RDBMS tradicional.
Para comenzar, vamos a decir que debes asumir que un RDBMS es probablemente la apuesta más segura. Casi cualquier cosa se puede hacer con un almacén de este tipo, con la excepción de no poder escalar y/o llevar a cabo tareas con la misma performance que una solución NoSQL. Una de las grandes ventajas de las soluciones RDBMS es que ellos ya cuentan con un enorme ecosistema de herramientas, documentación y dba con experiencia.
Dado lo anterior, ¿por que deberíamos entonces, mirar hacia una solución NoSQL? Los siguientes son algunos indicadores que nos pueden servir para decidir que una solución NoSQL puede ser la mejor opción para solucionar un problema:
- Estamos almacenando simples pares clave/valor. Si nuestra solución RDBMS termina siendo solo una tabla con un par de campos clave y otro CLOB XML, … entonces probablemente estaremos utilizando la herramienta equivocada para ese trabajo.
- Estamos almacenando estructuras de datos complejas las cuales son no-relacionales. si almacenamos estructuras con datos jerárquicos en donde cada “Maestro” tiene diferentes “Detalles”, sin un esquema estándar, estaremos en problemas con un RDBMS.
- Necesitamos escalabilidad masiva y la distribución, y la economía de esa escala es importante para nosotros. Muchas soluciones RDBMS ofrecen partición de esquemas y una muy buena escalabilidad, pero a un costo elevado( licencias y gastos de implantación), que generalmente son mucho más costas que escalar con una solución NoSQL.
Bueno, eso, corta y buena 
@chalalo
Hola!, los quiero invitar a un evento que se va a realizar en las oficinas de Microsoft Chile 

Migrando de HTML 4 a HTML 5sin quebrar la compatibilidad de tus sitios
Existe un amplio consenso en que HTML 5 es la plataforma de facto para la nueva Web. Cada día vemos como nuevos browsers, smartphones, tablets y e-readers incorporan soporte para ciertas capacidades del estándar en desmedro de los tradicionales plug-ins. Sin embargo, es también una realidad que una parte importante de nuestros clientes todavía visitan nuestros sitios Web a través de tecnologías más antiguas, sin soporte para muchas de las capacidades que hoy ya son parte del estándar. En esta sesión conoceremos el estado actual del estándar HTML 5 y su soporte en Internet Explorer 9, discutiremos las estrategias disponibles para la transición y mostraremos las herramientas de ASP.NET que nos pueden permitir abordar de mejor manera la evolución hacia HTML 5, manteniendo la compatibilidad con la versión anterior del estándar.
Oradores:
Gonzalo Pérez, Hans Nemarich y Pablo Berton.
Microsoft Chile - Sala Farellones y Colorado
Mariano Sánchez Fontecilla 310 Piso 6
Las Condes Santiago Región Metropolitana Chile
Fecha:
Jueves 26 de Abril desde las 18:30 horas a las 21:30 horas.
Regístrate acá
https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032509406&Culture=es-CL
Nos vemos allá!
@chalalo
Hola!, y seguimos con el tutorial de MongoDB + ASP.NET Web API , apoyándonos siempre en jQuery para la funcionalidad del front-end, los post anteriores son:
Esta vez vamos a realizar la funcionalidad de Editar, que encierra la acción de buscar un registro en particular y luego editarlo.
He hecho unos cambios pequeños al ejemplo que hemos estado desarrollando, el primero es que para mostrar el modificar, voy a agregar en la función de mostrar el código para mostrar el botón Modificar, pensé hacer lo mismo que hice con el botón borrar para referenciarlo, pero wait!, no puedo, debido a que en el botón borrar lo tengo asociado como Id, por lo que voy a crear un atributo data-clave al cual voy a asociar el id en el botón modificar:
function muestraFarmacias(farmacias) {
var li = "";
$("#lista").empty();
var href = null;
$.each(farmacias, function (index, farmacia) {
li += "<li>" + farmacia.Nombre +
"<button class='botonEliminar' id='" + farmacia.Id +"'>Borrar</button>
<button class='botonModificar' data-clave='" + farmacia.Id +
"'>Modificar</button></li>";
});
$("#lista").append(li);
$("#cargando").empty();
}
El cambio que hice sobre sobre el la acción de click sobre el botón Enviar/Modificar la paso a explicar en breve.
Entonces, manos a la obra
, el funcionamiento es mega básico: hacer click en el botón modificar de la lista, vamos a obtener los datos y dejarlos en las cajas de texto para poder modificarlos, el botón que antes decía Guardar , debemos setearlo a Modificar, luego de presionarlo, se debe obviamente modificar el registro y volver al estado inicial, el de ingreso de registros.

Veamos la acciones del controlador FarmaciaController que nos van a permitir obtener los datos de una farmacia en particular a partir de su Id y el siguiente, que nos va a permitir modificar un registro.
public Farmacia ObtFarmacia(string id)
{
try {
FarmaciaModels fm = new FarmaciaModels();
Farmacia farmacia = fm.GetFarmacia(id);
if (farmacia != null)
{
return farmacia;
}
throw new HttpResponseException(HttpStatusCode.NotFound);
}
catch (Exception){
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
}
public HttpResponseMessage PutFarmacia(Farmacia farmaciaMod)
{
try
{
FarmaciaModels fm = new FarmaciaModels();
fm.PutFarmacia(farmaciaMod);
return new HttpResponseMessage(HttpStatusCode.OK);
}
catch (Exception)
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
}
Como puedes ver la primera acción la utilizo para obtener una farmacia, su nombre comienza con Obt, y es que para no crear otro mapa de rutas, voy a utilizar el que permite agregar el nombre del controlador, acción e Id.
Para la segunda acción voy a utilizar el verbo Http PUT ,que tiene el significado de agregar o reemplazar, en nuestro caso es claramente reemplazar para ejecutar la acción del updatear el registro.
Revisemos ahora los métodos del modelo, que nos van a permitir realizar las tareas que las acciones exponen:
public Farmacia GetFarmacia(string id)
{
MongoDatabase db = Db();
return db.GetCollection<Farmacia>("farmacias").FindOneById(id)
}
public void PutFarmacia(Farmacia farmaciaMod)
{
MongoDatabase db = Db();
var farmacias = db.GetCollection<Farmacia>("farmacias");
Farmacia farmacia = farmacias.FindOneById(farmaciaMod.Id);
farmacia.Nombre = farmaciaMod.Nombre;
farmacia.Direccion = farmacia.Direccion;
farmacia.Telefono = farmacia.Telefono;
farmacia.Comuna = farmacia.Comuna;
farmacia.Latitud = farmacia.Latitud;
farmacia.Longitud = farmacia.Longitud;
farmacias.Save<Farmacia>(farmacia);
}
Destaca la simplicidad de los métodos, el primero para obtener una farmacia en particular, en donde instanciamos una colección de farmacias y sobre ella ejecutamos el método FindOneByID que permite buscar un elemento en la colección de MongoDB mediante el Id especificado para el objeto farmacias. Esto se hace con “carga demorada” y es una consulta compilada, es decir, no se obtiene toda la colección y sobre ella luego se filtra, si no que se hace la consulta directamente y muy optimizada de parte del motor para obtener un único registro.
Ahora para Modificar una farmacia, lo que hago es pasar el objeto que se va a modificar, el cual viene con el Id original y los datos modificados desde el formulario, para el Id cree una variable oculta (hidden field) dentro del formulario para guardar el valor. Luego obtengo el objeto y sobre escribo sus propiedades y luego lo guardo con el método Save.
Ahora que ya vimos el BackEnd, vamos a ver los métodos en el frontEnd que nos van a permitir llamar a las acciones:
Funciones Javascript, utilizando jQuery por su puesto, la primera para asociar el evento Click sobre el botón modificar, el cual llama a la acción del controlador ObtFarmacia,una vez que se obtienen los datos, se llama la funcion muestraFarmacia, que sirve para mostrar los datos en el formulario y setear el Id en el campo oculto, para tener disponible el Id para ejecutar el update.
$(".botonModificar").live("click", function () {
var id = $(this).attr("data-clave");
$.ajax({
url: "http://localhost:51753/Api/Farmacia/ObtFarmacia/"+id,
type:"GET",
contentType: "application/json;charset=utf-8",
statusCode: {
200: function (farmacia) {
muestraFarmacia(farmacia);
},
400: function () {
$("#mensaje").text("Error en la Petición");
},
404: function () {
$("#mensaje").text("Datos no Encontrados");
},
500: function () {
$("#mensaje").text("Error en el servidor");
}
}
});
});
function muestraFarmacia(farmacia) {
$("#Id").val(farmacia.Id);
$("#Nombre").val(farmacia.Nombre);
$("#Direccion").val(farmacia.Direccion);
$("#Telefono").val(farmacia.Telefono);
$("#Comuna").val(farmacia.Comuna);
$("#Latitud").val(farmacia.Latitud);
$("#Longitud").val(farmacia.Longitud);
$("#Fecha").val(farmacia.Fecha);
$("#boton").val("Modificar");
}
Ahora veamos la modificación que se hizo sobre el manejador del Submit del formulario, acá es donde se hizo la modificación, primero definimos una variable verbo, que según el botón esta en estado modificar, será PUT o de caso contrario, será POST, esto es para determinar a que acción del controlador vamos a llamar , PostFarmacia para ingresar o PutFarmacia para actualizar, recuerda que el tema de ingreso y borrado están en los post anteriores.
También seteo una variable acción de manera de poder enviar un msg adecuado al contexto la cual puede ser “Insertar” y “Modificar”.
Una vez que ya ejecutamos la llamada ajax mediante jQuery, limpiamos los elementos input, con lo que la variable oculta que contiene el Id también se limpia, también al botón lo volvemos a su texto original “Guardar”
$('#formulario').submit(function (event) {
var verbo = "POST"
var accion = "Insertar";
if ($("#boton").val() == "Modificar") {
verbo = "PUT";
accion = "Modificar";
}
event.preventDefault();
$.ajax({
url: "http://localhost:51753/Api/Farmacia",
type: verbo,
contentType: "application/json;charset=utf-8",
cache: false,
data: JSON.stringify($(this).serializeObject()),
statusCode: {
200: function (farmacia) {
listaFarmacias();
},
500: function () {
alert("Error al " + accion);
}
}
});
limpiar();
});
function limpiar() {
$(":input").val("");
$("#boton").val("Guardar");
}
Finalmente el funcionamiento queda de la siguiente manera, recuerda que no hemos hecho nada por el diseño, es solo funcionalidad, y si, de nuevo no arreglé lo de Regitros 
Espero que te sirva!, luego seguimos con el tema de seguridad
Saludos
@chalalo
En Hora Buena!
, he sido elegido nuevamente MVP ASP.NET/IIS, ya son 7 años , y cada año siempre vuelve el nerviosismo de si es que calificaste o no.
El año pasado fue particularmente difícil, pero gracias a Dios, pude concretar proyectos de Webcast, ScreenCast, charlas y artículos. He tratado de responder todos los correos, pido las disculpas por si he olvidado alguno. Siempre digo que el MVP es la consecuencia de lo que me apasiona, no es el el solo hecho de ser MVP. Debido a que hay un amplia tendencia al mundo del desarrollo móvil, en el cual he estado trabajando bastante, tuve menos tiempo para dedicarle a mi pasión, el desarrollo Web, pero bueno, creo finalmente todo salió bien.De hecho, además de ASP.NET próximamente estaré posteando tips para Windows Phone 7.
También estoy muy contento sobre la noticia de que ASP.NET MVC 4 con Razor y ASP.NET Web API son OpenSource, no lo sabías? mira este artículo, me gusta mucho el OpenSource (aunque algunos crean que no), esto abre muchas nuevas posibilidades de cooperación y mejora de estos excelentes productos.
Y Bueno, por ultimo agradecer a todos las personas que leen este humilde blog, trato de aportar con lo que pueda servir, muchas gracias!!!

@chalalo.