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.

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

  1. Buenas etomas!, muy buen articulo, estoy implementando test de conceptos investigando sobre .Net Core y se me presento un problema, no encuentro porque cuando hago una libreria dll y la referencio dentro de un proyecto WebApi de .NetCore, puedo usarla, compilar correctamente y hasta ejecutar el WebApi, ahora cuando quiero consumirlo, nunca responde, saco la referencia a la dll y su utilizacion y automaticamente el WebApi comienza a responder a las peticiones, no entiendo porque no me da algún error de referencias o algo por el estilo si el problema pasa por la dll referenciada (la dll contiene solo una clase con un metodo que devuelve “Hola Mundo”, nada raro). Te pasó alguna vez?, desde ya muchas gracias por tu tiempo y si encuentro el problema lo comentaré, hasta ahora no se porque no me responde.

    Saludos desde argentina!

    1. No.
      Si la WebApi no te responde, lo probable es que estés recibiendo un 500.
      Deberías mirar por qué…
      Poco más puedo decirte 🙁

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *