Angular 2 PathLocationStrategy y Asp.Net Core Mvc

Si has hosteado una aplicación de angular 1 o angular 2 en Asp.Net Core Mvc una de las cosas con las que te habrás peleado es con la configuración del routing de cliente.

En angular 1, por defecto se utiliza el # como separador para identificar la parte de la url que define la ruta de cliente, pero en angular 2, ya no es así, y no se utiliza ningún separador (aunque se puede cambiar para que vuelva a utilizar el #).

Así, una ruta que en angular 1 podría ser http://myapp.com/#ruta/local, por defecto en angular 2 sería http://myapp.com/ruta/local.

Esto supone un problema cuando se realiza la petición al servidor, ya que como es una ruta normal (sin #), el framework intentará buscar el controlador y el método de acción pare devolver el Html generado, pero en realidad no va a existir y recibiremos un bonito 404.

Hay varias opciones para configurar el framework para que soporte routing de cliente, pero la más sencilla es usar el paquete de NuGet Microsoft.AspNetCore.SpaServices.

Entre otras cosas, nos ofrece un método de extensión sobre IRouteBuilder para registrar un controlador y método de acción que sirva de fallback para todas las rutas de cliente que no sepa encontrar.

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");

    routes.MapSpaFallbackRoute("spa-fallback", new { controller = "Home", action = "Index" });
});

En esta aplicación, la página que contiene la SPA se sirve desde el controlador HomeController y la acción Index. Así que cualquier ruta que no se corresponda con un controlador y método de acción existente, entenderemos que forma parte de la SPA. Por lo tanto, devolveremos el punto de entrada de la SPA para que angular, en este caso, pueda gestionar sin problemas la parte de la url que corresponda al routing local.

Si estás trabajando con Asp.Net Core Mvc y angular (o React, o Knockout…), te recomiendo que te pases por este repo de GitHub https://github.com/aspnet/JavaScriptServices y revises algunas joyitas interesantes que aparecen por allí.

¡Que lo disfrutes!

Asp.Net Core Mvc y las convenciones

Asp.Net Core Mvc incluye un completo sistema de convenciones con el que podemos modificar completamente el comportamiento por defecto que tiene el framework.

Concretamente tenemos las siguientes interfaces:

  • IApplicationModelConvention
  • IControllerModelConvention
  • IActionModelConvention
  • IParameterModelConvention

Todas definen un sólo método (Apply) que recibe un modelo que se corresponde al contexto  con el que estamos trabajando(aplicación, controlador, método de acción o parámetro de método de acción) .

public interface IApplicationModelConvention
{
    void Apply(ApplicationModel application);
}

Lo realmente interesante, es que ese modelo que recibimos no es de sólo lectura, sino que podemos modificar a nuestro antojo las características de los controladores, acciones y parámetros, es decir, modificar el comportamiento del framework de forma implícita al cargar nuestra aplicación.

Podemos, por ejemplo, añadir un filtro a una acción si cumple una determinada condición. Vamos a verlo con un ejemplo sencillo.

A mi me gusta tener un ActionFilter que valide el ModelState en vez de tener que repetir el código de validación en todos los métodos de acción. Algo como esto:

public class ValidateModelStateAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        if (context.ModelState.IsValid == false)
        {
            context.Result = new BadRequestObjectResult(context.ModelState);
        }
    }
}

Este filtro se ejecuta antes de que se ejecute la acción pero habiendo hecho ya el ModelBinding de la petición, por lo que ya se han hecho las validaciones del modelo y, si ha habido errores, estos están reflejados en el ModelStateDictionary. Por lo tanto, si hay errores en el ModelState, no queremos que se ejecute el método de acción, y para eso, establecemos en el filtro el resultado. En este caso, la respuesta será un BadRequest  (400) incluyendo en la respuesta la información de los campos que no cumplen las reglas de validación.

Para utilizarlo en un método de acción, símplemente decoramos el método de acción con este atributo.

[HttpPost("api/products")]
[Authorize(Policies.ManageProducts)]
[ValidateModelState]
public async Task CreateProduct([FromBody]ProductBindingModel model)
{
    ...
}

Pero si me quiero evitar ir añadiendo este atributo a todos los métodos que lo necesitan, lo que me ofrecen las convenciones, es la posibilidad de añadir este atributo de forma automática a todos los métodos que lo necesiten, que serán todos los que tengan parámetros con tipos complejos.

La verdad es que con el api que expone el modelo de la aplicación, no es una tarea complicada. Quedaría algo así:

public class AddValidateModelStateAttributeConvention : IApplicationModelConvention
{
    public void Apply(ApplicationModel application)
    {
        var actionsWithComplexTypeParameters = application.Controllers
            .SelectMany(c => c.Actions.Where(a => a.Parameters.Any(p => p.ParameterInfo.ParameterType.IsComplexType())));
 
        foreach (var action in actionsWithComplexTypeParameters)
        {
            if (action.Attributes.Any(a => a.GetType() == typeof(ValidateModelStateAttribute)) == false)
            {
                action.Filters.Add(new ValidateModelStateAttribute());
            }
        }
    }
}

En primer lugar recuperamos todos los métodos de acción que tienen parámetros de tipos complejos (clases). Sobre estos métodos de acción iteramos y, si no tienen ya aplicado el atributo, lo añadimos a su colección de filtros. Así de sencillo!

