[Evento]–Hel10 Windows

Buenas! Ayer (22 octubre 2015) se celebró el “Hel10 Windows” un evento organizado por Microsoft en Madrid para hablar de las muchas novedades que incorpora Windows 10 y todo el ecosistema nuevo de la plataforma universal.

Antes que nada mi opinión general del evento: Estuvo basante bien. Una keynote un poco sosilla para mi gusto, a pesar de que algunas de las novedades presentadas eran bastante interesantes. Pero, por un lado vivimos en la época de la información globalizada y quien más quien menos ya había oído hablar de continuum y el resto de novedades, y por otro no tenemos el sentido del espectáculo de los americanos (por suerte o por desgracia según cada cual).

Después de la keynote empezaron cuatro tracks, los nombres oficiales de los cuales están el la página del evento, pero que básicamente eran:

  1. Desarrollo de aplicaciones universales y la UWP. Este track es el que se ha retransmitido via channel 9.
  2. Cosas raras de desarrollo. En este track estuve yo hablando sobre WinObjC.
  3. IoT y cacharritos
  4. Sistemas

Como digo yo estuve hablando de WinObjC o lo que es lo mismo “project Islandwood” o “Bridge for iOS” que es el nombre oficial. Se trata de un conjunto de herramientas que permitirá portar nuestras aplicaciones iOS en Objective-C a Windows10 como aplicación universal. Manteniendo la funcionalidad pero adaptando un poco el aspecto al aspecto de las aplicaciones universales.

Durante la charla tuve malditos problemas técnicos con Parallels que básicamente me impidió ejecutar las demos. Mucha rabia porque había usado Parallels (de hecho lo uso constantemente) sin problemas, pero no se si fue que el proyector estaba en una resolución no soportada por mi Mac o qué, pero el resultado es que el ratón en Parallels iba donde le daba la gana y era imposible darle click a nada… En fin, que le vamos a hacer. Me limité a mostrar el código en XCode y como usar compilación condicional para reemplazar aquellas partes que el bridge no soporta con llamadas a la API nativa de Windows 10.

En la charla intenté explicar un poco lo que hay hecho, pero sin engañar a nadie: el proyecto está muy verde, y es más la promesa de lo que va a ser que lo que es en la actualidad. El soporte para ficheros.xib, storyboards y layout constraints es casi obligatorio, porque sin esas tres características casi no se va a poder migrar aplicación alguna (excepto juegos). Lo que hay hecho, a pesar de ser una preview que, en mi opinión, no llega ni a alfa, pinta interesante, pero se tiene que ver como evoluciona.

He dejado la presentación de la charla en slideshare: http://www.slideshare.net/eduardtomas/winobjc-windows-bridge-for-ios

Y si te animas a probar las demos, las he subido todas a un repo de github para que puedas jugar con ellas: https://github.com/eiximenis/WinObjC-Samples

Saludos!

¿Qué hace ‘new’ en JavaScript?

Si preguntas a mucha gente cual es el objetivo de new en JavaScript te dirán que el de crear objetos. Y estarán en lo cierto, aunque esa definición no es del todo precisa. Y es que mucha gente no entiende exactamente que hace new así que vamos a dedicarle este post.

Creación de objetos sin new

La verdad es que new no es necesario en JavaScript. Se pueden crear objetos perfectamente sin necesidad de usar new:

  1. var foo = {
  2.     name: 'foo',
  3.     getUpperName: function () {
  4.         return this.name.toUpperCase();
  5.     }
  6. }

Esta manera de crear objetos la conocemos como object notation y nos permite definir objetos con campos y métodos. Por supuesto, en este caso solo creamos un objeto pero basta con declarar una función que tenga ese código para crear tantos objetos como queramos:

  1. var Foo = function (name) {
  2.     var foo = {
  3.         name: name || '',
  4.         getUpperName: function () {
  5.             return this.name.toUpperCase();
  6.         }
  7.     }
  8.  
  9.     return foo;
  10. }
  11.  
  12. var f2 = Foo("f2");
  13. f2.getUpperName();  // devuelve F2

