ASP.Net MVC Razor, la evolución desde apsx webforms hacia MVC y fundamentos básicos de ASP.Net MVC

aspnetQuienes hayan trabajado alguna vez con .Net, conocerán el sistema de plantillas de ASP.Net llamado webforms. Los webforms fueron un sistema de vistas con extensión aspx que podían ir o no acompañadas de un codebehind y controles. El objetivo de Microsoft cuando diseño esta parte del framework de .Net fue mover a los desarrolladores a crear aplicaciones en nube, que aunque ahora este tan de moda el termino nube, estamos en un contexto del año 2000. Los webforms permitían desarrollar una web, tal y como los desarrolladores del viejo Visual Basic hacían sus aplicaciones de escritorio, donde las páginas eran llamadas formularios (de ahí el término webform) y los elementos tales como inputs, botones, etc, se arrastraban con un editor wysiwyg. Los antiguos webforms, aunque simulaban un entorno de escritorio, en cuanto a formularios, no eran otra cosa que webs y como tales podías tocar el html desde el editor y no solo tener la opción de editor wysiwyg, encontrando bajo el capo una web de código espagueti tal y como siempre se habló de php por ejemplo, salvo que parte de la lógica estaba en el codebehind. Esta última parte era lo peor de todo, puesto que si el desarrollador era experto, el código espagueti era minúsculo, pero a medida que descendía la pericia del programador, aumentaba el tamaño tanto del codebehind como del propio espagueti html que era ese aspx webform.

Microsoft publico todo esto en las primeras versiones del .Net framework y fue un bombazo, cualquiera podía hacer una web con muchos formularios en un tris, pero claro, ahí esta está el cliente para recordarnos que era muy feo y que lo querían mas bonito como habían visto por internet otras páginas. Es entonces cuando empiezan a verse los primeros problemas a la hora de realizar webs y es que aspnet 1 no tenia soporte para páginas maestras, por lo que los desarrolladores acababan en practicas comunes en otros lenguajes y que eran tan criticadas como copiar y pegar la misma estructura de página (controles, cabecera, menu, pie, etc) por todas y cada una de las páginas que tuviéramos en nuestro proyecto. Así que como novedad, Microsoft pensó que aparte de cambiar la forma de incluir los controles en una web, automatizando todo el proceso, penso que era hora de crear un concepto mas que necesario, una masterpage. Una masterpage, no es mas que como su nombre indica, una página maestra, digamos que todo ese contexto de cabeceras, menu, pie, etc que ibamos copiando de página a página pero que ahora se centraliza en un sitio, marcando en esa página maestra, donde queremos que se renderice el contenido de la página. Esto supuso un gran avance, ya que las páginas desarrolladas con ASP.Net, fueron mejorando en el punto que eran mas limpias. Aun y con todo, seguian los problemas, el auge de librerías de javascript dinámicas, con efectos y llamadas de ajax, dejaba en ridículo a controles muy cerrados tipo updatepanels y los desarrolladores pedían a gritos mas flexibilidad.

Cuando uno ha vivido toda la vida amamantado por la teta de Microsoft, no se percata de cierta rigidez a la hora de desarrollar una web con ASP.Net, pero quien tocara cualquier otro entorno, veia como en php y python, aparecian framework MVC, que permitian utilizar todas esas librerias de ajax pero sin montar un pipote (caos) de código para que funcionen bien. Es entonces cuando aparece MVC. El concepto de MVC es un concepto creado en 1979, no trae ninguna novedad como tal, pero si que introduce ese concepto en ASP.Net teniendo una serie de caracteristicas fundamentales (en un sistema normal sin mucha floritura):

  • Los controladores son siempre los que reciben las peticiones, ya no hay controladores genéricos ashx, servicios asmx, paginas aspx, controles ascx, ni masterpages master. Los controles son clases donde por defecto, sus métodos serán aciones del controlador.
  • Las vistas son solo eso, vistas, con sintaxis webform en MVC 1 y 2 y con Razor en MVC 3 y 4.
  • Los modelos son clases con propiedades multifunción, validar automáticamente datos, enviar y recibir formularios, sincronizar datos con la base de datos (Entity Framework Code First).
  • El proyecto es un binario cerrado, como ocurría en la primera versión de ASP.Net y en el resto si lo cambiabas a proposito, ya no hay mas código abierto con el que dejar a IIS que compile el código, como si fuera php.