Para añadir la convención, sólo tenemos que ir al método Configure de nuestro Startup.cs y añadirlo a las convenciones que usa Mvc

services.AddMvc()
    .AddMvcOptions(options =>
    {
        options.Conventions.Add(new ValidateModelStateAttributeConvention());
    });

Problema

Desde mi prespectiva, a la definición y uso de convenciones personalizadas le veo un par de problemas que para mi son importantes.

En función del proyecto y de las convenciones que se hayan aplicado al mismo, código que va a tener el mismo comportamiento puede llegar a estar escrito de forma sensíblemente diferente. Pueden faltar atributos que se aplican por convención, no se valida el ModelState porque se hace por convención, y escenarios parecidos. Desde mi punto de vista, eso dificulta enormemente las revisiones de código en escenarios de trabajo multiproyecto y hace más dificil el revisar, de un vistazo, si nos hemos dejado algo en la implementación o no.

De la misma manera, un desarrollador acostumbrado a tener aplicadas unas convenciones en un proyecto, cuando se mueve a otro en el que no se han aplicado las mimas convenciones, es más fácil que escriba código con errores.

Llamadme antíguo, pero a mi me gusta que el código sea lo más explícito posible, no dando lugar a la interpretación. Es como el establecer el ámbito de visibilidad de clases y variables. Hay una visibilidad por defecto, pero creo que es mejor establecer siempre la visibilidad para que sea explícita y nadie se pueda equivocar al interpretarla.

Esto me ha llevado a no prestarles atención a las convencionas durante un tiempo. Hasta ahora…

¿Pero y si no sirven sólo para eso?

Pero hace poco, se me pasó por la cabeza un escenario en el que si que porían ser muy útiles las convenciones. El de los test de integración.

En vez de aplicar las convenciones de manera automática, vamos a utilizarlas para verificar que se han establecido unos atributos determinados en los métodos que los necesitan. Al final, con el modelo que exponen las convenciones ya hemos visto que este escenario sería muy sencillo.

Con esta perspectiva, en el ejemplo que hemos visto antes, mi convención debería validar que todos los métodos de acción que tienen tipos complejos como parámetros tienen aplicados este atributo, y si no lo tienen, lanzar una excepción con el nombre del controlador y del método de acción que no lo tiene.

De esta forma la nueva convención quedaría así:

public void Apply(ApplicationModel application)
{
    var actionsWithComplexTypeParameters = application.Controllers
        .SelectMany(c => c.Actions.Where(a => a.Parameters.Any(p => p.ParameterInfo.ParameterType.IsComplexType())));
    foreach (var action in actionsWithComplexTypeParameters)
    {
        if (action.Attributes.Any(a => a.GetType() == typeof(ValidateModelStateAttribute)) == false)
        {
            throw new InvalidOperationException(string.Format(
                "The action [{0}] in the controller [{1}] has a complexType parameter and has not a [ValidateModelState] attribute",
                action.ActionName,
                action.Controller.ControllerName));
        }
     }
}

Básicamente es el mismo código que hemos escrito antes, pero en vez de añadir el filtro, en este caso lanzará una excepción.

Esta nueva convención la añadiríamos sólo en el Startup.cs de nuestro proyecto de test de integración y, como parte de la validación de nuestra Api, verificaríamos que no nos hemos dejado nada importante en nuestra implementación.

La verdad es que las convenciones, aplicadas desde esta perspectiva, aportan mucho valor para validar el modelo de nuestra aplicación, permitiéndonos validar aspectos que sólo podríamos identificar de otra forma con test de integración atacando directamente al Api para validar estos escenarios.

¡Que lo disfrutéis!

Autorización en WebApi… ¿y si fuera como la de Asp.Net Core 1.0?

[Actualizado] El paquete de NuGet depende ahora de Microsoft.AspNet.Authorization (actualmente en versión 1.0.0-rc1-final) y esto implica algunos cambios. He actualizado el post para reflejarlos.

Una de las muchas novedades que nos ofrece Asp.Net Core 1.0 es el rediseño de los filtros de autenticación. Se deja atrás el concepto de autorización por roles o usuarios y se introduce un nuevo concepto de autorización por políticas. Cada una de estas políticas define que elementos quiere tener en cuenta para autorizar al usuario. Puede ser la presencia de un determinado claim, que un claim tenga uno o varios valores específicos, o incluso que el nombre del usuario o el rol tengan unos valores determinados (no olvidemos que los roles o el nombre del usuario siguen siendo claims ). Además se introduce también el concepto de un servicio de autorización (IAuthorizationService) que podremos inyectar en nuestros controladores para validar si un usuario está autorizado o no a realizar una acción, no sólo teniendo en cuenta las características del usuario, sino el propio estado del recurso al que se quiere acceder.

Estas políticas las definiremos de esta forma:

// Add Authorization policies
services.AddAuthorization(options =>
{
    options.AddPolicy("MiPolitica", policy =>
    {
        policy.RequireAuthenticatedUser();
        policy.RequireClaim("department", "sales");
    });
    options.AddPolicy("Mayor18", policy =>
    {
        policy.Requirements.Add(new MinimumAgeRequirement(18));
    });
});