Nos podemos preguntar cual es el prototipo de cada objeto creado mediante una llamada a Foo. Pues, como es de esperar, el prototipo de f2 será Object.prototype.

Podríamos indicar que los objetos creados por Foo heredan de Foo.prototype, con un código similar al:

  1. var Foo = function (name) {
  2.     var foo = {
  3.         name: name || '',
  4.         getUpperName: function () {
  5.             return this.name.toUpperCase();
  6.         }
  7.     }
  8.     Object.setPrototypeOf(foo, Foo.prototype);
  9.     return foo;
  10. }
  11.  
  12. var f2 = Foo("f2");
  13. f2.getUpperName();  // devuelve F2
  14. f2 instanceof Foo; // devuelve true

Lo interesante es que establecer como prototipo del objeto creado el objeto Foo.prototype, automáticamente hace que instanceof Foo devuelva true sobre todos los objetos creados por la función Foo. Vale, estoy usando Object.setPrototypeOf que es una función nueva de ES2015, pero en ES5 clásico tenemos Object.create que nos permite hacer lo mismo:

  1. var Foo = function (name) {
  2.     var foo = Object.create(Foo.prototype);
  3.     foo.name = name || '';
  4.     foo.getUpperName = function () {
  5.         return this.name.toUpperCase();
  6.     }
  7.     return foo;
  8. }
  9.  
  10. var f2 = Foo("f2");
  11. f2.getUpperName();  // devuelve F2
  12. f2 instanceof Foo; // devuelve true

¿Entonces… qué hace new?

Bueno, new se introdujo para dar una “sintaxis familiar” a los desarrolladores que venían de Java, pero básicamente hace lo mismo que hemos hecho nosotros. En JavaScript hablamos de funciones constructoras, pero no hay sintaxis para declarar una función constructora. Una función constructora es aquella pensada para ser llamada con new, pero que quede claro: es usar o no new al invocar una función lo que convierte a esa en constructora.

Cuando usamos new en una función, llamémosla Bar, ocurre lo siguiente:

  1. Se crea automáticamente un objeto vacío que hereda de Bar.prototype
  2. Se llama a la función Bar, con el valor de this enlazado al objeto creado en el punto anterior
  3. Si (y solo sí) la función Bar devuelve undefined, new devuelve el valor de this dentro de Bar (es decir, el objeto creado en el punto 1).

Como, gracias al punto 2, dentro de una función llamada con new el valor de this es el objeto creado en el punto 1, decimos que en una función constructora el valor de this es “el objeto que se está creando”. Y es por ello que las codificamos de esa manera:

  1. var Foo = function (name) {    
  2.     this.name = name || '';
  3.     this.getUpperName = function () {
  4.         return this.name.toUpperCase();
  5.     }
  6. }

Pero para que veas exactamente hasta que punto new no era “imprescindible” es porque incluso podríamos hacer una especie de polyfill para new:

  1. var functionToCtor = function (ctor) {
  2.     var o = Object.create(ctor.prototype);
  3.     var args = Array.prototype.slice.call(arguments)
  4.     args.splice(0, 1);
  5.     var v = ctor.apply(o, args);
  6.     return v === undefined ? o : v;
  7. }

La función functionToCtor hace lo mismo que new. Es decir, en este caso dada la función constructora Foo ambas expresiones son equivalentes:

  1. var foo = functionToCtor(Foo, "foo");
  2. var foo2 = new Foo("foo2");

Tanto foo como foo2:

  • Tienen como prototipo Foo.prototype
  • Tienen como constructor la función Foo
  • Devuelven true a la expresión instanceof Foo

¿Y si una función constructora devuelve un valor?

Esa es buena… Pues en este caso cuando se use new el valor obtenido será el devuelto por la función constructora (siempre que este valor sea distinto de undefined):

  1. var Foo = function (name) {    
  2.     this.name = name || '';
  3.     this.getUpperName = function () {
  4.         return this.name.toUpperCase();
  5.     }
  6.  
  7.     return { a: 10 };
  8. }
  9.  
  10. var f = new Foo();
  11. f.a;        //  10
  12. f instanceof Foo // false

Si… a pesar de que f ha sido creado usando new Foo, el prototipo de f ya no es Foo.prototype, ya que f vale el objeto devuelto por la función Foo. En este caso el objeto “original” cuyo prototipo es Foo.prototype y al que nos referíamos con this dentro de Foo se ha perdido. Lo mismo ocurre si usas el “polyfill” functionToCtor que hemos visto antes.

Funciones duales

Podemos hacer una función que sepa si se ha invocado con new o no? Pues sí:

  1. var Foo = function (name) {
  2.     if (this instanceof Foo) {
  3.         // Invocada con new
  4.     }
  5.     else {
  6.         // Invocada sin new
  7.     }
  8. }

Esto nos permite trabajar con this en el caso de que se haya usado new o bien no trabajar con this y devolver un valor en el caso de que no se haya invocado a la función con this. De todos modos si quieres que el usuario obtenga el mismo valor use new o no, lo más fácil es devolver el valor desde la función constructora. En este caso, eso sí, pierdes el hecho de que el prototipo del objeto sea la función constructora. Si quieres asegurarte que el usuario obtiene siempre un objeto con el prototipo asociado a la función constructora, es decir como si siempre usase new, puedes hacer:

  1. var Foo = function (name) {
  2.     var _create = function (name) {
  3.         this.name = name || '';
  4.         this.getUpperName = function () {
  5.             return this.name.toLocaleUpperCase();
  6.         }
  7.     }
  8.  
  9.     if (this instanceof Foo) {
  10.         _create.bind(this)(name);
  11.     }
  12.     else {
  13.         var o = Object.create(Foo.prototype);
  14.         _create.bind(o)(name);
  15.         return o;
  16.     }
  17. }

La función _create es la que realmente rellena el objeto (le llega ya creado en la variable this). La función Foo lo único que hace es mirar si ha sido llamada con new o no. En el primer caso llama a _create pero vinculando el valor de this dentro de _create al propio valor de this dentro de Foo (que en este caso es el objeto que se está creando) y no devolver nada. En el caso que el usuario no haya usado new la función Foo crea un objeto vacío, le asigna Foo.prototype como prototipo y luego llama a _create vinculando el valor de this dentro de _create al del objeto que acaba de crear. Y finalmente, en este caso, devuelve el objeto creado.

Así, tanto si el usuario hace var x = Foo() como var x2 = new Foo() obtiene lo mismo: un objeto cuyo prototipo es Foo.prototype y que por lo tanto devuelve true a instanceof Foo.

Espero que este post os haya ayudado a entender como funciona new en JavaScript.

Saludos!

Algunas consideraciones de seguridad sobre OAuth

Cuando hablo de OAuth y del acceso con tokens, ya sea en formaciones o en charlas más o menos coloquiales, muchas veces surgen dudas sobre cuan seguros son los tokens. En este post, sin pretender dar un repaso exhaustivo a todos los flujos OAuth existentes, si que me gustaría comentar algunas consideraciones básicas de seguridad.

En el principio estaba OAuth 1.0

La versión 1.0 de OAuth especifica, básicamente, un solo token, conocido como oauth_token. Dicho token es el que, enviado junto a una petición, permite validar que la petición es enviada un cliente en concreto. Dejando de lado como obtenemos dicho token (los distintos flujos OAuth) el resultado final es que el cliente debe mandar lo siguiente en cada petición:

  1. El oauth_consumer_key: El ID (público) de cliente. Dicho ID identifica a la aplicación cliente, aunque no a un usuario determinado. Es decir, identifica a la aplicación cliente, no al usuario.
  2. El oauth_token que identifica a un usuario en concreto. El oauth_token conjuntamente al oauth_consumer_key identifican un usuario concreto de una aplicación.