Hasta aquí, una breve explicación de como surge MVC, pero ¿Y Razor? Razor es el nuevo sistema de templates de ASP.Net MVC. Quien haya programado con webforms, se habrá dado cuenta que en una página con un poco de lógica, acaba creciendo mucho y complicando la sintaxis con abre código <%, mete código, cierra código %>, haciendo que no solo crezca una página, sino que además, el código se vuelve mas y mas feo por momentos. Razor soluciona esto con 2 procedimientos, el primero es su cierre automático inteligente, es decir, la etiqueta de apertura será una arroba @, pero no tendrá cierre como tal. La segunda peculiaridad es que el código es mucho mas fluido puesto que se aprovecha del propio html para formar ciertas partes de la sintaxis. Ademas, Razor tiene algunas ventajas como son poder indicar un modelo que utiliza la página para hacer validaciones, formularios y pintar datos de una forma mas sencilla.

Veamos un par de ejemplos de código hecho con Razor frente al hecho con webform:

@model Indacalsa.Models.LoginModel

@using (Html.BeginForm("Login", "Account", FormMethod.Post)) {
  @Html.AntiForgeryToken()
  <fieldset id="login">
    <legend>Datos de acceso @ViewBag.Title</legend>
    <p>
      <label>
        <span class="title">Usuario:</span>
        @Html.TextBoxFor(m => m.UserName)
        @Html.ValidationMessageFor(m => m.UserName)
      </label>
    </p>
    <p class="center">
        <input type="submit" value="Acceder" class="btn" />
    </p>
  </fieldset>
}
<form method="post" action="/Login/Account.aspx" runat="server">
  <fieldset id="login">
    <legend>Datos de acceso <%=this.Title%></legend>
    <p>
      <label>
        <span class="title">Usuario:</span>
        <asp:TextBox name="UserName" id="UserName" runat="server" />
        <asp:RegularExpressionValidator ID="validatorUserName" runat="server" ControlToValidate="UserName" ErrorMessage="La longitud mínima es de 5 caracteres" ValidationExpression=".{5}.*" />
      </label>
    </p>
    <p class="center">
        <asp:Button value="Acceder" class="btn" runat="server" />
    </p>
  </fieldset>
</form>

Lo he simplificado, primero en Razor y luego en ASP.Net webforms. La parte de webforms la he simplificado sin utilizar el tipico form que ocupa toda la página y sin mucha historia, para dar un acercamiento de como va el tema. Aparte de este ejemplo hay que sacar la mala experiencia de utilizar controles de webform y sus ids mágicos, si es que luego queremos dinamizar la página con ajax o javascript.

Y para los que vengan de atras, aquí van algunas similitudes entre webform y Razor:

  • Las masterpage de webform ahora son llamadas Layouts
  • Los controles de webform ahora son vistas parciales, pero con la salvedad de que no tendrán codebehind.
  • Para especificar código espagueti o en linea en webforms se hace con <% codigo %> y <%=codigo%>. Con Razor se hace con @micodigo o @(micodigo_muy_complejo).
  • Para ir renderizando texto dentro del código de Razor ya no es necesario abrir y cerrar las etiquetas de codigo <% y %>, sino que podemos usar <text>texto a renderizar</text>
  • Los asp:content de las masterpages ahora son sections.

Espero que os guste y os sirva un poco a aquellos rehacios a migrar a MVC o desde otros lenguajes.

W2S web ide

w2sLlevo una temporada sin escribir en el blog. El motivo es porque he estado trabajando en un proyecto, que aún no está terminado. El proyecto en concreto se llama w2s y se trata de un ide de desarrollo web que esta ahora mismo en una fase alfa pero completamente funcional. w2s es un entorno de trabajo, con el que poder desarrollar en multitud de lenguajes de programación. Actualmente aunque falta mucho por desarrollar, ya permite programar en c#, php, html, javascript y css.

¿Por qué crear un ide completo de desarrollo? Muy sencillo, porque no hay nada similar. En mi caso, programo en C#, pero utilizo OSX, a veces programo en PHP y otras veces en HTML y Javascript con Phonegap. El problema está en que para programar en C# para OSX solo se puede con Mono, que está muy retrasado con las nuevas versiones de .Net. En Windows ocurre lo mismo, para C# tienes el Visual Studio, que es muy bueno para C# pero no soporta PHP ni webs unicamente en HTML y Javascript. Luego existe el problema de trabajar en distintos sitios, el trabajo, en casa, el ordenador de mi mujer, incluso en el ipad. Es por estas cosas por las que un día decidí crear w2s, para tener un repositorio centralizado donde poder trabajar, con un ide de desarrollo online que me permitiese en una misma aplicación desarrollar en C#, PHP, Javascript, HTML5, CSS y poco a poco mas y mas lenguajes.

Cada día uso w2s en mas y mas desarrollos, entre los cuales cabe destacar el propio w2s. Entre las funcionalidades mas destacadas se encuentran:

  • Editor de código en C#, PHP, Javascript, HTML5, CSS3.
  • Intellisense o autocompletado de código para HTML5, Javascript y estoy trabajando en CSS3 y C#.
  • Avisador de errores en el código de Javascript.
  • Compilador de C#.
  • Poder subir archivos arrastrandolos desde el escritorio
  • Poder descargar el proyecto completo en un zip.
  • Cuenta de ftp
  • Un giga de espacio ampliable para almacenar proyectos
  • Tester web para probar la web como un pc, ipad, iphone4, iphone5

Ire publicando nuevas actualizaciones con cambios que vaya realizando. Y como siempre, quien quiera participar en la fase alfa o en posteriores versiones beta privada y beta publica, solo tiene que dejar un mensaje.

Añadir usuarios para el ftp al servidor proftpd

Proftpd es un servidor de ftp muy común en Linux que utiliza a los usuarios del sistema como listado de posibles usuarios a conectarse. Si intentamos conectarnos con un usuario del sistema a este servidor ftp, nos encontramos con que nos mostrará su carpeta home. Pongamos que tenemos un servidor web multidominio y queremos conectarnos con cada uno de estos usuarios a cada web sin que se mezclen las carpetas y para dar un poco de seguridad en este inseguro mundo de la informática ¿Como lo haríamos? La respuesta es bien sencilla y solo debemos seguir unos pequeños pasos para conseguirlo, debemos investigar para saber que grupos necesitamos, a que carpetas queremos acceder, crear los usuarios y establecer contraseñas de acceso.

  1. Lo primero que debemos averiguar es el usuario que utiliza nuestro servidor web. Esto es importante porque necesitamos saber a que grupo pertenece. Esto lo dejo un poco en el aire porque dependerá del servidor que ejecutemos, distribución que tengamos instalada, etc. Pero vamos a tomar como base www-data como usuario y grupo.
  2. Una vez tenemos el grupo, debemos tener claro cuales van a ser las carpetas donde queremos que nuestro usuario acceda, por ejemplo /usr/share/nginx/www y /usr/share/nginx/blog
  3. Creamos el usuario con el comando useradd con el siguiente formato: useradd -M -g grupo -d home_path nombre_usuario
  4. Estableceremos una contraseña a nuestro usuario con passwd usuario
Al final el resultado sería la ejecución de códigos similares a estos:
useradd -M -g www-data -d /usr/share/nginx/www usuario_www
useradd -M -g www-data -d /usr/share/nginx/blog usuario_blog
passwd usuario_www
passwd usuario_blog
Con esto estaríamos creando 2 usuarios, uno para www y otro para blog. Ambos usurarios pertenecerán al grupo www-data. Con el flag -M indicaremos expresamente que no cree la carpeta home, solo la definimos. ¿Por qué es importante el grupo www-data o el que corresponda obtenido del paso 1? Porque sino deberemos de estar cambiando permisos si queremos que nuestro código se ejecute, mientras que al ser del mismo grupo, no tendría muchos problemas.

Ahora ya podemos conectarnos a nuestro servidor ftp con los usuarios usuario_www y usuario_blog con las contraseñas que les indicamos en el passwd. Importante que ejecuteis y pongáis contraseña con passwd porque sino podreis intentar contectaros pero siempre dará error... a mi me paso 😀

Indalcasa + Bootstrap + Azure