En Asp.Net Core 1.0, esta configuración se hace en la clase Startup, dentro del método ConfigureServices. Como seguramente ya sabrás, este método lo que hace es configurar y registrar una serie de clases para que estén disponibles para el mecanismo integrado de inyección de dependencias, y puedan ser utilizadas por la propia infraestructura e incluso por el propio desarrollador.

Una vez definidas las políticas, se define con el atributo Authorize la política que se quiere aplicar a nivel de controlador o acción. De hecho, se ha creado una sobrecarga en el constructor de este conocido atributo para poder definir el nombre de la política que se va a utilizar para validar la autorización.

[Authorize("MiPolitica")]

La verdad es que toda esta nueva infraestructura nos permite abordar escenarios realmente complejos que en las versiones actuales de WebApi y Mvc exigirían mucho código personalizado.

¿Lo puedo utilizar en WebApi hoy?

Pero toda esta infraestructura no está disponible en los proyectos de WebApi en los que estamos trabajando hoy. Tenemos que seguir utilizando el atributo Authorize de toda la vida en el que sólo podemos especificar los roles o los usuarios que están autorizados.

¿O no?

Gracias al paquete de NuGet Acheve.Web.Http.Authorization podemos tener a nuestra disposición en los proyectos de WebApi toda la potencia de la autorización basada en políticas que nos ofrece Asp.Net Core 1.0.

Sólo hay que tener en cuenta una cosa importante, y es que, por defecto, WebApi no nos proporciona un mecanismo de inyección de dependencias integrado en el framework, y, por lo tanto, para que funcione todo esto estamos obligados a configurar nuestro contenedor de inyección de dependencias preferido con WebApi y a registrar en el los tipos que hacen posible que todo esto funcione.

Configurar un contenedor de inyección de dependencias externo en WebApi es sencillo. Sólo tenemos que asignar el Adapter para nuestro contenedor a la propiedad DependencyResolver de la configuración de WebApi.

Por ejemplo con Autofac, la configuración sería algo parecida a esto:

public class Startup
{
  public void Configuration(IAppBuilder app)
  {
    var builder = new ContainerBuilder();

    // STANDARD WEB API SETUP:

    // Get your HttpConfiguration. In OWIN, you'll create one
    // rather than using GlobalConfiguration.
    var config = new HttpConfiguration();

    // Register your Web API controllers.
    builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

    // Run other optional steps, like registering filters,
    // per-controller-type services, etc., then set the dependency resolver
    // to be Autofac.
    var container = builder.Build();
    config.DependencyResolver = new AutofacWebApiDependencyResolver(container);

    // OWIN WEB API SETUP:

    // Register the Autofac middleware FIRST, then the Autofac Web API middleware,
    // and finally the standard Web API middleware.
    app.UseAutofacMiddleware(container);
    app.UseAutofacWebApi(config);
    app.UseWebApi(config);
  }
}

A partir de este momento, nuestros controladores pueden definir dependencias en el constructor que serán resueltas por el contenedor.

Si instalamos el paquete de NuGet Acheve.Web.Http.Authorization.Autofac, podremos utilizar un método de extensión sobre el ContainerBuilder de Autofac que nos permitirá registrar nuestras políticas exactamente de la misma manera que en Asp.Net Core 1.0.

builder.UsePolicyAuthorization(options =>
{
    options.AddPolicy(Policies.Sales, policy =>
    {
        policy.RequireAuthenticatedUser();
        policy.RequireClaim("department", "sales");
    });
    options.AddPolicy(Policies.Over18Years, policy =>
    {
        policy.Requirements.Add(new MinimumAgeRequirement(18));   
    });
});

[Actualizado]
A partir de este momento, podremos usar los atributos definidos en el ensamblado Microsoft.Asp.Net.Authorization (este ya es Asp.Net Core!) para definir las políticas de autorización de nuestros controladores y métodos de acción. De hecho, el atributo se llama igual que el definido por WebApi, por lo que tendremos que utilizarlo definiendo el nombre completo del tipo.

    [Microsoft.AspNet.Authorization.Authorize]
    [RoutePrefix("products")]
    public class ProductsController : ApiController

Pero todavía nos falta una cosa. El nuevo modelo de Asp.Net Core permite que estos atributos no sean atributos de autorización del framework (lo que por otra parte nos permite reutilizarlos en una plataforma diferente). Así que si no hacemos nada más, realmente WebApi no sabría qué hacer con ellos. Para solucionarlo, configuraremos un filtro global en la configuración de WebApi que será el que se encargue de descubrir estos atributos e integrarlos en la autorización de WebApi.

config.Filters.Add(new UseAspNetCoreAuthorizationModelAttribute());

[Final actualizado]

Voy a ir escribiendo una serie de posts sobre el uso de toda esta nueva infraestructura de autorización para descubrir toda la potencia que nos ofrece. Pero lo más importante es que todo lo que veamos, lo vamos a poder utilizar tanto en WebApi 2 como en Asp.Net Core 1.0.

El código fuente de los paquetes de NuGet está aquí: https://github.com/hbiarge/Acheve.Web.Http.Authorization e incluye ejemplos de uso de este mecanismo de autorización en un proyecto de WebApi 2.

WebApi: Tests de integración con diferentes identidades

tldr;
Acabo de publicar un pequeño paquete de NuGet para facilitar los test de integración de WebApi cuando incluyen peticiones autenticadas y autorización por claims.
Lo puedes encontrar aqui: Acheve.Owin.Testing.Security
Y el código fuente aquí: Github

 

