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 🙂