Power by Windows AzureLlevo tiempo queriendo cambiar el blog y finalmente me decidi. He migrado el blog de hosting, ahora se encuentra en nube con azure y a un precio que de momento parece ser bastante mas económico que los cálculos iniciales que hice. Ya aproveche para instalar un nuevo tema al blog, con una apariencia bootstrap, limpia y sencilla y hacer limpieza de plugins y configurar un buen cache.

¿Por qué me decante por Azure y no por Amazon Web Services? es motivo de un post aparte. De momento me quedo con Azure, montando una instancia extra pequeña con un Ubuntu, usando nginx como servidor web y MySQL 5.5 como base de datos.

En sucesivos días ire contando las diferentes optimizaciones y configuraciones que he realizado sobre el servidor y el blog. Cómo instalar nginx, configurar php sobre nginx, optimizaciones de cache sobre php y sobre el blog y algunos truquillos que me he visto en la necesidad de sacarme de la manga.

ASP.Net y los errores de «La operación no es válida debido al estado actual del objeto» y como solucionarlo con MaxHttpCollectionKeys

A veces en ASP.Net, se da el caso de que una página tiene un formulario inmenso, cuando por ejemplo queremos mandar un modelo gigantesco. Aunque de darse este caso, deberiamos plantearnos si no debemos cambiar nuestro código, puede que si lo ejecutamos nos de un error indicando "La operación no es válida debido al estado actual del objeto" o en ingles "Operation is not valid due to the current state of the object". Esto pasa porque hemos sobrepasado el límite máximo de parámetros que se pueden enviar.

La solución es bien sencilla, solo debemos modificar nuestro web.config para que admita mas parámetros

<configuration>
  <appSettings>
    <add key="aspnet:MaxHttpCollectionKeys" value="5000" />
  </appSettings>
</configuration>

Añadiendo la key MaxHttpCollectionKeys y aumentandola hasta 5000, el problema se soluciona.

Problema de codificación UTF8, Internet Explorer 8 y PHP

El otro día tuve que tocar una web antigua de un compañero que estaba hecha en PHP4. Al abrir los archivos para hacer unos cambios que me pidieron, estos estaban codificados en vete tu a saber que codificación, así que al hacer cambios se estaba autocodificando todo en UTF8. Al hacer pruebas, todo va bien, en Chrome, Safari y Firefox se ve todo estupendamente, incluso en Internet Explorer 9 se veia bien, eso si, no sin antes añadir en la página el meta indicando que está codificada en UTF8. El problema es que cuando abres la misma web en Internet Explorer 8, este no muestra bien la codificación y esto es porque Internet Explorer 8 no lee bien el charset del meta de Content-Type y por tanto toma la codificación por defecto.

Una nota interesante es que Internet Explorer 8, aunque no reconoce el meta de Content-Type, si que reconoce el encabezado Content-Type que se envia desde el servidor en el protocolo http, por lo que, siguiendo unos sencillos pasos podemos paliar este problema y migrar esos proyectos antiguos que puedan haber por ahí a editores mas modernos.

  1. Recodificar el proyecto. Podemos utilizar un editor que guarde los archivos por defecto en UTF8 o hacernos de algún script que lo haga por nosotros.
  2. Añadir el meta de UTF8. En todas las páginas publicas, debemos añadir un meta de UTF8 y si ya existiera con el típico ISO-8859-1, cambiarlo a UTF8. Algo como <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  3. Por último y no menos importante, devolver el encabezado de http con el Content-Type en UTF-8. Con algo como esto: header('Content-type: text/html; charset=utf-8');

El código resultante sería en nuestro html:

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title> Indalcasa</title>
...

Y nuestro php, antes de devolver nada de texto, pintar la cabecera de http:

<?php
  header('Content-type: text/html; charset=utf-8');
?>

Por último comentaros que w3c recomienda en HTML5 que el meta de Content-Type se ponga como el primer elemento dentro del head antes incluso que el title para que se pueda interpretar correctamente la página.

Forzar la descarga de archivos en Apache con .htaccess e IIS con web.config

Cuando tenemos una página web, hay ocasiones en la que queremos que un fichero se descargue, por ejemplo si queremos hacer un sistema de almacenamiento tipo dropbox o simplemente unos pdf que tenemos en nuestra web. Normalmente cuando tenemos un archivo como un pdf, tradicionalmente este siempre se descargaba al abrirlo, pero con los avances en los navegadores, cada día mas potentes, nos dan previsualizadores de pdf, por lo que ya por defecto no se descarga porque los vemos online.