En general, no me gusta hacer test unitarios de mis controladores de WebApi. Me da la sensación que me aportan muy poco valor. Hay que mockear un montón de infraestructura, haciendo que los tests sean farragosos de configurar (por muchos métodos de extensión que creemos para facilitarnos el trabajo).

Una de las soluciones que más me gusta en estos escenarios es la de hacer test de integración del api. Juanma (aka @gulnor) lo comentaba por aquí (post de lectura muy recomendada) hace un tiempo, y yo no puedo estar más de acuerdo con esta visión.

“La complejidad reside en la configuración de los componentes”

El componente que suelo utilizar para estos test de integración es el paquete de NuGet Microsoft.Owin.Testing. Básicamente me ofrece un host basado en Owin para el api. Muy sencillo de configurar con su clase Startup y muy rápido de ejecutar.

Pero el problema es cuando el api, no sólo requiere peticiones autenticadas, sino que además incluye algún mecanismo de autorización basado en roles claims y hay determinados endpoints que tienen un comportamiento u otro en base a esta información. Desde luego, este es el escenario perfecto en el que los test de integración aportan muchísimo. Pero no es fácil de configurar. ¿Cómo puedo incluir de forma sencilla en mis test de integración los claims del usuario que quiero suplantar al realizar la petición?

La verdad es que he utilizado diferentes aproximaciones en diferentes proyectos, pero aquí te voy a contar la que más me ha gustado.

¿Dónde configuro el mecanismo de autenticación de mi api?

Antes de entrar en faena, déjame que haga una pequeña reflexión sobre este punto. Creo que es importante.

Con WebApi voy a poder “hostear” mi api de diferentes maneras. El propio framework ya permitía el concepto de Self Host cuando se publicó su versión 1. Esto quiere decir que no necesito un IIS para exponer el api, sino que lo puedo hacer en cualquier tipo de aplicación: consola, servicio de Windows, etc. Además, con la aparición de OWIN y “katana”, es todavía más fácil utilizar diferentes “hosts” para el api.

La idea es que mi api debe incluir la lógica de autorización, para lo que seguramente, necesitará un usuario autenticado para poder saber quién es y que permisos tiene sobre el api. Sobre todo en el escenario que planteábamos en el que hay que discriminar si el usuario que hace la petición está autorizado o le tenemos que devolver un 401 o un 403.

Pero en realidad es el host el que debe decidir qué mecanismo concreto de autenticación  se ha de utilizar. Es decir, qué elemento de la petición Http se debe utilizar para identificar al usuario y conocer cuales son sus credenciales (en el sentido de claims). En un host podré utilizar tokens bearer en la cabecera estándar “Authorization”, en otro una cabecera personalizada, en otro autenticación integrada de Windows o en otro autenticación básica. O incluso una combinación de ellas. Pero en cualquier caso, mi api, una vez autenticado el usuario por el mecanismo que considere el host debería responder de forma consistente a los requisitos de autorización.

Creando un middleware de autenticación personalizado

Por lo tanto, la aproximación está clara. El TestServer que me ofrece el paquete de NuGet Microsoft.Owin.Testing  no es más que un host de mi api en el que voy a configurar un mecanismo de autenticación personalizado que me permita, de forma sencilla, establecer las credenciales del usuario que quiero suplantar en la petición.

No voy a entrar en este momento en los detalles de cómo implementar un middleware de autenticación (lo dejamos para otro post), pero no es complicado. Básicamente nos vale con saber que, para el escenario de los test de integración, la información de los claims del usuario va a viajar codificada en Base64 en la cabecera estandar de autorización. Nada complicado. Pero cuidado. Nada seguro tampoco. !Ni se te ocurra utilizar este middleware en producción!

Los test de integración

La configuración del TestServer es sencilla. Lo único que tengo que hacer es crear la clase Startup que va a definir el comportamiento del servidor y allí, configurar el middleware de autenticación personalizada justo antes de usar mi api. Por ejemplo, así:

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseTestServerAuthentication();

            var config = new HttpConfiguration();
            Sample.Api.WebApiConfiguration.Configure(config);
            app.UseWebApi(config);
        }
    }

En los ejemplos, voy usar xUnit. Cada test que se ejecuta, crea una nueva instancia de la clase que lo contiene. Además utiliza mecanismos estándar (nada de atributos) para la inicialización de los tests (en el constructor de la clase) y para la limpieza (implementar la interfaz IDisposable).

Por lo tanto, en el contexto de mis test, crearé la instancia del TestServer en el constructor de la clase de test de la siguiente forma:

        private readonly TestServer _server;
        private readonly HttpClient _userHttpCient;

        public VauesWithDefaultUserTests()
        {
            _server = TestServer.Create<Startup>();
            _userHttpCient = _server.HttpClient
                .WithDefaultIdentity(Identities.User);
        }

La magia ocurre en ese método de extensión WithDefaultIdentity . En este caso, añade una cabecera por defecto a todas las peticiones que se hagan con el HttpClient que configura. En esta cabecera, viajará la información necesaria para que el middleware de autenticación que hemos configurado cree la instancia del ClaimsPrincipal que representará la petición.

De la misma forma, hay otro método de extensión sobre la clase RequestBuilder que nos permitirá configurar las credenciales de una única petición:

        [Fact]
        public async Task WithRequestBuilder()
        {
            var response = await _server.CreateRequest("api/values")
                .WithIdentity(Identities.User)
                .GetAsync();

            response.EnsureSuccessStatusCode();
        }

Los dos métodos de extensión aceptan el mismo tipo de parámetro: un IEnumerable<Claim> en el que definiremos la información que tenga nuestro usuario en el contexto de las peticiones al api. Por ejemplo, en los ejemplos de antes, he creado una clase estática que definirá todas las identidades que quiera utilizar en el contexto de los tests:

    public static class Identities
    {
        public static readonly IEnumerable User = new[]
        {
            new Claim(ClaimTypes.NameIdentifier, "1"),
            new Claim(ClaimTypes.Name, "User"),
        };
    }

Con estos dos métodos de extensión y con el middleware configurado en la clase Startup que utiliza el servidor de test, es todo lo que necesitamos para poder realizar peticiones autenticadas a cualquier api.

Sencillo, ¿no? Desde luego, ya no tienes excusa para no tener unos bonitos test de integración de tu WebApi.

¡Que lo disfrutes!

Si tenéis curiosidad, el código fuente está aquí: https://github.com/hbiarge/Acheve.Owin.Testing.Security. En la carpeta samples podrás encontrar un ejemplo completo de uso de la librería.

Angular 1.x y las fechas

Trabajar con fechas en cualquier sistema siempre ha sido uno de los puntos más conflictivos y propensos a fallos. Entender la gestión que las diferentes plataformas hacen de las fechas locales, las fechas UTC, las zonas horarias, los formatos de serialización, … no es trivial. Panificar cómo debe almacenar las fechas nuestro sistema y cómo las debe representar para que sean leidas y modificadas por el usuario, exige un mínimo de panificación.

En las aplicaciones web en general, tenemos que tener en cuenta las características del objeto Date en javascript (por ejemplo que los meses empiezan en 0!), el comportamiento de la serialización y deserialización a JSON para que viaje por la red, y el comportamiento de la capa de serialización-deserialización de nuestra tecnología de backend.

Una de las caracteríasticas que tiene el objeto Date, es que va a representar siempre la fecha en la zona horaria configurada en el navegador (normalmente la del sistema), y que por lo tanto, para representar horas UTC vamos a tener que hacer algo de “magia” una de las librerías que facilitan enormemente manipular fechas en javascript es moment, pero no nos va a hacer falta siempre.

Angular viene con dos pequeñas joyas, poco conocidas, para poder configurar como vamos a bindear las fechas.

ng-model con fechas

Cuando bindeamos un input[date] con ng-model, la fecha que vamos a recibir en el modelo va a ser siempre la fecha local. Es decir, que si yo selecciono el día 12/03/2016 en el input y, en mi caso estoy en ese momento en la zona horaria GMT + 1, la fecha que obtendré es 12/03/2016 00:00:00 GMT+1. El problema es que esa fecha, serializada a JSON (por lo tanto UTC) se representará como 11/03/2016T23:00:00Z.

Evidentemente, si lo que estoy bindeando, por ejemplo, es un filtro de fecha que voy a enviar al servidor, no obtendré los resultados esperados, ya que mi intención es filtrar por la fecha 12/03/2016 y en realizad estoy enviando el 11/03/2016.

Afortunadamente, desde la versión 1.3 de angular, en la directiva ng-model-options hay una configuración para configurar la zona horaria.

<input type="date" ng-model-options="{timezone: 'UTC'}" ng-model="$dates.dateTimezone">

Con esta configuración, con el ejemplo anterior, cuando yo seleccione el 12/03/2016  en el input, obtendré el 12/03/2016 01:00:00 GMT+1, que cuando lo serializamos a JSON, se representa como 12/03/2016T00:00:00Z.

Por lo tanto, ya enviaremos la fecha correcta del filtro al servidor, y sin utilizar ninguna librería externa.

filter date

Esta misma configuración la tenemos disponibles en el filtro date. Este filtro permite recibir como segundo parámetro la zona horaria en la que queremos que se visualice la fecha.

<div>{{ $dates.asDate | date:'yyyy-MM-dd HH:mm:ss.sss':'UTC' }}</div>

Con lo cual, nos resultará muy sencillo mostrar al usuario fechas en formato UTC, otra vez sin necesidad de usar librerías externas.

Además otra cuestión muy interesante con el filtro date es que soporta objetos Date, strings y number. Por lo tanto, si recibimos la fecha serializada en JSON en el modelo, y sólo queremos mostrarla (no editarla), podemos bindearla tal cual sin necesidad de convertirla a un objeto Date. Si necesitamos editarla, sí que tendremos que hacer esa conversión, porque ng-model sobre un input[date] sí que necesita bindear sobre una propiedad de tipo Date.

Os dejo un plunk con algunas pruebas sobre estos temas para jugar.

Hasta la próxima!

ASP.NET Core 1.0, TypeScript y los sourcemaps

En el momento de publicar este post, el uso de TypeScript en un proyecto de ASP.NET Core 1.0 debe seguir una configuración determinada, tal y como se explica aquí: https://github.com/Microsoft/TypeScript/wiki/Using-TypeScript-With-ASP.NET-5