Visto así, parece que si alguien interceptase una petición concreta, podría ver tanto el oauth_consumer_key como el oauth_token y de esa manera impersonar al usuario en concreto. Para protegernos de eso, lo más sencillo es usar un canal seguro (es decir https) pero OAuth 1.0 incorpora un mecanismo para securizar nuestros tokens incluso en canales no seguros: la firma de peticiones.

Cada petición OAuth debe ir firmada digitalmente, y esa firma digital se realiza utilizando otro token (oauth_token_secret), dicho token es conocido es conocido solo por el cliente y el servidor y no es enviado nunca por el cliente (el cliente lo recibe junto su token oauth cuando realiza el flujo correspondiente). De esta manera si alguien intercepta una petición y obtiene tanto el oauth_consumer_key como el oauth_token no podrá generar nuevas peticiones válidas, ya que no podrá firmarlas. Por supuesto podría reenviar la petición tantas veces como quisiera (lo que podría tener consecuencias fatales), pero nunca podría enviar una petición modificada o con otros datos.

Para evitar que alguien pueda reenviar una petición se establece un nuevo mecanismo de seguridad en OAuth: Cada petición incluye un nonce (acrónimo de “number once”) que es un identificador “único” de petición. El formato del nonce queda a elección del servidor (puede ser un guid, puede ser un timestamp en formato Unix, o cualquier otra cosa). La idea es que el servidor no aceptará dos peticiones del mismo cliente con el mismo nonce (en cierto intervalo de tiempo a definir por el servidor). Además, las peticiones OAuth llevan un timestamp que indica cuando el cliente las emite (en un tiempo que debe estar sincronizado con el del servidor, por lo que se suele usar UTC). El servidor valida dicho timestamp y si no coincide con el de la hora del servidor (dentro de cierto margen de tolerancia) la petición es rechazada. De este modo basta con que los nonce no se puedan repetir en todo el periodo de tolerancia del timestamp. Debe notarse que tanto el nonce como el timestamp forman parte de la petición, por lo que son firmados digitalmente (y por lo tanto no pueden alterarse).

Creedme si os digo por experiencia que la parte más dura de crear un cliente (o un servidor) OAuth es la creación y/o validación de las firmas digitales. Eso incluye crear lo que la especificación llama una “forma canónica de la petición” que no es trivial. La gran mayoría de errores de implementación de clientes o servidores OAuth vienen por ahí.

A cambio tenemos una cierta garantía de que incluso en canales no seguros, si alguien intercepta una petición no podrá usar los tokens para generar nuevas peticiones y impersonar al usuario. Las únicas peticiones en OAuth 1 que debemos mandar bajo https sí o sí son las que nos permiten obtener los tokens iniciales… Aunque mi recomendación sería usar siempre https por supuesto.

OAuth 2 y los bearer tokens

OAuth 2 cambió las normas del juego: dado que la generación y validación de la firma digital son complejos, en OAuth 2 se elimina la firma digital, lo que deja los tokens en una situación bastante más comprometida.

De hecho si en OAuth 1 era bastante natural que un oauth_token tuviese una validez muy larga (o incluso que no caducase) en OAuth 2 eso sería como pegarse un tiro: Una vez el cliente obtiene un token oauth (al igual que en OAuth 1.0 existen varios flujos para hacerlo) dicho token realmente impersona al usuario. Es decir, si alguien intercepta el token, es a todas luces, como si tuviese las credenciales del usuario… durante el tiempo de validez del token. A ese tipo de tokens los conocemos como bearer tokens.

Insisto para dejarlo claro: si una petición incluye el bearer token dicha petición se considerada autenticada y además impersona a un usuario en concreto. Por lo tanto cualquiera que intercepte una petición que incluya el bearer token tiene abiertas las puertas de par en par.