En este ejemplo hablo de pdf, pero se puede llevar a cualquier tipo de archivo, incluso un .html. Un archivo pdf tiene como MIME application/pdf, pero ¿Qué es un MIME? Un MIME es un estándar que define tipos de ficheros en base a una categoría y una subcategoría, por ejemplo, un pdf de tipo application/pdf quiere decir que es un archivo de aplicación del tipo pdf. Otros ejemplos de MIME son de imágenes como el image/jpeg o de texto en html text/html. Cuando un navegador abre un pdf, el servidor tiene por defecto configurado indicar que el archivo es de tipo application/pdf que se indica en la cabecera de http Content-Type.

Tras esta breve explicación, a veces pasa, que no todos los navegadores tienen visores de pdf, por los que algunos como pasa con algunas versiones de Firefox o Internet Explorer se descarguen los archivos, mientras que Safari o Chrome los visualicen online. Pero claro, este comportamiento no es muy elegante ya que quizás sea necesario que se comporte igual en todos los navegadores y tengamos que hacer que siempre se descargue el archivo y esto ya depende del servidor.

Para forzar la descarga de archivos, como el ejemplo que tratamos, un .pdf, tendremos que redefinir un MIME asociado a una extensión, es este caso diremos que es un octet-stream o un stream de bytes (un archivo binario). Al entender el navegador, que el archivo se trata de un archivo binario, no intentara leerlo sino que lo descargará independientemente de la extensión que tenga.

Forzar la descarga de archivos en Apache con .htaccess

Tan solo tenemos que añadir una nueva entrada AddType donde definiremos que los archivos .pdf son binarios y por tanto el navegador los descargará:

AddType application/octet-stream .pdf

Forzar la descarga de archivos en IIS con web.config

Al igual que con apache, deberemos indicar al servidor que el tipo de archivo .pdf es un binario:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <staticContent>
      <mimeMap fileExtension=".pdf" mimeType="application/octet-stream" />
    </staticContent>
  </system.webServer>
</configuration>

Ordenar los bundles de ASP.Net MVC

Si alguna vez habeis intentado hacer un gran proyecto con ASP.Net MVC, vereis que utilizar los bundles para incluir el código tanto javascript (ScriptBundle) como css (StyleBundle) en nuestra página es muy útil ya que nos ofrece diferentes formas de tratar los archivos a incluir, uno de mis favoritos es unificar todo el bundle compilado y minimizado. Todo parece un camino de rosas, poder agrupar todos nuestros css y javascript en una sola linea incluyendo archivos o directorios.

No todo es maravilloso y aunque Microsoft suele hacer las cosas bastante bien, siempre se deja algún extraño por el camino. En este caso el extraño es el orden en que se cargan los archivos en la página usando Bundles. Cuando tenemos multitud de archivos javascript o css por ejemplo, se da el caso en que no todos los archivos se cargan en el orden en que lo incluimos. No se si tiene algo que ver mezclar inclusiones por archivos y directorios a la vez, pero no mantiene el orden igual. Es una locura, puesto que aparentemente todo sigue un orden, pero cuando tenemos una docena de archivos javascript o css, a veces hay alguno que se descoloca. A mi me pasó con backbone y underscore, que como sabreis quien haya trabajado con estas librerias, backbone requiere de underscore y si no esta incluido previamente provoca un error.

Lo primero que tenemos que hacer es crear una nueva clase para hacer el IBundleOrderer.OrderFiles que ordene los bundles, en nuestro caso, realmente no queremos que ordene sino que los muestre en el orden en que los escribimos. La clase en cuestión sería:

public class UserDefinedBundleOrderer : IBundleOrderer {
    public virtual IEnumerable<FileInfo> OrderFiles(BundleContext context, IEnumerable<FileInfo> files) {
        return files;
    }
}

Una vez tengamos nuestra clase IBundleOrderer, solo deberemos indicar a nuestro bundle, bien sea un ScriptBundle, un StyleBundle o un Bundle genérico, que utilice como Orderer nuestra clase que se encarga de la "ordenación" o en este caso, dejar las cosas como están. Lo haremos con el Bundle.Orderer como se muestra en el ejemplo:

myBundle.Orderer = new UserDefinedBundleOrderer();

Y ahora os dejo un ejemplo real sacado directamente de un proyecto propio. Así quedaría todo el archivo completo. Podemos ver como el BundleConfig donde definimos la carga de Bundles, tenemos un StyleBundle que cargará nuestros css, mientras que el ScriptBundle cargará nuestras librerías javascript y es a esta clase donde aplicamos nuestra clase para la ordenación de Bundles.

using System.Collections.Generic;
using System.IO;
using System.Web;
using System.Web.Optimization;

namespace MyWeb {
  public class BundleConfig {
    public static void RegisterBundles(BundleCollection bundles) {
      BundleTable.EnableOptimizations = true;

      bundles.Add(new StyleBundle("~/assets/css").Include(
        "~/Content/css/dark-hive/jquery-ui.css",
        "~/Content/css/bootstrap.css",
        "~/Content/css/site.css"
      ));

      ScriptBundle libs = new ScriptBundle("~/assets/libs");
      libs.Orderer = new UserDefinedBundleOrderer();
      libs.Include(
        "~/Scripts/libs/jquery-1.8.2.js",
        "~/Scripts/libs/jquery-ui-1.8.24.js",
        "~/Scripts/libs/jquery-ui.datepicker.es.js", 
        "~/Scripts/libs/underscore-1.4.1.js",
        "~/Scripts/libs/backbone-0.9.2.js",

      bundles.Add(libs);
    }
  }

  public class UserDefinedBundleOrderer : IBundleOrderer {
    public virtual IEnumerable<FileInfo> OrderFiles(BundleContext context, IEnumerable<FileInfo> files) {
      return files;
    }
  }
}

Espero que os sirva de ayuda.

Overflow scroll fluido para safari mobile

Algunos desarrolladores que hacemos webs para dispositivos móviles como puede ser un iPhone o un iPad, a veces nos encontramos con un gran problema y es que si queremos hacer un scroll horizontal funciona pero no queda muy fluido. Supongamos que tenemos una pequeña página y a modo de appstore, queremos tener un cuadro que tenga varias capturas de pantalla o imágenes y que entre las imágenes, hemos hecho un scroll. Si probamos esto en un iPad o un iPhone, veremos como el scroll no es muy fluido, va como a tropezones, pero la solución es bien fácil, solo hay que cambiar un pequeño estilo de CSS.

Para solucionar esto podemos utilizar -webkit-overflow-scrolling: touch; para indicarle a safari mobile que queremos hacer un scroll con el dedo y de esta forma, el scroll ira fluido y no se trabará.

Os dejo un ejemplo de como quedaría:

Mobile test

Cambiar los saltos de linea rn de Windows a n de Linux, Unix, Mac OSX

Quienes tenemos que trabajar con código fuente entre varios sistemas operativos, a veces nos encontramos con un mas que desagradable problema, y es que los saltos de linea se desvirtuan. Al trabajar desde un sistema operativo nix, como pueden ser: Linux, Unix, Mac OSX (si ya se que es un Unix pero es por dejarlo claro) y mover esos ficheros a un Windows, salvo que editemos los ficheros con el avanzadísimo sistema del notepad, no tendremos mayores complicaciones. Realmente, si editamos a la inversa, es decir, llevando el archivo desde Windows a Mac OSX o a Linux, no tendremos tampoco muchos problemas, ya que los sistemas están preparados para soportar los saltos de linea. El problema real radica en los sistemas de control de versiones.

Pongo en situación para quien no lo conozca. En los sistemas operativos hay un caracter especial que determina el salto de linea, lo que ocurre cuando pulsamos la tecla intro en un editor de texto, como si de una maquina de escribir, baja un nivel, hasta la siguiente linea. El caracter de salto de linea se representa con n. Ahora vayamos a Windows y su similitud con las máquinas de escribir. En Windows no basta con hacer un salto de linea n, sino que ademas hay que hacer un retorno de carro. Probablemente muchos no sepan que significa un retorno de carro representado con r pero viene de cuando en las máquinas de escribir antiguas llegabas al final de la linea, con una palanca que había en el extremo, el carro (donde se posiciona para escribir en el papel) se desplazaba hasta el principio de la linea. Por tanto en Windows, el salto de linea se representa con rn es decir, retorno de carro (volver el cursor al principio de la linea) y un salto de linea.

Es por esto, que cuando tenemos un sistema de control de versiones como puede ser GIT o SVN y archivos de diferentes sistemas nos podemos encontrar con el problema de que nos dice que el 100% del archivo ha cambiado, solo porque ha cambiado el salto de linea y entiende que es una linea nueva. Esto por ejemplo pasa con el cliente de consola de GIT por poner un caso, pero ocurre en mas lugares. La solución es muy fácil, solo tenemos que ejecutar un script que nos corrija los molestos saltos de linea de Windows de la siguiente manera:

perl -i -pne "s/rn/n/g" archivo-a-corregir.html

Donde le decimos a perl que recorra cada linea del archivo en modo sed y que nos sustituya los rn de Windows por los n de Linux/Mac OSX. También podemos utilizar el comando sed tal que:

sed -i "s/rn/n/g" archivo-a-corregir.html

Cual utiliceis es a gusto de cada uno. Quizas el sed sea mejor, puesto que al ser un comando del sistema operativo y no perl directamente a alguno le gusta mas.

Desactivar el scroll vertical en apps de phonegap

Al hacer una app con phonegap, nos encontramos con que el scroll horizontal se desactiva fácilmente, ya que phonegap, al tener un webview, este se adapta a nuestro html y si ademas eliminamos la opción de zoom con los scale

<meta name="viewport" content="initial-scale=1, maximum-scale=1, minimun-scale=1, user-scale=no" />

Resultará curioso como al probar nuestra aplicación, horizontalmente es estática, pero cuando deslizamos el dedo de arriba hacia abaja, vemos un efecto cuanto menos curioso y es que se desliza como si fuera una página web normal y corriente, es decir, nos aplica un scroll vertical como el navegador. Os pongo una imagen para que veáis lo que digo:

Esto es muy fácil de arreglar. Tan solo tenemos que irnos a nuestro proyecto de phonegap, concretamente al archivo Cordova.plist, que lo podemos encontrar de 2 formas:

  • Xcode: raíz del proyecto > Resources > Cordova.plist
  • Finder: raíz del proyecto > [Nombre del proyecto] > Cordova.plist

Ahora, dependiendo de si lo editamos desde Xcode o con otro editor veremos algo como lo siguiente:

Tan solo deberemos poner el valor del UIWebViewBounce a NO en Xcode o a false en el xml del plist y asunto arreglado, al intentar hacer scroll vertical, ya no se deslizará fuera de la pantalla.

El porque del estilo Metro y Windows 8, cuando debemos de actualizar nuestro navegador

De casualidad y haciendo unas pruebas para una web, di con la clave del por que del diseño que se utiliza en Windows Mobile y en las futuras versiones a partir de Windows 8 en escritorio. Los diseñadores de Redmon, se les ocurrió la idea de copiar un framework de fronted como puede ser bootstrap de twitter, tras pensarlo deliveradamente, decidieron entrar en la web de bootstrap con la versión en ese momento de Internet Explorer.

Aunque en el momento ya estaba Internet Explorer 9, como iba a ser utilizado para Windows 8, decidieron entrar con la versión de Internet Explorer 8 (por eso de hacer el honor al 8) y se encontraron una agradable sorpresa y es que el diseño les encanto. Pero ojo, no penséis si vais corriendo a la web de bootstrap vais a ver lo mismo que ellos vieron, nada mas lejos de la realidad. Lo que verían estos diseñadores eran cajas cuadradas, de colores claros, elegantes y lisos. Nada de degradados, brillos y efectos. Os dejo una captura de como se ve la web en Internet Explorer 8 y os animo a entrar con vuestro navegador favorito, ya sea Chrome, Firefox, Safari, etc.

Ni que decir tiene que es una chorrada de las típicas que se le ocurren a uno cuando lleva demasiadas horas trabajadas y que la interfaz Metro, Windows 8 o ModernUI como la llaman (ya que con Metro tienen un pleito de marcas registradas), es una interfaz que aunque para mi gusto tengo otras preferencias con mas curvas, no es desagradable a la vista (aunque si algo extraña). Por supuesto todo tiene su por que y esta interfaz no es menos.

Espero que por lo hemos os haya sacado una sonrisa.