Los proyectos de ASP.NET Core 1.0 sirven los ficheros estáticos desde la carpeta wwwroot, pero la configuración nos propone crear una carpeta scripts en la raíz del proyecto y en ésta, incluir el archivo tsconfig.json y los ficheros .ts. En el tsconfig.json configuramos que la ruta del javascript generado esté en la carpeta wwwroot y listo.

En mi opinión, esta es una estructura muy interesante de organizar el código, y estoy totalmente de acuerdo con ella. Pero tiene un inconveniente. Los archivos originales de TypeScript a partir de los cuales se ha generado el javascript no están disponibles en el navegador pese a que hemos configurado en el tsconfig.json la generación de sourcemaps. ¿Por qué? Pues porque apuntan a un directorio de nuestro proyecto que no se encuentra bajo wwwroot y por lo tanto no es accesible como archivo estático.

NoSourcemaps

Pero no está todo perdido…

Una de las mejores características de ASP.NET Core 1.0 es que podemos configurar completamente el pipeline que gestiona la petición y la respuesta de nuestra aplicación mediante pequeñas piezas de código que llamamos middleware. De hecho, el que nuestra aplicación sirva archivos estáticos es posible porque hemos configurado un middleware para ello. Toda esta configuración se hace en el archivo Startup.cs, dentro del método Configure.

Pues bien, lo único que tendremos que hacer es configurar una nueva instancia del middleware que permite servir archivos estáticos diciéndole que queremos servir el contenido de la carpeta scripts. Algo así:

app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(
        appEnvironment.ApplicationBasePath + @"\scripts"),
    RequestPath = new PathString("/scripts")
});

app.UseStaticFiles();

En este caso, appEnvironment es una instancia de IApplicationEnvironment que hemos añadido como parámetro en el método Configure y que nos permitirá tener acceso a la ruta física de la carpeta raíz de nuestra aplicación.

De esta forma, nuestra aplicación será capaz de servir los archivos .ts aunque no estén dentro de la carpeta wwwroot.

Sourcemaps

Experiencia de depuración completa!

Retomando el blog…

La verdad es que no ha habido nunca mucha actividad es este blog. Son esas cosas que un día tomas la decisión de empezar, escribes unas cuantas entradas con mucha ilusión, pero luego resulta muy dificil darle continuidad.

Pues vamos a darle otra oportunidad!

Mi intención es volver a escribir de forma continuada contenidos variados en el blog. ¿Sobre qué? Pues ya veremos, pero seguro que algo de .Net Core y Angular, pero en general, sobre temas variados de desarrollo web.

A ver que ha pasado cuando veamos este post en perspectiva Smile

Y tu… ¿que versión estás ejecutando?

Hace pocos días, los Rangers de Visual Studio ALM (que están realizando un excelente trabajo publicando guías y laboratorios sobre diferentes tecnologías) liberaban la guía de personalización de builds con TFS 2010.  En este excelente trabajo, nos explican algunas de las opciones de las que disponemos para personalizar los workflows que se ejecutan por defecto al crear una build automatizada de nuestro proyecto en TFS. Además han liberado también algunas Actividades personalizadas de Workflow Foundation para que las podamos reutilizar cuando personalicemos nuestras builds. Muy recomendable, de verdad.

Leyendo la guía, en un momento dado, aborda un tema que en algún que otro momento hemos necesitado cualquiera de los que nos dedicamos a esto del desarrollo del software, la personalización de la versión de nuestros ensamblados. Conforme vamos avanzando en el desarrollo de un proyecto, y sobre todo, en el momento en que ponemos en producción alguna versión de nuestro producto, éste tiene una versión. Si más adelante descubrimos que esa versión tiene un bug (seguro que no, verdad!!) o cuando añadimos nueva funcionalidad en una versión posterior, nuestros ensamblados DEBEN tener una versión diferente, ya que si no, no seremos capaces de saber qué versión concreta se está ejecutando de nuestra aplicación.

¿Pero cómo gestiona .Net el versionado de nuestros ensamblados?

Pues salvo que estés utilizando alguna utilidad, o una build personalizada que actualice automáticamente las versiones de tus ensamblados, la gestión es completamente manual. Tendrás que buscar alguna fórmula de actualizarla mediante plugins de Visual Studio, Task de MSBuild, u otros mecanismos para automatizarla. Pero primero, entendamos como se definen las versiones.

La opción más sencilla de verificar cual es la versión de tus ensamblados es acceder a las propiedades del proyecto, en la pestaña “Application”, y pulsar en el botón “Assembly information…”. Se abrirá una ventana en la que podemos establecer la versión de nuestra aplicación.

image

Pero espera… ¿La versión? ¡Que versión… ? Aparecen dos versiones… ¿Cual es la que tengo que modificar?

Pues, ¡¡no son sólo dos tipos de versiones sino tres!!

En realidad, estas versiones son atributos que se establecen a nuestro ensamblados, y los podemos encontrar, por defecto, en el archivo “AssemblyInfo.cs” (por defecto el atributo AssemblyInformationalVersion no está definido).image

[assembly: AssemblyVersion(“1.0.0.0”)]
[assembly: AssemblyFileVersion(“1.0.0.0”)]
[assembly: AssemblyInformationalVersion(“1.0.0.0”)]