Para minimizar daños se hace que los bearer tokens tengan una duración corta (lo de corta depende de cada uno), de forma que a pesar de tener un bearer token uno puede, al cabo de cierto tiempo, recibir un 401 lo que indica que el token ha caducado. En este caso existe un flujo OAuth 2 que permite “renovar” el token. Renovar el token incluye enviar otro token específico (el refresh token). Dicho token se obtiene junto al token de acceso y sirve solo para esto: para refrescar el token de acceso cuando ha caducado. Dado que el refresh token no viaja en cada petición, alguien que haya obtenido un token oauth, no podrá renovarlo.

Por supuesto si este alguien que está escuchando intercepta una petición de “refresco de token” entonces si que la situación se vuelve complicada de verdad: a pesar de que los refresh tokens pueden caducar la verdad es que su tiempo de vida suele ser muy largo y aunque se pueden revocar esto solo consigue “cerrar las puertas” una vez alguien ya ha podido hacer daño.

En resumen OAuth 2 con los bearer tokens toma una filosofía muy clara: que el canal de comunicaciones es seguro. O dicho de otro modo: no puede usarse OAuth 2 con bearer tokens si no se usa un canal seguro (https). Y no me refiero solo a las peticiones que obtienen los tokens, si no a todas. Todas las peticiones OAuth 2 con bearer tokens deben enviarse bajo https. Si no, la seguridad queda totalmente comprometida.

MAC Tokens

Para ser justos con OAuth 2, no obliga a usar bearer tokens (a pesar de que esos sean los más usados). OAuth 2 soporta también otro tipo de tokens, conocidos como tokens MAC (Message Authentication Code). En este caso OAuth 2 se comporta de forma parecida a OAuth 1: cuando el cliente obtiene el token, obtiene también otro token adicional que le sirve para firmar las peticiones. En este caso, al igual que en OAuth 1, se usan los parámetros nonce y timestamp de la petición para evitar que alguien pudiese reenviar peticiones. Al igual que en OAuth 1 se soportan varios algoritmos de firma digital (aunque HMAC SHA256 suele ser el más usado).

Si usamos tokens MAC el requisito de canal seguro desaparece, excepto, por supuesto, en las peticiones que permiten obtener los tokens.

Os dejo algunos enlaces con más información al respecto:

Espero que si teníais alguna duda al respecto esto os ayude un poco 🙂

La dualidad objeto-función en JavaScript

No sé si Brendan Eich es un amante de la física cuántica, pero al menos viendo algunas de las características, así lo parece. No solo tenemos el principio de incertidumbre de this si no que también tenemos el hecho de que en JavaScript un objeto puede comportarse como una función y viceversa, es decir una dualidad objeto-función.

