HTML5 Apis: File API

¡Muy buenas! Vamos a empezar una serie de posts (que como digo siempre, a ver donde nos llevan) sobre las APIs de HTML5, dado que hay muchas (algunas más conocidas que otras). La que veremos en este post es File API que dicho rápidamente nos permite leer ficheros locales usando javascript.

Si al leer que ahora podemos leer ficheros desde javascript se te han puesto los pelos como escarpias pensando en los posibles agujeros de seguridad, tranquilo: no hay forma alguna de leer un fichero a través de su ruta. Siempre se requiere que sea el usuario el que inicie la acción y abra explícitamente el fichero.

Leyendo datos de un fichero

Lo primero que necesitamos para poder acceder al contenido de un fichero es que el usuario lo abra. ¿Y que mecanismo tenemos en HTML para permitir al usuario seleccionar uno o varios ficheros? Exacto! El feote <input type=”file” /> y eso es lo primero que necesitamos.

    1 <!DOCTYPE html>

    2 

    3 <html>

    4     <head>

    5         <title>title</title>

    6     </head>

    7     <body>

    8         <div>

    9             Selecciona un fichero: <br />

   10             <input type=»file» value=»Leer» id=»fichero»/> 

   11         </div>

   12         <script type=»text/javascript»>

   13             function ficheroSeleccionado(evt) {

   14                 var ficheros = evt.target.files;

   15                 // Tan solo procesaremos el primer fichero

   16                 var fichero = ficheros[0];

   17             }

   18             document.getElementById(«fichero»).addEventListener(‘change’, ficheroSeleccionado, false);

   19         </script>

   20     </body>

   21 </html>

Si ejecuto eso mismo en Chrome, y pongo un breakpoint en la línea 17 veo lo siguiente:

image

Podemos ver como efectivamente la propiedad files del <input> me ha devuelto una FileList y el primer elemento es un File con la información del archivo seleccionado. ¡Bien!

Una vez tenemos un objeto File ya podemos leerlo, para ello debemos instanciar un FileReader y llamar a algunos de sus métodos:

  • readAsBinaryString: para leerlo de forma binaria . Ese método devuelve una cadena con el contenido binario. Si te parece raro que se reciba una cadena con el contenido en binario, decirte que a los que crearon la API les debió parecer lo mismo (léete la PD al final del post).
  • readAsText: para leerlo como texto
  • readAsDataURL: para leerlo como “data-url” (eso es ideal para previews de imágenes).

Vamos a ver un ejemplo rapidísimo: vamos a crear un visor hexadecimal. Para ello añadimos dos <div>s, uno de los cuales contendrá los códigos hexadecimales de cada byte del archivo y otro contendrá el carácter ASCII imprimible asociado:

    1         <style>

    2             .terminal {font-family: courier new}

    3             #raw {float: left}

    4             #rawtext {float:right}

    5         </style>

    1         <div id=»raw» class=»terminal»></div>

    2         <div id=»rawtext» class=»terminal» ></div>

Y ahora usaremos readAsBinaryString para obtener el contenido binario del archivo.

Cuando usemos las funciones de FileReader debemos tener presente que esas NO devuelven ningún resultado, si no que nos lanzan un evento cuando la lectura ha finalizado, y entonces podemos consultar el valor de la propiedad result del FileReader. Para ello modificamos la función ficheroSeleccionado para que quede tal y como sigue:

    1 function ficheroSeleccionado(evt) {

    2     var ficheros = evt.target.files;

    3     // Tan solo procesaremos el primer fichero

    4     var fichero = ficheros[0];

    5     var reader = new FileReader();

    6 

    7     reader.onloadend = function(ievt) {

    8         if (ievt.target.readyState == FileReader.DONE) {

    9             mostrarResultado(ievt.target.result);

   10         }

   11     };

   12 

   13     reader.readAsBinaryString(fichero);

   14 }

Fijaos que asignamos una función gestora al evento loadend, que nos lanza el FileReader para indicar que la lectura ha finalizado. En esta función gestora nos limitamos a asegurarnos que realmente la lectura no ha dado error y si es el caso llamamos a mostrarResultado que será la función que rellenerá los dos <div>s:

    1 function mostrarResultado(resultado) {

    2     var raw = document.getElementById(«raw»);

    3     var rawtext = document.getElementById(«rawtext»);

    4     var shtmlraw = «»;

    5     var shtmltext = «»;

    6     for (var idx = 0; idx < resultado.length; idx++) {

    7         var ascii = resultado.charCodeAt(idx);

    8         var codigo = ascii.toString(16);

    9         if (codigo.length < 2) codigo = «0» + codigo;

   10         shtmlraw += codigo + «&nbsp;»;

   11         shtmltext += ascii >= 32 && ascii <= 127 ? «&#» + ascii : «.»;

   12         if ((idx + 1) % 8 == 0 && (idx + 1) % 24 != 0) {

   13             shtmlraw += «&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;»;

   14         }

   15         if ((idx+1) % 24 == 0) {

   16             shtmlraw += «<br />»;

   17             shtmltext += «<br />»;

   18         }

   19     }

   20 

   21     raw.innerHTML = shtmlraw;

   22     rawtext.innerHTML = shtmltext;

   23 }

No hay mucho que contar sobre esa función, es javascript puro y duro 🙂 Un consejo por si alguna vez usáis la propiedad innerHTML para asignar código HTML a un elemento del DOM: es muuuuuuuuy lenta. Así que es mejor ir creando el código en una cadena y usar innerHTML una sola vez al final.

¡Y listos! Ya puedo seleccionar un fichero cualquiera y ver su contenido binario:

image

Ahhh… que nostalgia de aquellos tiempos de MS-DOS, con aquellos editores hexadecimales tan bonitos, eh??? Pues bueno, aquí tenéis una buena imitación, eso sí solo lectura, que File API no permite modificar en ningún caso el contenido de ningún archivo!

Previsualizando imágenes

Bueno… ya puestos vamos a añadir un poco de funcionalidad a nuestro editor hexadecimal. Si el archivo seleccionado es una imagen vamos a visualizarla como tal (junto con su volcado hexadecimal).

Y es que File API nos permite de forma muy fácil crear una previsualización de una imagen, gracias al método readAsDataURL. Ya hablé hace tiempo en este blog de las data url así que no me repetiré ahora, simplemente para resumir: el atributo src de un <img> puede ser una URI especial (que empieza por data:) y que tiene el contenido en Base64 de la imagen a mostrar.

Pues bien, eso es precisamente lo que nos devuelve readAsDataURL. Así para previsualizar una imagen basta con asignar su atributo src al valor leído por el FileReader (en el evento loadend por supuesto). Veamos como queda el código completo.

En este caso el código queda un poco más liado porque lo que debemos hacer ahora es:

  1. Si el fichero es una imagen debemos
    1. Leerlo usando readAsDataURL y previsualizarlo
    2. Leerlo de nuevo usando readAsBinaryString y previsualizarlo
  2. Si el fichero NO es una imagen debemos
    1. Leerlo usando readAsBinaryString y previsualizarlo

Para ello modificamos primero la función ficheroSeleccionado para saber si el fichero es una imagen o no y actuar en consecuencia:

    1 function ficheroSeleccionado(evt) {

    2     var ficheros = evt.target.files;

    3     // Tan solo procesaremos el primer fichero

    4     var fichero = ficheros[0];

    5     var reader = new FileReader();

    6 

    7     if (fichero.type.match(‘image.*’)) {

    8         leerImagen(reader, fichero);

    9     }

   10     else {

   11         leerBinario(reader, fichero);

   12     }

   13 

   14 }

El método leerBinario es simplemente el código de lectura que teniamos antes en ficheroSeleccionado:

    1 function leerBinario(reader, fichero) {

    2     reader.onloadend = function (ievt) {

    3         if (ievt.target.readyState == FileReader.DONE) {

    4             mostrarResultado(ievt.target.result);

    5         }

    6     };

    7 

    8     reader.readAsBinaryString(fichero);

    9 }

El método mostrarResultado por supuesto es el mismo de antes 😉

Vayamos ahora a por el método leerImagen. Este simplemente leerá usando readAsDataURL y luego llamará a leerBinario:

    1 function leerImagen(reader, fichero) {

    2     reader.onloadend = function (ievt) {

    3         if (ievt.target.readyState == FileReader.DONE) {

    4             previsualizarImagen(ievt.target);

    5             leerBinario(reader, fichero);

    6         }

    7     };

    8     reader.readAsDataURL(fichero);

    9 }

Y para completar la ecuación tan solo nos queda el método previsualizarImagen:

    1 function previsualizarImagen(filereader) {

    2     var datauri = filereader.result;

    3     var image = document.getElementById(«preview»);

    4     image.src = datauri;

    5     image.style.visibility = «visible»;

    6 }