¿Y para qué sirve cada uno de estos atributos?

  • AssemblyVersion: Es la versión del ensamblado, la que maneja internamente .Net para identificar la versión de nuestros ensamblados. Es la versión que verán otros ensamblados cuando referencien al nuestro. Esta versión forma parte del FullName de nuestro ensamblado, por lo tanto tiene gran importancia si se firman con nombre seguro los ensamblados. El atributo no es obligatorio. Si no se define, la versión será 0.0.0.0.
  • AssemblyFileVersion: Identifica la versión del archivo. Se usa básicamente para identificar un ensamblado en el momento del despliegue. Puede ser usado por programas de instalación. Podemos verlo desde la ventana de propiedades del archivo en el explorador de Windows. No es un atributo obligatorio. Si no se define, se usa la versión de AssemblyVersion.
  • AssemblyInformationalVersion: Identifica la versión del producto. Puede tener un formato diferente a las anteriores, ya que puede incluir texto libre en la versión, por ejemplo “2.0 RC1”. Podemos verlo desde la ventana de propiedades del archivo en el explorador de Windows. Si no está definida, se usa la versión de AssemblyFileVersion.

image

Algunas curiosidades con el número de versión

En el atributo AssemblyVersion, podemos usar un * para sustituir los dos últimos número (la Build y la Revision). El compilador genera estos dos números de manera automática. Por lo tanto, serían válidas versiones como “2.3.15.*” o “2.3.*”.

En cambio, el atributo AssemblyFileVersion no soporta este formato de versionado. Si el compilador se encuentra con algo parecido a “2.3.*” en el atributo AssemblyFileVersion, generará un warning en la compilación y se establecerá la versión a “2.3.0.0”. En cambio, y como cosa curiosa, si no hemos establecido el atributo AssemblyInformationalVersion, éste mostrará la versión “2.3.*”.

Esto pasa porque, como hemos comentado antes, AssemblyInformationalVersion soporta formatos que no sigan la definición de <major.minor.buils.revision>, por lo que aquí sería válido establecer la versión como “2.0 RTM” o “2.0 SP1”.

Acceso mediante código a las diferentes versiones

Mediante código, podemos acceder a las tres diferentes versiones de un ensamblado, y por lo tanto, mostrar al usuario la que nosotros queramos.

Para AssemblyVersion:

Assembly assembly = Assembly.GetExecutingAssembly();
// O cualquier otra forma de recuperar una instancia de tipo Assembly Version version = assembly.GetName().Version;

Para AssemblyFileVersion y paraAssemblyInformationalVersion:

Assembly assembly = Assembly.GetExecutingAssembly();
// O cualquier otra forma de recuperar una instancia de tipo Assembly FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(assembly.Location); string fileVersion = fileVersionInfo.FileVersion; string productVersion = fileVersionInfo.ProductVersion;

Destacar que la versión de AssemblyVersion es una instancia del tipo Versión, mientras que la versión de AssemblyFileVersion y la de AssemblyInformationalversion es un string ya formateado.

 

Para más información:

http://stackoverflow.com/questions/64602/what-are-differences-between-assemblyversion-assemblyfileversion-and-assemblyinf

http://msdn.microsoft.com/en-us/library/system.reflection.assemblyversionattribute.aspx

http://msdn.microsoft.com/en-us/library/system.reflection.assemblyfileversionattribute.aspx

http://msdn.microsoft.com/en-us/library/system.reflection.assemblyinformationalversionattribute.aspx

Contenedores de inyección de dependencias

En estos momentos, parece comúnmente aceptado que, en el diseño de una arquitectura mínimamente decente para una aplicación, es casi imprescindible el uso de un contenedor de inyección de dependencias. El uso de este tipo de componentes nos permitirá mantener lo más desacopladas posibles nuestras clases, con las innegables ventajas que ello supone (testeo, mantenibilidad, …).

Existen bastantes implementaciones a nuestra disposición de estos contenedores: Unity, Spring.Net, Autofac, NInject, StructureMap, CastleWindsor, cada uno con sus ventajas e inconvenientes. Es recomendable tener una idea mínima de cuales son los puntos fuertes de cada contenedor para, en función del tipo de aplicación que construyamos y de nuestros requerimientos, tener claro cual nos interesa elegir (porque hay que tener claro que ninguno es perfecto!). Una buena referencia es la información que nos proporciona Mark Seeman en el libro Dependency Injection in .NET.

Pero nosotros necesitamos de alguna manera, una forma común, independiente del contenedor que elijamos, de introducir este concepto dentro de la arquitectura de nuestra aplicación. La forma más sencilla es crear una abstracción del concepto de inyección de dependencias que sea común a todos los contenedores y así abstraernos de la implementación específica. La buena noticia es que esto ya lo han hecho por nosotros!. En Codeplex, existe un proyecto supervisado por el equipo de Patterns and Practices de Microsoft que precisamente ofrece esto (muy interesante revisar el porqué surgió este proyecto). Se trata de una pequeña librería que define una interfaz con una abstracción común del patrón ServiceLocator y una clase estática que hace las veces de variable de ambiente para acceder a esta abstracción. Además, ofrece una clase base para implementar con cada uno de los diferentes contenedores un proveedor especifico. Otra buena noticia es que muchos de los contenedores tienen ya implementaciones para usar esta librería. Es más, en la última versión de Unity, la 2.1, esta clase viene incluida en la propia dll de Unity (UnityServiceLocator).