Tomemos jQuery p. ej. Por defecto nos define el archiconocido $, con el cual podemos hacer algo como $(“#mydiv”), es decir, usarlo como una función, pero también podemos hacer $.getJSON(“…”), es decir, usarlo como un objeto. A ver como podemos conseguir esa dualidad es a lo que vamos a dedicar este post 🙂

La dualidad ya existente

La verdad… es que JavaScript ya viene con esa dualidad de serie… Todas las funciones de JavaScript se comportan a su vez como objetos (de hecho, en JavaScript las funciones son un tipo específico de objeto). O si no, observa el siguiente código:

  1. var f = function () {
  2.     console.log("i am a function, or an object?");
  3. }
  4.  
  5. console.log(typeof (f));
  6. console.log(f.toString());

El primer console.log, imprime “function”, dejando bien claro que f es una función. Pero luego observa que se está llamando al método toString de la función f. De la función en sí, no del valor devuelto por dicha función (lo que, ya puestos, generaría un error, pues f devuelve undefined). Así pues, las funciones tienen propiedades y métodos. Puede parecer chocante, pero en JavaScript los funciones, son también, objetos.

En JavaScript cada objeto tiene asociado su prototipo que es otro objeto (y dado que el prototipo es un objeto tiene asociado su propio prototipo, lo que genera una cadena de prototipos, que termina en un objeto llamado Object.prototype y que su prototipo es null).

Existe una propiedad, llamada __proto__, que nos permite acceder al prototipo de un objeto en concreto. Cuando creamos un objeto, usando object notation dicha propiedad se asigna a Object.prototype (como puedes comprobar en esa captura de pantalla de las herramientas de desarrollador de Chrome):

image

Las funciones, como objeto que son, tienen todas su propio prototipo que es… Function.prototype, que es por cierto el objeto que define las funciones call, apply y bind, que podemos llamar sobre cualquier función.

image

(Por si lo estás suponiendo, sí: el prototipo de Function.prototype es Object.prototype).

Entender bien la cadena de prototipado es fundamental, pues en ella se basa todo el sistema de herencia de JavaScript.

Ahora que ya vemos que las funciones en realidad son objetos, vamos a ver como podemos hacer como hace jQuery y colocar métodos propios en una función que definamos.

No nos sirve agregar métodos a Function.prototype: si lo hacemos esos métodos van a estar disponibles para todas las funciones y nosotros queremos que dichos métodos estén disponibles solo para una función en concreta (al igual que hace jQuery, que agrega métodos específicos pero solo a la función $).

Creando nuestra propia dualidad

Por extraño que parezca crear nuestra propia dualidad es muy sencillo, basta con el siguiente código:

  1. var f = function (name) {
  2.     return "Hello " + name;
  3. }
  4. f.foo = function () {
  5.     return "foo Utility method";
  6. }

Una vez tenemos esto podemos invocar a la función f, pero también a la función foo de la función f:

  1. var x = f("edu");
  2. var x2 = f.foo();

Ya tenemos a nuestra variable f, comportándose dualmente como una función y un objeto a la vez.

Por supuesto podemos refinar un poco esa técnica:

  1. var f = function (name) {
  2.     return "Hello " + name;
  3. }
  4. var fn = {
  5.     foo: function () {
  6.         console.log("Utility method");
  7.     }
  8. }
  9. Object.assign(f, fn);

Este código es equivalente al anterior, pero usa Object.assign (método de ES6) para copiar las propiedades contenidas en fn (el método foo) dentro del objeto (función) f.

Usando ES6 es muy fácil crearnos una función factoría que nos permita establecer un objeto con un conjunto de operaciones comunes a una función. Para ello podemos establecer este objeto como prototipo de la función (a su vez este objeto prototipo de la función debe “heredar” de Function.prototype para no perder las funciones que este provee).

  1. var factory = function (p, f) {
  2.     var fp = Object.create(Function.prototype);
  3.     Object.assign(fp, p);
  4.     Object.setPrototypeOf(f, fp);
  5.     return f;
  6. }

De este modo si tenemos un objeto cualquiera y queremos que todas sus operaciones sean heredadas por una función:

  1. var f = function () { return this; };
  2. factory({
  3.     dump: function () {
  4.         console.log('dump…');
  5.     }
  6. }, f);
  7. f.dump();

Ahora, la función f, además de los métodos definidos en Function.prototype (tales como apply o call) tiene también todos los métodos definidos en el objeto pasado como primer parámetro de factory, es decir el método dump.

Fácil y sencillo, ¿no?

Por cierto, ya puestos a divertirnos un poco. Cual es la salida del siguiente código si lo ejecutas en la consola JS del navegador?

  1. var f = function () { return this; };
  2. var obj = {
  3.     foo: f
  4. };
  5. factory({
  6.     unbind: function () {
  7.         return this.bind(this);
  8.     }
  9. }, f);
  10. console.log("f()", f());
  11. console.log("f.bind({a:10})()", f.bind({ a: 10 })());
  12. console.log("f.unbind()()", f.unbind()());
  13. console.log("obj.foo()", obj.foo());
  14. console.log("obj.foo.unbind()()", obj.foo.unbind()());

Piénsalo un poco con calma… si aciertas los valores de los 5 console.log eres de los que dominan el principio de incertidumbre de this 😉

Saludos!

Class library Packages (AKA ASP.NET5 Class Library) y Class Libraries “normales”

Una de las novedades de ASP.NET5 es la posibilidad de crear un proyecto de tipo Class Library. Este tipo de proyecto crea una librería de clases pero que utiliza el runtime de ASP.NET5 (DNX). En VS2015 se encuentran bajo el apartado de Web, aunque no tengan que ser usados necesariamente para proyectos web:

image

Teóricamente la salida de este tipo de proyectos no es una DLL, si no un paquete de NuGet. Vamos ahora a suponer el escenario que creamos una WebApi usando ASP.NET5 y tenemos un controlador como el siguiente (el código es lo de menos):

 

  1. [Route("api/[controller]")]
  2. public class BeersController : Controller
  3. {
  4.     // GET: api/values
  5.     [HttpGet]
  6.     public async Task<IActionResult> Get()
  7.     {
  8.         IEnumerable<Beer> beers = new[] {
  9.             new Beer {
  10.                 Id = 1,
  11.                 Name = "Estrella Damm"
  12.             },
  13.             new Beer {
  14.                 Id = 2,
  15.                 Name = "Moritz Epidor"
  16.             }
  17.         };
  18.         return new ObjectResult(beers);
  19.     }
  20. }

La clase Beer la tenemos definida en un proyecto Class Library (Package) llamado WebApi.Models, de forma que hemos agregado una referencia desde el proyecto WebApi hacia la Class Library. Eso lo podemos hacer directamente con VS2015 (de la forma “tradicional” usando Add Reference), lo que por debajo lo que hace es modificar el project.json, concretamente la sección “dependencies”:

  1. "dependencies": {
  2.   "Microsoft.AspNet.Mvc": "6.0.0-beta7",
  3.   "Microsoft.AspNet.Server.IIS": "1.0.0-beta7",
  4.   "Microsoft.AspNet.Server.WebListener": "1.0.0-beta7",
  5.   "Microsoft.AspNet.StaticFiles": "1.0.0-beta7",
  6.   "WebApi.Models": "1.0.0-*"
  7. },

Ahora, vamos a suponer que queremos crear una librería .NET para usar de cliente de nuestra WebApi en proyectos de escritorio. Y queremos reaprovechar las clases que están en WebApi.Models. El primer paso es crear una Class Library tradicional. Para ello elegimos .NET Framework 4.5 y creamos un proyecto de tipo Class Library. Llamémosle WebApi.Client.

Ahora si queremos reaprovechar las clases existentes en WebApi.Models para usarlas en esta librería, podemos intentar agregar una referencia desde la class library tradicional (WebApi.Client) hacia la librería WebApi.Models. Y cuando lo intentamos es cuando nos encontramos con un error:

image

Parece ser que no se puede agregar una referencia a un proyecto ASP.NET5 desde un proyecto .NET tradicional. Veamos como podemos conseguirlo.

Una manera es indicarle al proyecto ASP.NET5 que genere su salida. La idea es que esos proyectos ya no generan DLL tradicionales si no paquetes de NuGet (de ahí su nombre, precisamente). Por defecto esos paquetes no se generan, porque DNX no los requiere obligatoriamente en ejecución, pero si nos vamos a sus propiedades, pestaña build, podemos marcar la checkbox “Produce outputs on build”:

image

Ahora cuando compilemos WebApi.Models nos dejará el paquete de NuGet dentro de la carpeta artifacts/bin que cuelga de la carpeta de la solución. Allí nos encontraremos los paquetes de NuGet:

image

Si vas dentro de la carpeta dnxcore50 o dnx451 hay la DLL. Así, cuando hagas Add Reference, en lugar de irte a “Projects” y agregar una referencia de tipo “Project” (lo que termina con el error que hemos visto antes), le das a browse, navegas hacia la carpeta dnxcore50 y agregas una referencia a la DLL WebApi.Models.dll. Y con esto la referencia te aparecerá en la librería y podrás usar los tipos definidos en WebApi.Models:

image

Pero existe otra manera de obtener esa referencia y es aprovecharnos de que los proyectos ASP.NET5 generan paquetes de NuGet. Para ello primero necesitamos un “servidor local de NuGet” que es, básicamente, una carpeta. En mi caso se llama C:ufonuget. Es una carpeta normal y corriente, no tiene nada especial.

Ahora debes dar de alta esta carpeta como servidor de NuGet. Esto se hace a través de un fichero llamado NuGet.config que está en la raíz de la solución. Lo más fácil es que VS2015 modifique este fichero, yendo a Tools –> Options –> NuGet Package Manager –> Package Sources y agregar dicha carpeta como “package source”:

image

Esto automáticamente modifica el fichero NuGet.config a nivel de la solución:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <configuration>
  3.   <packageSources>
  4.     <!–To inherit the global NuGet package sources remove the <clear/> line below –>
  5.     <clear />
  6.     <add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" />
  7.     <add key="nuget.org" value="https://www.nuget.org/api/v2/" />
  8.     <add key="ufonuget" value="c:\ufonuget" />
  9.   </packageSources>
  10. </configuration>

Ahora debemos publicar el proyecto ASP.NET5 en el package source “ufonuget”. Para ello vamos a basarnos en las herramientas de línea de comandos de DNX. Abre una línea de comandos y vete a la carpeta raíz del proyecto WebApi.Models (la que contiene el fichero project.json). El primer punto es indicarle que se restauren todas las dependencias con “dnu restore”. Si este comando no te funciona (te dice que dnu no está reconocido) es que no tienes ningún framework DNX establecido por defecto. Ningún problema.

Si este es el caso teclea “dnvm list” y te saldran los distintos runtimes de DNX que tienes instalados:

image

El que tengas por defecto te saldrá marcado con un asterisco. En este caso no tenemos ninguno así que vamos a seleccionar el 1.0.0-beta7 para clr y x64. Para ello teclea “dnvm use 1.0.0-beta7 -arch x64 -r clr”. Esto, básicamente, agrega al path local (solo para esta línea de comandos) las herramientas del runtime de DNX que hemos elegido. Ahora sí, que ya puedes teclear “dnu restore”:

image

Ahora que ya tenemos las referencias necesarias para que se pueda compilar ese proyecto, vamos a empaquetarlo a c:ufonuget. Para ello vamos a usar el comando “dnu pack –out c:ufonuget”. Una vez haya terminado en la carpeta c:ufonuget deberíamos tener el paquete de NuGet.

Ahora volvemos a Visual Studio y usamos NuGet para agregar un proyecto a WebApi.Models a la class library WebApi.Client que hemos creado:

image

Obtenemos un error de que WebApi.Models no es compatible con .NET Framework 4.5. Eso es porque tenemos que añadir .NET4.5 como target de nuestra librería ASP.NET5. Para ello editamos el fichero project.json de WebApi.Models y añadimos “net45” dentro de la sección frameworks (dnx451 y dnxcore50 ya estaban):

  1. "frameworks": {
  2.   "dnx451": { },
  3.   "net45": { },
  4.   "dnxcore50": {
  5.     "dependencies": {
  6.       "Microsoft.CSharp": "4.0.1-beta-23225",
  7.       "System.Collections": "4.0.11-beta-23225",
  8.       "System.Linq": "4.0.1-beta-23225",
  9.       "System.Runtime": "4.0.21-beta-23225",
  10.       "System.Threading": "4.0.11-beta-23225"
  11.     }
  12.   }

Como no hay ninguna dependencia adicional para net45 no la colocamos. Ahora publicamos de nuevo el paquete nuget con “dnu pack –out c:ufonuget” y ahora si que podemos instalar el paquete NuGet:

image

¡Y eso es todo! Espero que os haya resultado interesante!

Saludos!

PD: Es posible que te preguntes que valores puede tener la sección “frameworks” además de dnx451, dnxcore50 y net45. Pues la verdad no he hecho pruebas, pero esta imagen extraída del post de Oren Novotny creo que contiene la respuesta:

Con esto (insisto que debo probarlo) se podrían atacar no solo librerías .NET si no de otras plataformas e incluso claro está PCLs.