Fijaos que se limita a poner en el atributo src de una imagen el valor leído por el FileReader usando readAsDataURL. Y eso es lo que vemos si seleccionamos una imagen:

image

Fijaos como podemos ver la imagen, sin que esa haya subido en ningún momento al servidor.

¡Y listos! Con eso ya hemos visto lo básico de File API. Hay más, pero mejor lo dejamos para otro post de esta serie 😉

PD: Notas sobre soporte de los navegadores.

El código de este post lo he probado con Chrome (a la hora de escribirlo era la versión 23.0, cuando le leáis a saber cual es) y con IE10. Ambos soportan File API (al igual que el resto de los navegadores importantes).

Peeeeeero el método readAsBinaryString NO está soportado en IE10. Pero, que quede claro, no es un incumplimiento del estándard: El estandard de la W3C no define un método readAsBinaryString (lo podeis ver en http://www.w3.org/TR/FileAPI/#dfn-filereader). Existió tiempo atrás pero se marcó como obsoleto (y en la versión final ha desaparecido). Chrome lo mantiene (creo que FF también) pero IE10 es más estricto con el cumplimiento del estandard y no lo hace.

Eso es típico cuando usamos HTML5: algunas de esas APIs están vivas o se han terminado hace muy poco y a veces es fácil caer en métodos obsoletos o ya desparecidos.

PD2: Vale… muy bien ¿pero como acceder al contenido binario usando la última especificación del estandard?

¡Que nadie se alarme! Es muy sencillo: debemos usar el método readAsArrayBuffer() en lugar de readAsBinaryString() que nos devuelve un ArrayBuffer que contiene los valores. Veamoslo.

El cambio a leerBinario es trivial:

    1 function leerBinario(reader, fichero) {

    2     reader.onloadend = function (ievt) {

    3         if (ievt.target.readyState == FileReader.DONE) {

    4             mostrarResultado(ievt.target.result);

    5         }

    6     };

    7 

    8     reader.readAsArrayBuffer(fichero);

    9 }

Y será mostrarResultado el que ahora en lugar de recibir una cadena con el contenido en binario recibe un ArrayBuffer. El tema es que los ArrayBuffer no se pueden consultar directamente. En su lugar debe usarse una vista por encima del ArrayBuffer. En nuestro caso dado que queremos leer byte a byte usaremos un Uint8Array.

El código de mostrarResultado es idéntico al que ya teníamos con la excepción del principio:

    1 function mostrarResultado(resultado) {

    2     var raw = document.getElementById(«raw»);

    3     var rawtext = document.getElementById(«rawtext»);

    4     var shtmlraw = «»;

    5     var shtmltext = «»;

    6     var view = new Uint8Array(resultado);

    7     for (var idx = 0; idx < view.length; idx++) {

    8         var ascii = view[idx];

El resto del código es idéntico. Fijaos como creamos el Uint8Array por encima del ArrayBuffer devuelto y luego ya leemos byte a byte. Dado que ahora view es un array ya de bytes y no una cadena como antes, ya no necesitamos usar charCodeAt() para obtener el código ascii (valor del byte) asociado.

Ahora sí que el código debería funcionar tanto en IE10, como en Chrome, como en FF como en el resto de navegadores importantes!

El orden de los algoritmos… esa gran O.

¡Muy buenas! Este va a ser un post teórico que nada tiene que ver con el desarrollo concreto en .NET. Lo que vamos a decir aquí es aplicable a cualquier algoritmo, esté implementado en .NET, Java, Scala, Javascript, Dart, Smalltalk o cualquier otro lenguaje existente. No, no voy a hablar de buenas prácticas, ni nada parecido. Voy a hablar de un concepto que se usa en la ingenería del softwara para clasificar algoritmos en función de bueno… eso lo veremos con más detalle.

Disclaimer: Este post pretende ser introductorio, así que voy a realizar ciertas simplificaciones. La idea es que se entienda el concepto y lo que significa… 🙂

A dicho concepto lo conocemos como orden (realmente orden de complejidad) del algoritmo, y la notación empleada se conoce como Big-O Notation (aahh… que bien que suenan las cosas en inglés :P) debido a que se emplea la letra O (mayúscula) como símbolo.

De hecho seguro que más de uno ha visto, cosas como p.ej. que un algoritmo es O(n) mientras que otro es O(n ^2). Pero… exactamente ¿qué significa eso?

Se puede argumentar que el orden de un algoritmo nos define cuan rápido es. Así un algoritmo con O(n) será más rápido que otro con O(n^2), por la sencilla razon de que n^2 >= n.

Pero esa visión no es cierta. El orden de un algoritmo no mide su rapidez, aunque nos permite ordenar los algoritmos del más eficiente al menos eficiente. Alguna vez en literatura informática he visto cosas como “ese algoritmo es de O(2n)”. Bien, esta sentencia es totalmente incorrecta: No existe O(2n). O dicho de otro modo O(2n) = O(n)

Quizá esto te sorprenda, pero es lo que hay 😉 Si el orden pretendiese medir cuan rápido es un algoritmo entonces si que tendría sentido algo como O(2n) que indicaría que un algoritmo determinado es el doble de lento que otro con O(n).

Pero, como digo, el orden no pretende medir cuan rápido es un algoritmo respecto a otro. El orden mide otra cosa. Mide cuan rápidamente aumenta el tiempo de ejecución de un algoritmo cuando aumenten los datos de entrada. Tomemos como ejemplo un algoritmo cualquiera, p.ej. uno para ordenar listas.

Si tiene O(n) significa que el tiempo aumenta linealmente al aumentar los datos de entrada. Es decir, que si para una lista de 100 elementos el algoritmo tarda x segundos, para una lista de 1000 elementos (10 veces más grande) tardará 10 veces más. Es, en definitiva, lo que nos dice el sentido común: si te doblo el tamaño de entrada, debes tardar el doble. Lógico, ¿no? De hecho, el orden lineal es una característica deseable de cualquier algoritmo.

Pero ¡ojo! por supuesto, podemos tener dos algoritmos distintos para ordenar listas, ambos de O(n) y uno mucho más rápido que otro. Pero ambos aumentarán linealmente su tiempo de ejecución al aumentar el tamaño de los datos de entrada.

Por otro lado si el algoritmo tiene O(n^2) significa que el tiempo aumenta cuadráticamente. No quieras tener algoritmos como esos: en este caso si para ordenar una lista de 100 elementos el algoritmo tarda x segundos, para una lista de 1000 elementos ¡tardara 100 veces más! Es decir, hemos aumentado los datos de entrada en un ratio de 10 y el algoritmo no tarda 10 veces más si no 100 (10^2). Pero bueno… si debes lidiar con uno de esos, consuelate pensando que, aunque no lo parezca, los hay de peores, como los que tienen orden polinomial (O(n^a) donde a es mayor que 2), los todavía peores de orden exponencial (O(a^n) donde a es mayor que 1) y quizá los peores de todos, totamente intratables, los de orden factorial (O(n!)).

Pero existen unos algoritmos que desafían al sentido común y son una maravilla: en estos el tiempo aumenta logarítmicamente. Es decir, si para ordenar una lista de 100 elementos el algoritmo tarda x segundos, para ordenar una lista 10 veces más larga tardará… ¡tan solo el doble! ¡Una maravilla! Esos son los que tienen un orden O(log n) y los que, por supuesto, se intentan encontrar en cualquier caso.

Por norma general, siempre que sea posible debemos usar un algoritmo del menor orden posible. Es decir si tenemos dos algoritmos que hacen lo mismo y uno es de O(n) y el otro es O(n^2) mejor usamos el primero, ya que nos protege mejor contra volúmenes de datos grandes, aunque todo depende… porque si sabemos que nuestros datos nunca van a crecer por encima de un determinado umbral, quizá nos interese usar uno de orden mayor pero que sea más rápido (aunque el orden nos dice que se volvería más lento a partir de cierto tamaño de los datos de entrada).

Por último mencionar que el orden se suele aplicar al tiempo de ejecución, pero puede aplicarse a otros aspectos (p.ej. la memoria que consume un determinado algoritmo).

¡Un saludo!

ASP.NET SimpleMembership: Una vuelta de tuerca más

Cuando, allá por el 2005, aparecía ASP.NET 2.0 una de las novedades que incorporaba era el sistema de Membership. Dicho sistema pretendía ser una solución unificada para solucionar problemas de autenticación y autorización de usuarios. La idea era muy simple: en lugar de que los controles web (recordad, estamos en 2005, MVC no existe) accedan a la BBDD directamente (o el proveedor de autorización usado, como Active Directory) para comprobar logins y passwords se usa una capa intermedia que centralice dichos accesos. Dicha capa se estandariza y pasa a formar parte de la API del sistema para que cualquier control la pueda usar. Es esta capa lo que conocemos con el nombre de Membership (aunque realmente incluye el proveedor propiamente de Membership (usuarios), el de Roles y el de perfiles). Es curioso como, a tenor de las preguntas en los foros de MSDN en español, todavía hay hoy, más de siete años después de la salida de ASP 2.0 mucha confusión al respecto de Membership. De serie ASP.NET venía (viene) con un proveedor de Membership para SQL Server y otro para Active Directory (autenticación windows). Si requieres que la información de tus usuarios esté en otro sistema (p.ej. MySql) debes crearte un proveedor propio (lo que llamamos custom membership provider), que realmente es crear una clase que derive de MembershipProvider.

A lo largo del tiempo el sistema de Membership ha mostrado sus problemas. Los más evidentes son:

  1. Una interfaz muy hinchada. El proveedor de Membership intenta dar solución “a todo lo posible en temas de Membership”. Eso significa que si tienes que crearte un proveedor propio vas a tener que implementar muchos métodos, aunque no tengan sentido en tu aplicación. P.ej. si en tu aplicación los usuarios no pueden estar bloquados da igual. Deberás implementar los métodos de bloquear y desbloquear usuarios porque están declarados en el Membership. O al revés… si tus usuarios NO tienen password (p.ej. usas OAuth) da igual, porque Membership requiere un password por cada usuario.
  2. Un esquema SQL fijo. Antes he comentado que ASP.NET incorpora de serie un Membership provider para SQL Server. Pues bien, eso es cierto siempre y cuando use el esquema prefijado del Membership provider. Si quiero que mis usuarios se almacenen en mi tabla “Usuarios” ya no podré usar el Memebrship provider por defecto, porque este espera que las tablas tengan unos nombres y columnas predeterminados.

Con el tiempo el Membership ha ido sufriendo ciertas mejoras, todas ellas en tiempos más o menos recientes ciertamente, para intentar solucionar algunos de los problemas. La más importante es la aparición de los Universal Providers, de los cuales ya escribió José M. Aguilar en su blog. Estos intentan evitar que tengamos que escribir nuestro propio Membership provider si queremos usar otra BBDD que no sea Sql Server. Las últimas releases de los Universal Providers solucionan el problema que José María menciona en su blog (que no consiguió hacerlo funcionar con MySql) y funcionan con cualquier BBDD ya que usan EF para conectarse (por lo que cualquier BBDD que tenga un proveedor de EF será válida y eso incluye, entre otras, a MySql). De regalo, los Universal Providers nos traen una simplificación del esquema SQL usado, lo que es otro avance 😉 Pero ojo, aunque ahora tenemos un esquema simplificado, seguimos estando atados al esquema de tablas que requieren los universal providers, así que si queremos usar nuestro propio esquema de BBDD entonces seguimos estando obligados a escribirnos nuestro propio Membership provider…

… al menos, hasta la aparición del Simple Membership!

Así pues ahora en ASP.NET tenemos dos modelos de Membership, el clásico que data de 2005 y cuya última iteración serían los universal providers y el nuevo conocido por SimpleMembership. La ventaja de SimpleMembership respecto al Membership clásico es que se integra con cualquier esquema de BBDD existente… Pero, ojo! SimpleMembership tan solo funciona con cualquier BBDD de la familia de SQL Server. Es decir, con cualquier versión de SQL Server (incluyendo Express), SQL Azure, SQL Compact y la última iteración de SQL Server Express conocida como LocalDb.

De todos modos que nadie se lleve a engaño: SimpleMembership deriva del Membership clásico y eso en el sentido más literal. Por un lado en WebMatrix.WebData.dll nos encontramos con:

public abstract class ExtendedMembershipProvider : MembershipProvider

Y luego con:

public class SimpleMembershipProvider : ExtendedMembershipProvider

Así que queda claro, no? Por cierto que un vistazo al código fuente de SimpleMembershipProvider también nos aclara el porque solo funciona bajo la familia de BBDD de Sql Server:

if (!SimpleMembershipProvider.CheckTableExists(db, SimpleMembershipProvider.OAuthMembershipTableName))

  db.Execute("CREATE TABLE " + SimpleMembershipProvider.OAuthMembershipTableName + " (Provider nvarchar(30) NOT NULL, ProviderUserId nvarchar(100) NOT NULL, UserId int NOT NULL, PRIMARY KEY (Provider, ProviderUserId))", new object[0]);

Este código precedente está dentro del método interno CreateTablesIfNeeded y como podéis ver usa directamente sintaxis de SQL Server. Códigos similares a esto se repiten en otros métodos de la clase SimpleMembership.

Llegados a este punto debemos tener claro que podemos usar SimpleMembership en cualquier sitio donde se espere el Membership clásico (p.ej. controles Webforms) pero al revés obviamente no. Actualmente las APIs que usan SimpleMembership son Web Pages 2 (es decir WebMatrix 2) o bien el template de “Internet Application” de MVC4. En este post nos centraremos tan solo en ASP.NET MVC4.

SimpleMembership en ASP.NET MVC 4

Si creamos un proyecto nuevo de ASP.NET MVC4 del tipo “Internet Application” VS2012 nos genera un AccountController que va a usar el SimpleMembership (en lugar de generarnos un AccountController que use el código del Membership tradicional), además de generarnos toda la infraestructura necesaria para ponerlo en marcha.

Si miráis el código del web.config veréis que NO hay en ningún momento ninguna referencia a la configuración del proveedor de Membership (etiqueta <membership> del web.config). De hecho no hay ninguna referencia a SimpleMembership en el web.config. Y es que SimpleMembership se “habilita por defecto” siempre y cuando se referencie el ensamblado WebMatrix.WebData.dll. La clave está en el siguiente código de la clase WebMatrix.WebData.ConfigUtil.cs:

private static bool IsSimpleMembershipEnabled()

    {

      string str = ConfigurationManager.AppSettings[WebSecurity.EnableSimpleMembershipKey];

      bool result;

      if (!string.IsNullOrEmpty(str) && bool.TryParse(str, out result))

        return result;

      else

        return true;

    }

El valor de WebSecurity.EnableSimpleMembershipKey es “enableSimpleMembership”. De este código se deduce que el SimpleMembership se habilitará si existe el appSetting “enableSimpleMembership” con valor a true o bien si dicho appSetting no existe.

Dicho código se llama en el siguiente método (de la clase WebMatrix.WebData.WebSecurity):

internal static void PreAppStartInit()

{

  if (!ConfigUtil.SimpleMembershipEnabled)

    return;

  MembershipProvider currentDefault1 = Membership.Providers["AspNetSqlMembershipProvider"];

  if (currentDefault1 != null)

  {

    SimpleMembershipProvider membershipProvider = WebSecurity.CreateDefaultSimpleMembershipProvider("AspNetSqlMembershipProvider", currentDefault1);

    Membership.Providers.Remove("AspNetSqlMembershipProvider");

    Membership.Providers.Add((ProviderBase) membershipProvider);

  }

  // Codigo omitido por brevedad…

}

Fijaos en lo que hace dicho código:

  1. Mira si se usa SimpleMembership
  2. En este caso obtiene el proveedor de Membership con clave AspNetSqlMembershipProvider
  3. Crea un SimpleMembershipProvider (vinculado al proveedor de Membership anterior)
  4. Elimina el proveedor de Membership encontrado en el punto 2.
  5. Añade el SimpleMembershipProvider como nuevo proveedor de Membership (recordad que SimpleMembershipProvider deriva de ProviderBase).

Si alguien se pregunta desde donde se llama el método PreAppStartInit() se llama desde el método Start() de la clase WebMatrix.WebData.PreApplicationStartCode. Pero si buscas desde donde se llama este método Start() encontrarás que no se llama desde ningún sitio. ¿Y entonces? Entonces ha llegado la hora que leas este post de @haacked: http://haacked.com/archive/2010/05/16/three-hidden-extensibility-gems-in-asp-net-4.aspx. En este post se explican tres métodos de extensibilidad de ASP.NET que no son muy conocidos. De todos nos interesa el primero, el atributo PreApplicationStartMethod que te permite declarar un método para ser invocado esto… antes del Application_Start. Y en efecto. el ensamblado WebMatrix.WebData usa este atributo:

[assembly: PreApplicationStartMethod(typeof (PreApplicationStartCode), "Start")]

¡Y así cerramos el círculo! Ya sabemos como y cuando se crea el SimpleMembership: antes de inicializar la aplicación web.

Tan solo queda aclarar que cualquier aplicación ASP.NET 4 (y eso incluye ASP.NET MVC4) incluye un proveedor de Membership llamado AspNetSqlMembershipProvider, incluso si no lo define en el web.config, ya que el machine.config contiene dicha definición.

Y así terminamos este post. Hemos visto que es el SimpleMembership, la relación que tiene con los antiguos proveedores de Membership de ASP.NET y como se carga y configura. Nos queda ver como usarlo, pero eso lo dejamos para otro post!

Un saludo!

ASP.NET WebApi y X-HTTP-Method-Override

Muy buenas! Después de largo tiempo vuelvo a la carga con otro post sobre ASP.Net WebApi. En un post anterior vimos como WebApi usaba automáticamente el verbo http usado para invocar el método correspondiente del controlador. Eso está muy bien en aquellos casos en que el cliente es una aplicación de escritorio y tiene acceso a todos los verbos http posibles. Pero si el cliente es una aplicación web es posible que tan solo tenga acceso a dos de los verbos http: GET y POST.

En una aproximación REST, habitualmente GET se usa para recuperar datos y POST para modificar datos existentes. Se usa DELETE para eliminar datos y PUT para insertar datos nuevos. Si tenemos un controlador WebApi con el siguiente código:

public class PlayerController : ApiController

{

    public string GetById(string id)

    {

        // Devolver el jugador con el id indicado

        return id;

    }

    public string Put(string name)

    {

        // Crear un jugador nuevo y devolver su id

        return "new player created " + name;

    }

}

Si queremos invocar el método put debemos usar el verbo HTTP PUT pero eso, en navegadores puede no ser posible (puedes ver que métodos soporta tu navegador a través de XmlHttpRequest en http://www.mnot.net/javascript/xmlhttprequest/).

Para seguir permitiendo el enrutamiento según verbo http pero a la vez dar soporte a navegadores que no soporten otros verbos http salvo GET y POST se inventó la cabecera X-HTTP-Method-Override. La idea es guardar en esta cabecera el verbo http que se querría haber usado (p.ej. PUT) y usar el verbo http POST para realizar la llamada. Esta cabecera HTTP no es un estandard reconocido, comenzó a ser utilizada por Google creo y su uso se ha extendido (hay variantes de dicha cabcera, p.ej. la especificación de OData usa X-HTTP-Method en lugar de X-HTTP-Method-Override pero la idea es la misma).

Lamentablemente ASP.NET WebApi no tiene soporte para X-HTTP-Method-Override (ni para X-HTTP-Method ni ninguna otra variante). Si usas el verbo POST todas las llamadas se enrutarán a alguno de los métodos cuyo nombre empiece por Post con independencia del valor de estas cabeceras.

DelegatingHandlers

Por suerte dentro de ASP.NET WebApi no se incluye tan solo la idea de “haz controladores que devuelvan objetos y deja que se enruten a través del verbo http”. También se incluyen un conjunto de clases nuevas para interaccionar con la pipeline de Http… y entre esas encontramos los DelegatingHandlers.

Si tienes experiencia con los HttpModules, la idea es similar: un DelegatingHandler intercepta una petición http (también puede interceptar la respuesta si fuese necesario). A nivel de WebApi existe una cadena de DelegatingHandlers y la petición va viajando de uno a otro. Cada DelegatingHandler puede modificar los datos de la petición acorde a lo que necesite y pasar la petición al siguiente DelegatingHandler de la cadena. Lo mismo aplica a la respuesta http por supuesto.

¿Ya tienes la solución, verdad? 😉

Efectivamente, basta con crear un DelegatingHandler que recoja la petición, examine las cabeceras, mire si existe X-HTTP-Method-Override y establezca como nuevo verbo HTTP el valor que se indique en dicha cabecera.

El código puede ser algo parecido a:

public class OverrideMethodDelegatingHandler : DelegatingHandler

{

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)

    {

        if (request.Method == HttpMethod.Post && request.Headers.Contains("X-HTTP-Method-Override"))

        {

            var newMethod = request.Headers.GetValues("X-HTTP-Method-Override").FirstOrDefault();

            if (!string.IsNullOrEmpty(newMethod)) {

                request.Method = new HttpMethod(newMethod);

            }

        }

        return base.SendAsync(request, cancellationToken);

    }

}

¿Creo que no necesita mucha explicación verdad? Simplemente validamos que la petición sea POST (si alguien envía X-HTTP-Method-Override a través de GET lo ignoramos) y si la cabecera existe modificamos el verbo http de la petición.

Ahora tan solo nos queda el punto final: registrar nuestro DelegatingHandler. Como todo en WebApi (y ASP.NET MVC) se sigue la filosofia de usar una clase estática con la configuración:

GlobalConfiguration.Configuration.MessageHandlers.Add(new OverrideMethodDelegatingHandler());

Y listos! Con esto ya podemos usar X-HTTP-Method-Override en nuestras APIs WebApi. Para probarlo nos basta con el siguiente código:

<!DOCTYPE html>

 

<html>

    <head>

        <title>title</title>

        <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.2.min.js"></script>

    </head>

    <body>

        <script type="text/javascript">

            $(document).ready(function() {

                $("#myfrm").submit(function (evt) {

                    var url = @Url.RouteUrl("DefaultApi", new {httproute="", controller="Player", name="xxx"}).

                        replace("xxx", $("#name").val());

                     $.ajax({

                         url: url,

                        type: ‘post’, // usamos http post

                        headers: {

                            "X-HTTP-Method-Override" : ‘PUT’

                        }

                    });

                    evt.preventDefault();

                });

            });

 

        </script>

          <div>

            <form method="POST" id="myfrm">

                <input type="text" name="name" id="name" />

                <input type="submit"/>

            </form>

 

        </div>

    </body>

</html>

Y si colocais un breakpoint en el método Put del controlador vereis como la llamada llega a pesar de estar usando POST 😉

Un saludo!

Promise Pattern

¡Buenas!

Este post está “inspirado” por un tweet de Gisela Torres. Posteriormente ella misma hizo un post en su blog sobre este mismo patrón que os recomiendo leer.

Ultimamente está muy de moda, al menos en el mundo de Javascript, hablar del Promise pattern (lo siento, pero llega un punto en que yo ya desisto de intentar encontrar traducciones para todo…). Ese patrón se asocia mucho con la realización de aplicaciones asíncronas, llegándose a ver como el mecanismo para la realización de este tipo de aplicaciones.

No. El promise pattern nada tiene que ver con la creación de aplicaciones asíncronas, aunque es en estas, por razones que ahora veremos, donde se puede explotar más. Pero es basicamente un patrón de organización de código. Tampoco es exclusivo de Javascript, por supuesto… De hecho, y para no ser clásicos, vamos a ver un ejemplo de su uso en C#.

El promise pattern nos ayuda a organizar nuestro código en aquellos casos en que un método recibe como parámetro otro método (en el caso de C# un delegate). Este otro método (o delegate) es usualmente una función de callback, aunque no tiene exactamente porque.

Vamos a verlo con un ejemplo muy tonto. Imaginad una clase como la siguiente:

class NoPromise

{

    public void Sumar (IEnumerable<int> data, Action<int> next )

    {

        var result = 0;

        foreach (var item in data) result += item;

        next(result);

    }

 

    public void Invertir(int value, Action<int> next)

    {

        var result = value * -1;

        next(result);

    }

 

    public void Dividir(int value, float divisor, Action<float> next)

    {

        var result = value/divisor;

        next(result);

    }

}

Esta clase expone tres métodos Sumar, Dividir e Invertir. Ambos aceptan un segundo parámetro (un delegate) llamado next que le dice al método que hacer con el resultado.

Así podemos invocar dichos métodos así:

np.Sumar(list, x =>

    np.Invertir(x, y=>

        np.Dividir(y, 4.0f, z =>

            Console.WriteLine("El resultado es " + z))));

Aquí no tenemos asincronidad alguna, simplemente estamos encadenando métodos. Fijaos en como tenemos una “cascada” de funciones encadeandas. La llamada a la primera función (Sumar) tiene en su interior la llamada a Invertir, que en su interior tiene la llamada a Dividir que en su interior tiene el Console.WriteLine. Tenemos pues “una cascada de funciones dentro de funciones”.

Este problema es el que el promise pattern intenta solucionar… Veamos primero como sería el resultado de las llamadas usando este patrón:

var prom1 = pd.Sumar(list);

var prom2 = prom1.Then(x => pd.Invertir(x));

var prom3 = prom2.Then(x => pd.Dividir(x, 4.0f));

prom3.Then(x => Console.WriteLine("El valor es " + x));

Si preferís podríais usar una sintaxis más compacta sin declarar las variables intermedias:

pd.Sumar(list).

    Then(x => pd.Invertir(x)).

    Then(x => pd.Dividir(x, 4.0f)).

    Then(x => Console.WriteLine("final: " + x));

La idea es que el método Sumar no recibe como un parámetro el método a invocar a continuación si no que nos devuelve un objeto (el promise). A este objeto le podremos indicar (usando el método Then) cual es el siguiente método a invocar. Además los promises se encadenan entre ellos. Fijaos como hemos pasado de una llamada a un método (que dentro tenía varias llamadas más) a cuatro llamadas separadas. Eso mejora mucho la legibilidad del código que es el objetivo principal de este patrón.

Por si os interesa aquí tenéis la implementación que he usado del patrón. Primero la interfaz:

public interface IPromise<T>

{

    IPromise<TR> Then<TR>(Func<T, TR> action);

    void Then(Action<T> action);

    T Value { get; }

}

Y luego la clase que lo implementa:

class Promise<T> : IPromise<T>

{

    private T _data;

 

    public Promise(T data)

    {

        _data = data;

    }

    public IPromise<TR> Then<TR>(Func<T, TR> action)

    {

        return new Promise<TR>(action(_data));

    }

    public T Value

    {

        get{ return _data; }

    }

    public void Then(Action<T> action)

    {

        action(_data);

    }

}

Finalmente necesitamos que el método Sumar (que es el iniciador de la cadena de promises) me devuelva un IPromise:

class PromiseDemo

{

    public IPromise<int> Sumar(IEnumerable<int> data)

    {

        var result = 0;

        foreach (var item in data) result += item;

        return new Promise<int>(result);

    }

    public int Invertir(int value)

    {

        return value * -1;

    }

    public float Dividir(int value, float div)

    {

        return value / div;

    }

}

El resto de métodos son métodos “normales”.

¿Y porqué (casi) todo el mundo asocia el promise pattern con asincronidad?

Bueno… si os fijáis el promise pattern permite organizar mejor nuestro código en aquellos casos en que un método espera a otro método como parámetro. Y eso es un caso habitual en… las funciones asíncronas que, por norma general, esperan un parámetro adicional que es el callback.

Ahora imaginad la situación clásica de que el callback de una función asíncrona es a su vez una función asíncrona que espera otro callback que es a su vez otra función asíncrona con otro callback… Llegamos así a la cascada de callbacks dentro de callbacks que es justo el caso que soluciona este patrón. De ahí que la gente asocie promise pattern a asincronidad aunque no tengan nada que ver.

De hecho .NET, en la TPL tiene una implementación ya realizada del promise pattern… Os suena el método ContinueWith de la clase Task? Pues viene a ser una implementación del promise pattern (en este caso la propia clase Task actúa como promise).

¿Y porque se habla tanto del promise pattern en Javascript?

De hecho más que en javascript deberíamos decir en lenguajes funcionales donde las funciones son ciudadanos de primer orden. En C# hasta la aparición de las expresiones lambda y los delegados genéricos no podíamos implementar este patrón (de una forma cómoda). Por eso en lenguajes no funcionales no se habla mucho de este patrón ya que en estos lenguajes no puede pasarse “una función entera” como parámetro a una función.

Pero en Javascript si se puede, y la popularidad que está adquiriendo el lenguaje junto con muchos frameworks que tienen este tipo de llamadas hace que la gente empiece a hablar de este patrón.

Pero insisto: no tiene nada que ver con asincronidad (aunque ahí se use mucho). P.ej. el siguiente código jQuery no tiene nada de asíncrono pero sería un candidato perfecto a utilizarel promise pattern:

$(document).ready(function() {

    $("#cmdOpen").click(function() {

        $("#divData").fadeIn("slow", function() {

            $("#divOther").show();

        });

    });

});

¡Espero que este post sobre este patrón os haya parecido interesante!

Un saludo!

Integra oAuth en tus “viejas” aplicaciones ASP.NET MVC

En el post anterior vimos como integrar pseudo-autenticación basada en oAuth en aplicaciones MVC4, usando el paquete Microsoft WebPages OAuth Library. Pero… qué ocurre con versiones anteriores? O bien si no queréis usar este paquete? Es muy difícil integrar pseudo-autenticación basada en oAuth entonces?

Hace algún tiempo tuve precisamente esta necesidad y estuve buscando librerías que me permitiesen integrar oAuth en mi aplicación de una forma cómoda. Como todo el mundo terminé por encontrar DotNetOpenAuth pero al final no la usé. Al final me decidí por investigar como funcionaba el protocolo de oAuth e implementarme una librería propia, que se adaptase un poco más a mis necesidades.

En este post os voy a mostrar como usar esta librería que he realizado y que está en codeplex: http://epnukeoauth.codeplex.com/ Debo decir que aunque hay el código fuente en codeplex, no hay release binario porque no la considero “terminada”, aunque sí usable y no sé cuando la tendré “terminada” del todo. La intención es que termine siendo un paquete de NuGet.

Así que por el momento tan solo os queda descargaros el código fuente (solución VS2010) y compilarla.

A día de hoy la solución consta de cuatro proyectos:

  1. Epnuke.OAuth: Librería base de oAuth
  2. Epnuke.OAuth.Mvc: Extensiones a la librería pensadas para MVC
  3. Epnuke.OAuth.Tests: Tests unitarios
  4. Epnuke.OAuth.Demo.SignWithTwitter: Demostración de pseudo-autenticación basada en oAuth.

Es este útimo proyecto el que discutiremos en este post 😉

A diferencia de la clase OAuthWebSecurity que vimos ayer y que está atada a los diversos proveesdores oAuth (a través de los métodos RegisterXXXClient), esta librería es totalmente genérica (de hecho no solo permite pseudo-autenticación, también permite llamadas arbitrarias de oAuth, pero esto queda fuera de este post).

Eso significa que usarla no es tan sencillo como la solución de Microsoft, pero ya veréis que tampoco es mucho más complicado.

El primer paso (una vez bajada la librería) es referenciar el ensamblado Epnuke.OAuth.dll y crear una aplicación MVC (puede ser MVC3).

Para iniciar el flujo de pseudo-autenticación de oAuth nos creamos una acción en un controlador (yo he usado para variar AccountController) y he llamado a dicha acción LogOnTwitter. Esta acción es la que iniciará todo el proceso de pseudo-autenticación. Para hacerlo:

  1. Debe crearse una nueva sesión de oAuth. Esta sesión es la que nos encapsula todo el proceso de oAuth.
  2. Llamar al método RequestTemporaryCredentials. Este método hace una llamada para obtener un primer token oAuth. Este token oAuth es temporal y tan solo se usa para poder redirigir al usuario a la página de login del proveedor
  3. Redirigir al usuario a dicha página (en este caso la página de login de twitter).

El código sería tal y como sigue:

public ActionResult LogOnTwitter()

{

    var oauthSession = new OAuthClientSession(ConfigurationManager.AppSettings["consumer-key"],

        ConfigurationManager.AppSettings["consumer-secret"],

        new NonceGenerator32Bytes());

    var uri = ConfigurationManager.AppSettings["request_token"];

    oauthSession.RequestTemporaryCredentials(uri, "POST", "http://127.0.0.1:64983/Account/Callback");

    Session["oauth"] = oauthSession;

    return Redirect(oauthSession.GetAuthorizationUri(ConfigurationManager.AppSettings["authorize"]));

}

La primera línea crea la sesión de OAuth. Los tres parámetros necesarios son el consumer key, el consumer secret (esos mismos son  los dos que usábamos en el método RegisterTwitterClient del post anterior) y el generador de nonces. Un nonce es un valor “único” que se genera de forma aleatória para cada petición oAuth. El proveedor puede (puede, no está obligado a) validar que no haya dos peticiones distintas con  el mismo nonce durante un cierto periodo de tiempo. Es un mecanismo de seguridad. La especificación de oAuth es totalmente ambigua en cuanto al formato de nonce usado. Se supone que cada proveedor puede usar el formato de nonce que prefiera. Aquí uso el generador de nonces de 32 bytes que es el formato que usa twitter para el nonce (aunque desconozco si acepta otros).

Con esto tenemos una sesión lista para empezar a hacer peticiones oAuth. El siguiente método que llamamos es RequestTemporaryCredentials. A este método se le pasan los siguientes parámetros:

  1. La url del proveedor de oAuth que expone el endpoint de request_token (en el caso de twitter se llama oauth/request_token).
  2. El método http a usar (en el caso de twitter es POST).
  3. Y la dirección de callback a la que twitter nos deberá redireccionar una vez el proceso de logon esté completado.

El método RequestTemporaryCredentials realiza la petición y obtiene las credenciales temporales de oAuth pero no hace nada más. A diferencia del método RequestAuthentication de OAuthWebSecurity que vimos ayer, aquí la redirección a la página de login del proveedor la debemos hacer nosotros.

Luego nos guardamos la sesión oAuth en la sesión de la aplicación web porque la necesitaremos luego (la librería ofrece alternativas a este punto en caso de no querer/poder usar la sesión). Y finalmente redirigimos el usuario a la página de login del proveedor (endpoint authorize de oAuth). En el caso de twitter la página de login que se usa para oAuth es oauth/authenticate. Pero NO basta con redirigir a dicha página: le hemos de pasar via querystring el token temporal que hemos obtenido previamente. Y eso es lo que hace el método GetAuthorizationUri de la clase oauthSession.

En este punto redirigimos el usuario a la página de login de twitter, donde el usuario podrá entrar sus credenciales. Y una vez entradas dichas credenciales el usuario será redirigido a la URL que pasamos como parámetro al método RequestTemporaryCredentials. En nuestro caso era /Account/Callback.

Dicho método recibe por querystring el código de verificación de twitter (parámetro oauth_verifier). Dicho código significa algo como “hey! el usuario se ha autenticado correctamente”. Pero este código de verificación tan solo sirve para una cosa: para obtener los tokens oAuth definitivos y que nos permitirán hacer llamadas oAuth en nombre de este usuario.

Veamos pues el código de la acción Callback:

public ActionResult Callback(string oauth_verifier)

{

    var oauthSession = Session["oauth"] as OAuthClientSession;

    oauthSession.Authorize(oauth_verifier, ConfigurationManager.AppSettings["access_token"]);

 

    if (oauthSession.IsAuthorized)

    {

        var name = oauthSession.GetAdditionalData("screen_name");

        FormsAuthentication.SetAuthCookie(name, false);

        return RedirectToAction("Index", "Private");

    }

    else

    {

        return RedirectToAction("Index", "Home");

    }

 

}

En la primera línea recuperamos la sesión oAuth que teníamos guardada y luego llamamos al método Authorize. Dicho método espera los siguientes parámetros:

  1. El códgo de verificación enviado por el proveedor
  2. La URL que expone el endpoint access_token de oAuth. En el caso de twitter dicha URL es oauth/access_token.

Una vez se haya llamado al método Authorize, se puede usar la propiedad IsAuthorized del objeto OAuthClientSession para saber si el usuario está autorizado o ha habido algún error.

De nuevo, a diferencia de la clase OAuthWebSecurity que vimos en el post anterior, la libería se limita a decirnos si el usuario está autenticado o no. Pero no nos dice su ID o su login. Para obtenerlo ya dependemos del proveedor de oAuth que usemos. Hay dos opciones:

  1. Si el proveedor de oAuth nos ha mandado en la respuesta de acces_token el login del usuario o el ID podremos recogerlo si sabemos el nombre del campo que usa.
  2. Si el proveedor de oAuth no nos la ha mandado deberemos hacer una llamada oAuth a la API del proveedor.

Twitter nos manda el login del usuario en el parámetro screen_name, así que usamos el método GetAdditionalData de la clase OAuthClientSession para obtenerlo (si preferís el ID lo teneis en el parámetro user_id). Y una vez tenemos el login del usuario lo autenticamos en nuestro sistema con FormsAuthentication.

En este punto ya tenemos el usuario autenticado en ASP.NET. No solo esto, también tenemos en el objeto OAuthClientSession los tokens oAuth que podemos usar para hacer llamadas a la API de twitter como si fuesemos este usuario… pero esto lo dejamos para otro post 😉

Espero que os haya resultado interesante!

Un saludo!

Os dejo como referencia el enlace al proceso entero de pseudo-autenticación basada en oAuth usando twitter.

Integra oAuth en tu aplicación ASP.NET MVC

¡Buenas! Una de las novedades de ASP.NET MVC4 es la facilidad para incorporar pseudo-autenticación basada en oAuth. Si seleccionamos la plantilla de proyecto de “internet application” esta ya viene configurada por defecto y usarla es de lo más sencillo.

Veamos ahora como añadirla en el caso de que estemos usando otra plantilla de proyecto. En este caso usaremos la plantilla de proyecto “Empty” que en el caso de MVC4 significa vacío de verdad, ya que no tendremos apenas nada en nuestro proyecto.

El módulo que se encarga de proporcionarnos pseudo-autenticación oAuth en MVC4 es un paquete de NuGet llamado Microsoft WebPages OAuth Library, así que el primer paso será añadirlo a nuestro proyecto. Para ello abrimos la Package Manager Console y tecleamos Install-Package Microsoft.AspNet.WebPages.OAuth. Esto nos instalará el paquete y todas sus dependencias (entre las que están DotNetOpenAuth y algunos ensamblados propios de WebPages).

Como parte de instalación del paquete se nos modificará el web.config,  básicamente con la configuración de DotNetOpenAuth.

Una  vez tenemos el paquete instalado, ya podemos registrar proveedores de oAuth, es decir que sitios de oAuth vamos a poder usar para registrarnos en nuestra aplicación web. Para ello usaremos la clase OAuthWebSecurity. Esta es una clase estática que es la que usaremos para todo el flujo de pseudo-autenticación de oAuth. Lo bueno es que es extremadamente simple de usar 🙂

Para registrar un proveedor de oAuth usamos el método RegisterXXXClient donde XXX es el nombre del proveedor usado. Están soportados los más importantes como Facebook, Twitter y Linkedin p.ej. Para ello añadimos el siguiente código en el Application_Start:

OAuthWebSecurity.RegisterTwitterClient(

               consumerKey: "dhkdshdhasjhdaskdhsk",

               consumerSecret: "eyuweywuieywuieywi");

Por supuesto debeís usar los valores correctos de consumerKey y consumerSecret (esos valores son proporcionados por el proveedor de oAuth, en este caso twitter).

Ahora debemos crear el flujo de autenticación de nuestra aplicación. Va a ser muy sencillo:

  1. Le mostraremos una lista de los proveedores válidos que puede usar para autenticarse (en este caso tan solo twitter).
  2. Cuando seleccione uno, empezará el flujo de oAuth: el usuario será redirigido hacia el proveedor (twitter) para que introduzca allí sus credenciales.
  3. El proveedor nos hará hará una petición a nuestra dirección de callback y en esa dirección deberemos autenticar al usuario en nuestra aplicación web.

Vamos a encapsularlo todo dentro de un controlador al que llamaremos AccountController. El primer paso es crear la vista que contenga la lista con los proveedores válidos a usar. Llamaremos Login a esta vista:

@using Microsoft.Web.WebPages.OAuth

@{

    ViewBag.Title = "Login";

}

 

<h2>Login to BeerHunters</h2>

 

 

@using (Html.BeginForm())

{

    foreach (var registerData in OAuthWebSecurity.RegisteredClientData)

    {

        <input name="provider" type="submit" value="@registerData.DisplayName" />

    }

}

Esta vista utiliza la propiedad RegisteredClientData de OAuthWebSecurity para mostrar tantos botones como clientes hayamos registrado. En este caso es un poco inútil ya que tan solo hemos registrado un proveedor (twitter) pero bueno… nos sirve para ver como tratar varios proveedores. Al final termina haciendo un post con el nombre del cliente registrado (según el botón que se pulse). Es en el método de acción que trata dicho post donde debemos lanzar el flujo de oAuth.

Para lanzar el flujo de oAuth es suficiente con llamar al método RequestAuthentication de OAuthWebSecurity. A este método le tenemos que pasar el nombre del proveedor usado:

[HttpPost]

public ActionResult Login(string provider)

{

    OAuthWebSecurity.RequestAuthentication(provider);

    return null;

}

Podemos devolver null como ActionResult porque el resultado “escapa” a ASP.NET MVC: seremos redirigidos a twitter y allí entraremos las credenciales. Cuando las haya entrado twitter me mandará de vuelta (hacia la dirección que se le especifique, que por defecto es la misma de la cual venimos), pero en la querystring me dejará datos relativos a la autenticación:

image

Si no queremos ser redirigidos a la URL de donde venimos (/Account/Login) podemos usar el método RequestAuthentication con dos parámetros, el segundo del cual es la URL a la cual seremos redirigidos:

[HttpPost]

public ActionResult Login(string provider)

{

    OAuthWebSecurity.RequestAuthentication(provider, Url.Action("ExternalLogin"));

    return null;

}

Ahora seremos redirigidos a la acción ExternalLogin una vez hayamos entrado las credenciales en twitter.

Finalmente tan sólo nos queda validar que todo ha ido bien. Para ello en la acción ExternalLogin miramos si la autenticación ha sido correcta, y si lo es autorizar al usuario en nuestra aplicación:

public ActionResult ExternalLogin()

{

    var result = OAuthWebSecurity.VerifyAuthentication();

    if (result.IsSuccessful)

    {

        FormsAuthentication.SetAuthCookie(result.UserName, false);

        return RedirectToAction("Private");

    }

    return View();

}

El método VerifyAuthentication hace su trabajo basándose en los datos que nos ha enviado el proveedor via la querystring. El objeto result contiene los datos relativos al intento de autenticación. Si en lugar del nombre del usuario queremos su ID (su id dentro de twitter en este caso) debemos usar result.ProviderUserID.

La acción “Private” es una acción privada, tan solo accesible a usuarios autenticados:

[Authorize]

public ActionResult Private()

{

    ViewBag.UserName = User.Identity.Name;

    return View();

}

Y listos! Con esto ya tenemos el usuario identificado en nuestra web a través de su cuenta de twitter. La verdad es que más simple y sencillo no podía ser 🙂

Y el combate se decidió por KO (vi)–Validaciones

Bueno… sigamos con otro post sobre esta serie en la que vamos hablando de cosas sobre knockout. Y en esta ocasión toca hablar de como validar los campos que tengamos enlazados en un formulario.

Dado que estamos moviendo toda nuestra lógica al viewmodel de cliente, es lógico asumir que las validaciones irán también en él, en lugar de estar “ancladas” al DOM como ocurre cuando usamos jQuery validate, p.ej. Si usamos knockout lo normal es tener los campos de nuestro formulario enlazados con propiedades de nuestro viewmodel.

Extendiendo observables

Lo primero que necesitamos para poder aplicar una validación en un viewmodel de knockout es poder colocar código en las propiedades del viewmodel. De esa forma podremos poner el código que queramos cuando se establezca el valor de dicha propiedad. Pues bien ello es posible, pero con una condición: que dichas propiedades sean observables. Para ello se usa la técnica de extender un observable a través del objeto ko.extenders.

Retomemos el ejemplo del post anterior y añadamos una vista de edición de cervezas. Para ello, creamos un método en el controlador de WebApi para que nos devuelva una cerveza:

public Beer GetById(int id)

{

    return beers[id];

}

Y luego creamos una vista para el controlador HomeController que llamaremos Edit. El código inicial puede ser algo como:

@model int

 

@{

    ViewBag.Title = "Edit Beer";

}

 

@section scripts

{

    <script type="text/javascript">

        $(document).ready(function() {

            var getUri = "@Url.RouteUrl("DefaultApi", new {httproute="", controller="Beers", id=Model.ToString()})";

            $.getJSON(getUri, function (data)

            {

                createViewModel(data);

            });

        });

 

        function createViewModel(jsonData)

        {

            var vm = {

                name: ko.observable(jsonData.Name),

                brewery: ko.observable(jsonData.Brewery),

                ibu: ko.observable(jsonData.Ibu)

            };

            ko.applyBindings(vm);

        }

    </script>

 

}

 

@using (Html.BeginForm())

{

    <fieldset>

        <legend>Edit Beer</legend>

        <div class="editor-label">

            <label for="name">Name:</label>

        </div>

        <div class="editor-field">

            <input type="text" id="name" data-bind="value: name"/>

        </div>

 

        <div class="editor-label">

           <label for="brewery">Brewery</label>

        </div>

        <div class="editor-field">

            <input type="text" id="brewery" data-bind="value: brewery"/>

        </div>

 

        <div class="editor-label">

            <label for="ibu">Ibu</label>

        </div>

        <div class="editor-field">

            <input type="text" id="ibu" data-bind="value: ibu"/>

        </div>

        <p>

            <input type="button" value="Save" id="cmdSave"/>

        </p>

    </fieldset>

}

La vista recibe el ID de la cerveza a editar, hace la llamada via Ajax para obtener esos datos, crea el viewmodel de knockout y muestra los campos de la UI enlazados.

Vamos a validar los IBUs. Los IBUs son una medida que indican la amargura de una cerveza. Una lager normal suele estar alrededor de los 30-35 IBUs mientras que una IPA puede alcanzar los 150. Así que vamos a meter una validación para que el valor de los IBUs sea numérico 🙂

Para ello vamos a extender el observable ibu. Para ello debemos añadir la función que extiende el observable en ko.extenders. Extender un observable significa declarar una función que se ejecutará cuando se acceda a dicho observable. Dicha función puede hacer algo y debe devolver un observable (que es el que se terminará enlazando al campo enlazado al observable inicial). Usualmente se devuelve el propio observable original, pero se puede devolver un observable calculado que use el original de cualquier manera.

Empecemos pues por declarar una función que valide si ibu es un número. Para ello añadimos al principio de la función createViewModel:

ko.extenders.numericval = function (target, params) {

    function validate(value) {

        return  value % 1 == 0;

    }

    validate(target());

    target.subscribe(validate);

 

    return target;

};

En este código hacemos cuatro cosas:

  1. Definimos y añadimos el campo numericval dentro de ko.extenders. Dicho campo es una función.
  2. Dentro de dicha función definimos otra función interna que es la que realmente comprueba si un valor es entero o no.
  3. Realizamos una primera validación (del valor inicial del observable)
  4. Suscribimos la función validate al observable. Cada vez que el observable se modifique la función validate se ejecutará.

Si ahora ejecutáramos el código veríamos que no ocurre nada. El código dentro de ko.extenders.numericval no se ejecuta nunca. La razón es que hemos definido la extensión del observable pero nos falta extender el observable en sí. Eso se consigue con el método extend. Este método recibe un objeto json con una propiedad. El nombre de la propiedad es la extensión a aplicar y el valor de la propiedad es el valor que tomará el segundo parámetro (params) de la extensión que hemos creado (el primer parámetro target es el observable que extendemos):

var vm = {

    name: ko.observable(jsonData.Name),

    brewery: ko.observable(jsonData.Brewery),

    ibu: ko.observable(jsonData.Ibu).extend({ numericval: "" })

};

Ahora sí! Hemos definido una extensión (numericval) y la hemos aplicado al observable ibu. Le pasamos “” como parámetros (que tampoco usamos para nada).

Pero esta extensión todavía NO hace nada. Es decir, si depuráis el código javascript veréis que se efectivamente cada vez que se modifica el observable ibu se ejecuta el método validate, pero este método no hace nada salvo devolver true o false.

¿Como podemos informar al usuario de que el valor es incorrecto?

Subobservables

Pues la solución a la pregunta anterior pasa por usar un “subobservable”. Un subobservable es un observable definido dentro de otro observable. Vamos pues a crear un subobservable, que llamaremos hasError. Este subobservable lo definiremos dentro del observable que extendamos, es decir dentro de target. Luego modificaremos validate() para que en lugar de devolver true o false, establezca el valor del subobservable hasError:

ko.extenders.numericval = function (target, params) {

    target.hasError = ko.observable();

    function validate(value) {

        target.hasError(!(value % 1 == 0));

    }

    validate(target());

    target.subscribe(validate);

    return target;

};

Y ya casi estamos! Ahora nos queda un punto que es… enlazar un elemento de la UI al subobservable. ¿Y como enlazamos a un subobservable? Pues del mismo modo que enlazamos a un observable normal, salvo que ahora el nombre del observable es “observable.subobservable”. Así si queremos enlazar algo al valor del subobservable hasError, deberemos usar “ibu.hasError” como nombre:

<div class="editor-field">

    <input type="text" id="ibu" data-bind="value: ibu, css: {‘input-validation-error’: ibu.hasError, ‘field-validation-error’ : ibu.hasError}"/>

</div>

Fijaos en el atributo data-bind del <input>. Ahora estoy usando dos bindings:

  1. value (que ya usábamos) para enlazar el valor
  2. css para aplicar clases css en función del valor del observable. El binding css toma un objeto json, en el cual los nombres de las propiedades son las clases que se aplicarán y el valor de dichar propiedades es un campo del viewmodel. Si vale true se aplica la clase y si vale false no. En este caso:
    1. Se aplicará input-validation-error si ibu.hasError vale true
    2. Se aplicará field-validation-error si ibu.hasError vale true

Nota: En este caso he puesto los nombres de las clases entre comillas simples porque esos nombres no son identificadores javascript válidos. Si los nombres de las clases a aplicar son identificadores javascript válidos, no es necesario entrecomillarlos.

Por supuesto podríamos añadir un mensaje de error, p.ej. en un <span> que se visualice si ibu.hasError vale true. Para ello podemos usar el binding visible que tiene knockout:

<div class="editor-field">

    <input type="text" id="ibu" data-bind="value: ibu, css: {‘input-validation-error’: ibu.hasError, ‘field-validation-error’ : ibu.hasError}"/>

    <span data-bind="visible: ibu.hasError" class="message-error">Error: Debe ser numérico</span>

</div>

¡Y listos!

Aquí tenéis el resultado:

image

Un tema que se observa si se ejecuta el código es que el observable ibu no se modifica cada vez que tecleamos, si no tan solo cuando el textbox pierde el foco. Pero como ya vimos en el post anterior, eso tiene fácil solución.  Basta con usar valueUpdate:

<input type="text" id="ibu" data-bind="value: ibu, valueUpdate: ‘afterkeydown’ ,

    css: {‘input-validation-error’: ibu.hasError, ‘field-validation-error’ : ibu.hasError}"/>

Y con eso hemos terminado. Apuntar solamente que las extensiones se “almacenan” en ko.extenders y son independientes del viewmodel (recordad que debemos “aplicarlas” usando extend). Por lo tanto podemos tener nuestras librerías de “validaciones” con knockout!

Espero que os haya resultado interesante!

Os dejo el ejemplo completo en my skydrive: https://skydrive.live.com/redir?resid=6521C259E9B1BEC6!174 (Nota el zip es KoDemoVI.zip, aunque la solución y la carpeta luego se llamen KoDemoV). Para probar la edición basta con ir a /Home/Edit/{id}, pasando el id de la cerveza.

Saludos!

[Kata]- Cambio con monedas

Muy buenas! Puro divertimento 🙂

Os propongo un kata por si quereis entrenar las neuronas. Por supuesto no es un kata original mío (soy muy malo para eso), de hecho es un kata creo que bastante famosillo, pero es uno con el que me he enfrentado no hace mucho…

El enunciado es muy simple… Crear una función que reciba dos parámetros: Un entero que represente una cantidad de dinero, y una colección que represente los tipos de monedas de los que disponemos. Dicha función debe devolver de cuantas maneras diferentes podemos repartir las mondedas para conseguir el valor total de dinero (asumiendo que tenemos infinitas monedas de cada tipo).

P.ej. si el dinero es 4 y los tipos de monedas son 1 y 2, la función debe devolver “3”, ya que hay 3  maneras de sumar 4 usando 1 y 2:

  • 1+1+1+1
  • 2+2
  • 1+1+2

Si los tipos de monedas son 5,10,20,50,100,200 y 500 y la cantidad de dinero es 300 el valor devuelto debe ser 1022. Con las mismas monedas y dinero 500 el resultado asciende a 6149. Y finalmente con las mismas monedas y la cantidad de dinero 301 el valor es 0, ya que no hay combinación alguna.

El kata es sencillo, simplemente rellenar la función:

int TiposCambio(int money, IEnumerable<int> coins)

{

}

Como “pista” diré que usando C# 3.0 puede conseguirse una respuesta de 3 líneas de código y que no requiere ninguna variable local.

Podéis ir proponiendo soluciones, sugerencias, pistas… en los comentarios! 😉

Saludos!

PD: Si ya conoces la respuesta (como digo es un kata muy conocido) deja que los demás la busquen (aunque nada te impide dar sútiles pistas en los comentarios :p)

PD 2: No, no hay premio alguno… tan solo el placer de haber solucionado el acertijo… os parece poco? 😛 😛 😛

Y el combate se decició por KO (v): Filtrando colecciones

Muy buenas! Tras un parón, volvemos a la carga con la serie que trata sobre knockoutjs. Recuerda que puedes ver todos los artículos de esta serie.

En este post vamos a ver como filtrar colecciones con knockout.

Como siempre comenzamos con una clase Beer y un controlador de WebApi que devuelva una colección de elementos Beer. La clase Beer es tal como sigue:

public class Beer

{

    public string Name { get; set; }

    public string Brewery { get; set; }

    public int Ibu { get; set; }

}

Bien, ahora vamos a realizar una vista (Home/Index) que me muestre el listado de cervezas. Para ello creamos una vista como la que sigue:

<script type=»text/javascript»>

     $(document).ready(function() {

         $.getJSON(«@Url.RouteUrl(«DefaultApi», new {httproute=«», controller=«Beers»})«, function(data) {

             CreateViewModel(data);

         });

 

     });

 

     function CreateViewModel(data) {

         var vm = { beers:data };

         window.vm = vm;

         ko.applyBindings(vm);

     }

 </script>

<table>

    <thead>

        <th>Nombre</th>

        <th>Ibus</th>

        <th>Cervecería</th>

    </thead>

    <tbody data-bind=»foreach: beers»>

        <tr>

            <td data-bind=»text: Name»></td>

            <td data-bind=»text: Ibu»></td>

            <td data-bind=»text: Brewery»></td>

        </tr>

    </tbody>

</table>

Nada nuevo hasta ahora, pero con eso ya vemos nuestra tabla de cervezas:

image

Ahora vamos a jugar un poco con esos datos en cliente usando knockout. Para ello vamos a implementar unos filtros para filtrar los datos directamente desde cliente.

Así pues, vamos a introducir un texbox donde se introducirá el nombre de la cervecería y nos filtrará los datos. El código del textbox es:

<input type=»text» data-bind=»value: brewerySelected, valueUpdate: ‘afterkeydown'» />

Aquí enlazamos la propiedad value del textbox con la propiedad “bewerySelected” del viewmodel (que deberemos crear) y además le indicamos cuando debe modificarse el valor de la propiedad del viewmodel. El valor de valueUpdate es el nombre del evento que knockout usará para modificar la propiedad del viewmodel. En este caso le indicamos ‘afterkeydown’ para que nos actualice la propiedad del viewmodel cada vez que pulsemos una tecla. Si no ponemos valueUpdate el evento usado es ‘change’ (en el caso de los textboxs se lanza cuando pierden el foco).

Ahora añadimos esta propiedad a nuestrov viewmodel:

var vm = {

    beers: data,

    brewerySelected : ko.observable(«»)

};

Es importante destacar que brewerySelected se declara como un observable. Pero ¡ojo! eso NO es para que desde el textbox pueda modificarse dicha propiedad (eso viene de serie). Necesitamos que sea un observable porque vamos a necesitar que la propia knockout sepa cuando se ha modificado dicha propiedad. La razón es que vamos a crear un observable calculado que depende de dicha propiedad y nos interesa que knockout refresque el valor del observable calculado cuando el valor de brewerySelected cambie. De ahí que necesitemos que sea un observable.

¿Y cual va a ser el valor calculado? Pues la lista de cervezas cuya cervecería empieza por el valor que haya en brewerySelected:

vm.filteredByBrewery = ko.computed(function() {

    var filter = this.brewerySelected().toLowerCase();

    if (!filter) return this.beers;

    return ko.utils.arrayFilter(this.beers, function (item) {

        return ko.utils.stringStartsWith(item.Brewery.toLowerCase(), filter);

    });

}, vm);

Fijaos que usamos ko.computed (que ya vimos) para definir el observable calculado. En este caso dicho observable es la colección de elementos cuya propiedad Brewery empieza por el valor que haya en brewerySelected. Para implementarla hacemos uso de dos métodos propios de knockout:

  1. ko.utils.arrayFilter: Filtra los elementos de un array por aquellos que cumplan el predicado que se le pasa. Dicho predicado es una función que se llama por todos elementos del array y debe devolver true o false según el elemento deba ser incluído o no.
  2. ko.utils.stringStartsWith: Devuelve si una cadena empieza por otra indicada.

Y casi listos! Tan solo nos queda hacer una pequeña modificación, que es enlazar el <tbody> a la propiedad filteredByBrewery (en lugar de a la propiedad beers):

<tbody data-bind=»foreach: filteredByBrewery»>

¡Y listos, podemos ver que a medida que vayamos escribiendo la lista se va filtrando!

imageimage

La clave es, recordad, en declarar selectedBrewery como observable. Eso hace que cuando se modifique knockout recalcule el observable calculado filteredByBrewery. Y este último al ser un observable cuando es recalculado forza una modificación de la UI.

Ahora a lo mejor alguien se está haciendo la pregunta: ¿Como sabe knockout que debe recalcular el observable calculado filterByBrewery al modificarse el observable selectedBrewery? Pues simple y llanamente porque desde el código de la función de filterByBrewery se llama a selectedBrewery. A mi personalmente que sea capaz de llegar a ese nivel me parece brutal! Si no te lo crees prueba de añadir otro observable, enlázalo a un cuadro de texto y observa que al modificar este segundo observable el observable calculado filterByBrewery no es recalculado (puedes comprobarlo poniendo un breakpoint con cualquiera de las herramientas de debug de javascript). Es decir knockout sabe de que observables depende cada observable calculado y así solo recalcularlos cuando es necesario… ¡Simplemente fantástico!

Os dejo el código fuente del proyecto en mi skydrive: https://skydrive.live.com/redir?resid=6521C259E9B1BEC6!314 (es el fichero KoDemoV.zip).

Saludos!