Su uso es realmente sencillo. Lo único que debemos hacer es crear algún tipo de inicialización en nuestra aplicación de tal forma que, al iniciarse, configure el contenedor y asigne el proveedor específico a la variable de ambiente ofrecida por la librería.

Por ejemplo, para su uso con Unity, podría ser algo tan sencillo como esto:

    /// <summary>
    /// Implementación del IoC con Unity.
    /// </summary>
    public static class UnityIoC
    {
        /// <summary>
        /// Inicializa el contenedor.
        /// </summary>
        public static void Initialize()
        {
            // Creamos el contenedor
            var container = new UnityContainer();

            // Registramos los tipos
            container.AddNewExtension<CommonTypesExtension>();

            // Definimos el contenedor en el ServiceLocator
            ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(container));
        }
    }

Como vemos, creamos el contenedor, registramos los tipos y definimos el provider a través de la implementación por defecto del provider en Unity. Así de sencillo!!

Su uso en la inicialización de una aplicación simple de consola por ejemplo sería así:

    internal class Program
    {
        internal static void Main(string[] args)
        {
            // Inicializamos
            UnityIoC.Initialize();

            // Obtenemos la instancia de ambiente
            var locator = ServiceLocator.Current;

            // Resolvemos un tipo y ejecutamso una operación
            var testService = locator.GetInstance<ITestService>();
            testService.TestOperation();

            Console.ReadLine();
        }
    }

Como comentario, personalmente me gusta mucho el uso de las extensiones de Unity para realizar el registro de los tipos en el contenedor. Esto nos permite tener el código mucho más limpio, ya que cada clase tiene una responsabilidad bien marcada. IoCUnity establece la variable de ambiente y la extensión registra los tipos.

La implementación de una extensión también es muy sencilla:

 public class CommonTypesExtension : UnityContainerExtension
    {
        protected override void Initialize()
        {
            // Registrar tipos comunes
            Container.RegisterType<ILogger, MyLogger>();
            Container.RegisterType<ITestService, TestService>();
        }
    }

Utilizado de esta manera, tenemos el contenedor disponible desde cualquiera de nuestros ensamblados simplemente añadiendo una referencia a Microsoft.Practices.ServiceLocation.

¿La mejor manera? Con NuGet, por supuesto!

Proveedores personalizados

Pero, ¿que pasa si necesitamos algo más de lo que nos deja hacer el proveedor por defecto?

Pongamos un ejemplo. Una de las cosas que me gusta de la guía de arquitectura N Capas orientada al dominio publicada desde Microsoft España es el planteamiento que se hace con el contenedor de inyección de dependencias. En vez de de utilizar un único contenedor, organizan una jerarquía de contenedores desde un contenedor raíz añadiendo tantos contenedores hijos como “entornos” queramos tener en el sistema. Después, elegimos el entorno concreto definiendo una variable en el archivo de configuración de la aplicación. Una de las grandes ventajas de este sistema es que podríamos variar el comportamiento de nuestra aplicación ¡incluso en tiempo de ejecución!

Para incorporar esta funcionalidad, deberemos implementar nuestro proveedor personalizado. Pero no os preocupéis, tampoco es nada complicado. Sólo debemos heredar de la implementación por defecto que encontramos en Microsoft.Practices.ServiceLocation, que se encuentra en la clase ServiceLocatorImplBase.

Aquí va una posible implementación:

using System;
using System.Collections.Generic;
using System.Configuration;

using Microsoft.Practices.ServiceLocation;
using Microsoft.Practices.Unity;

namespace IoC.Unity
{
    public class CustomUnityServiceLocator : ServiceLocatorImplBase
    {
        #region Members

        private readonly IDictionary<string, IUnityContainer> containersDictionary;

        #endregion

        #region Constructores

        public CustomUnityServiceLocator(IDictionary<string, IUnityContainer> containersDictionary)
        {
            if (containersDictionary == null)
            {
                throw new ArgumentNullException("containersDictionary");
            }

            this.containersDictionary = containersDictionary;
        }

        #endregion

        #region Métodos

        protected override object DoGetInstance(Type serviceType, string key)
        {
            var containerName = this.GetContainerName();
            this.CheckContainerName(containerName);

            var container = this.containersDictionary[containerName];

            return container.Resolve(serviceType, key, new ResolverOverride[0]);
        }

        protected override IEnumerable<object> DoGetAllInstances(Type serviceType)
        {
            var containerName = this.GetContainerName();
            this.CheckContainerName(containerName);

            var container = this.containersDictionary[containerName];

            return container.ResolveAll(serviceType, new ResolverOverride[0]);
        }

        protected virtual string GetContainerName()
        {
            return ConfigurationManager.AppSettings["defaultIoCContainer"];
        }

        private void CheckContainerName(string containerName)
        {
            if (string.IsNullOrWhiteSpace(containerName))
            {
                throw new ArgumentNullException("containerName");
            }

            if (!this.containersDictionary.ContainsKey(containerName))
            {
                throw new InvalidOperationException("No se encuentra la clave en el diccionario");
            }
        }

        #endregion
    }
}

Como veis, sólo estamos obligados a definir dos métodos abstractos de la clase base (DoGetInstance y DoGetAllInstances) que se encargan de resolver realmente la instancia (o todas las instancias) utilizando el contenedor que tengamos definido en la configuración.

Esto es todo. Ahora a desacoplar nuestras aplicaciones.

Solución de ejemplo en GitHub