Aclaratoria I

Recientemente he estado revisando el código fuente que distribuyo en mi blog y he anexado al mismo mi particular disclamer, plus lo he actualizado para que funcione con el nuevo Visual Studio 2012.

También he integrado a las respectivas soluciones el maravilloso NuGet de manera que las referencias a terceras librerías como jQuery o los Microsoft Enterprise Libraries sean parte de la misma solución y se puedan descargar durante su compilación.

Para que funcione, es necesario que en los respectivos Visual Studio tengan instalado el NuGet (ya el Visual Studio 2012 lo trae instalado out of the box) y esté configurado el «Package Manager» para descargar aquellos paquetes que no se encuentren.

Package Manager Configuration

De resto, encontrarán mi código en el mismo lugar de siempre.

Como Validar el DNI o el RUC de Perú en C#

En estos días me ha tocado trabajar en un proyecto que, como tantos otros hoy día, está pensado para un entorno empresarial globalizado.

Parte de las reglas de negocio del proyecto exige, como también es común en tantos otros proyectos, validar el documento de identidad correspondiente al cliente para el país al cual éste pertenece. Para el caso de países como España o Brasil existe amplia documentación y recursos referentes al algoritmo empleado para validar sus respectivos documentos de identidad.

Pero lamentablemente para Perú, uno de los países que tengo que gestionar, la cantidad y la calidad de la información disponible es decepcionante.

DNI Electrónico Peruano

Por otro lado, al hablar de documentos de identidad en Perú, debemos distinguir entre el DNI (Documento Único de Identidad) y el RUC (Registro Único de Contribuyente). El primero aplica a los ciudadanos en general y cuenta con un identificador conocido como CUI (Cédula Única de Identidad), mientras que el segundo aplica a empresas y comercios.

El siguiente algoritmo permite validar documentos de identidad peruanos (tanto DNI como RUC). Para el caso del DNI, es independiente que el CUI tenga como término de verificación un número o una letra.

public static bool ValidateIdentificationDocumentPeru(string identificationDocument)
{
    if (!string.IsNullOrEmpty(identificationDocument))
    {
        int addition = 0;
        int[] hash = { 5, 4, 3, 2, 7, 6, 5, 4, 3, 2 };
        int identificationDocumentLength = identificationDocument.Length;

        string identificationComponent = identificationDocument.Substring(0, identificationDocumentLength - 1);

        int identificationComponentLength = identificationComponent.Length;

        int diff = hash.Length - identificationComponentLength;

        for (int i = identificationComponentLength - 1; i >= 0; i--)
        {
            addition += (identificationComponent[i] - '0') * hash[i + diff];
        }

        addition = 11 - (addition % 11);

        if (addition == 11)
        {
            addition = 0;
        }

        char last = char.ToUpperInvariant(identificationDocument[identificationDocumentLength - 1]);

        if (identificationDocumentLength == 11)
        {
            // The identification document corresponds to a RUC.
            return addition.Equals(last - '0');
        }
        else if (char.IsDigit(last))
        {
            // The identification document corresponds to a DNI with a number as verification digit.
            char[] hashNumbers = { '6', '7', '8', '9', '0', '1', '1', '2', '3', '4', '5' };
            return last.Equals(hashNumbers[addition]);
        }
        else if (char.IsLetter(last))
        {
            // The identification document corresponds to a DNI with a letter as verification digit.
            char[] hashLetters = { 'K', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J' };
            return last.Equals(hashLetters[addition]);
        }
    }

    return false;
}

Finalmente, el gobierno de Perú pone a disposición la siguiente herramienta para verificar documentos de identidad; y esta otra herramienta para validar RUC.

Espero que les sea de utilidad.

Humor: El Conocimiento de los Antiguos

Los comics de XKCD son uno de mis favoritos. Pero si hay uno que me ha marcado como ninguno ha sido este:

Nunca me sentí más cerca a otra alma y a la vez estar tan desesperadamente solo que cuando googleo un error y hay un único resultado en un foro por alguien con el mismo problema pero sin respuesta. El post es de 2003…
¿Quién eras tu? ¿Qué viste?

Y me ha marcado porque los que en él se describe me ha pasado infinidad de millones de veces!

Un Framework para Programación Orientada a Aspectos (AOP) en C#    Parte 3: Un aspecto para manejo de excepciones

Esta publicación es la cuarta parte (aunque diga parte tres) de una serie de cuatro publicaciones que estaré realizando sobre programación orientada a aspectos en .NET empleando el lenguaje de programación C#.

A parte del registro de eventos, otro elemento muy común en la programación orientada a objetos y en los lenguajes actuales (como Java o C#) es la gestión de excepciones.

El otro típico infierno al que se enfrenta un arquitecto o líder técnico a la hora de establecer la política de gestión de errores y excepciones en su diseño es la gobernabilidad de dicho diseño, y la monitorización de su cumplimiento por parte del equipo de desarrollo, cosa que se torna excesivamente complicada por la creatividad de algunos miembros del equipo que rompe la homogeneidad del mecanismo elegido como parte del modelo. Hasta aquí, este párrafo es prácticamente igual al de la segunda parte de esta serie de artículos.

Y es que el diseño y la gobernabilidad del mecanismo de gestión y manejo de excepciones adoloce de los mismos problemas y retos que que podemos encontrar con el registro de eventos.

Particularmente se encuentra que los dos (2) aspectos más difíciles de gestionar son el acto de capturar y apropiadamente manejar la excepción, seguidamente de la política a aplicar sobre ésta. Muchas veces podemos encontrarnos con aplicativos web que cuando una excepción ocurre nos muestra la temida pantalla amarilla de ASP.NET o directamente nos expone todo el stack trace de la excepción (con información de base de datos y todo), lo cual fácilmente podría usar un potencial atacante para literalmente destruir el aplicativo.

ASP.NET Yellow Page of Death

A través del enfoque de AOP, es posible interceptar las llamadas a los métodos y determinar cuando estos han generado una excepción para posteriormente aplicar la política de manejo más apropiada. Estas políticas puede ser parte del propio aspecto de gestión de excepciones. Como en el caso del registro de eventos, la implementación de este aspecto buscará reducir su implementación (y aplicación) a un atributo que decore el método cuyas posibles excepciones se quieren gestionar.

Un Apropiado Soporte

Al crear un mecanismo de gestión y manejo de excepciones, no deberíamos partir desde cero, ya que existe un montón de excelentes productos y frameworks que nos simplificarían esta tarea. Para este caso, emplearé los Microsoft Libraries, en particular el Exception Handling Application Block; sin embargo el enfoque de AOP y de este framework que he venido presentado permite emplear cualquier otra librería.

Implementación

Es importante que si no han leido las primeras partes de esta serie de artículos, aprovechen este momento para hacerlo, sobre todo la parte 1. A partir de este momento mis explicaciones considerarán que el conocimiento y los detalles técnicos explicados en esa parte ya son conocidos.

El primer paso es crear el atributo (Attribute) que decorará las clases/interfaces para capturar su ejecución e inyectar el código de manejo de excepciones. Nuestro atributo se llamará ExceptionHandlingAttribute y extiende de InterceptableAttribute, la clase base en el framework de AOP que sirve para definir atributos de intercepción.

    /// <summary>
    /// A custom attribute for exception handling purposes under an Aspect Oriented Programming paradigm.
    /// </summary>
    /// <remarks>
    /// It applies only to methods.
    /// </remarks>
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public sealed class ExceptionHandlingAttribute : InterceptableAttribute
    {
        /// <summary>
        /// Represents the exception handling politic to apply while intercepting with this concern.
        /// </summary>
        private ExceptionHandlingPolitic politic;

        /// <summary>
        /// Initializes a new instance of the <see cref="ExceptionHandlingAttribute" /> class.
        /// </summary>
        /// <param name="politic">The exception handling politic to follow.</param>
        public ExceptionHandlingAttribute(ExceptionHandlingPolitic politic)
        {
            this.politic = politic;
            this.Processor = Activator.CreateInstance(typeof(ExceptionHandlingProcessor)) as IProcessor;
        }

        /// <summary>
        /// Gets the specified exception handling politic.
        /// </summary>
        /// <value>
        /// Returns the politic to use when handling exceptions represented as a <see cref="ExceptionHandlingPolitic"/>.
        /// </value>
        public ExceptionHandlingPolitic Politic { get { return this.politic; } }
    }

Este atributo tiene una (1) propiedad muy importantes llamada Politic la cual permite establecer la política con la que se gestionará la excepción.

En el tema de políticas de manejo de excepciones hay muchas opiniones, controversias y religiones. En lo personal, dependen mucho de las características del sistema y del entorno donde se desplegará, pero habitalmente me decanto por las siguientes tres (3) políticas:

  • Encapsular: o encapsulate en inglés, es la política más habitualmente aplicada en la gestión de excepciones. Consiste en retornar una excepción nueva más significativa al llamador, pero agregando o anexando (encapsular) la excepción original en la nueva excepción. Esta política preserva el stack trace.
  • Reemplazar: o repace en inglés, consiste en retornar una nueva excepción más significativa al llamador del método, pero si agregar o anexar la excepción original; incluso pudiéndose cambiar el mensaje de la excepción. En esta política el stack trace no se preserva.
  • Propagar: o propagate en inglés, se refiere al acto de pasar la excepción al llamador del método. Esto no quiere decir que no se gestione la excepción per se, sino que no se transformará o encapsulará esta. El stack trace no sufre modificación alguna.

Utilizo estas políticas, porque la mayoría de mis diseños de software siguen un enfoque de capas, donde las excepciones que ocurren dentro de una misma capa son propagadas, cuando se pasa de una capa inferior a una capa superior se encapsulan, y cuando se tienen que llevar a la capa de UI o presentar la excepción al usuario, entonces se reemplaza (para evitar mostrar datos e información sensible a un potencial atacante). Otros enfoques arquitectónicos como el MVC o el MVVC muy probablemente empleen políticas totalmente diferentes.

Así, la propiedad Politic del atributo ExceptionHandlingAttribute admite valores del siguiente enumerado que representa las políticas antes mencionadas:

    /// <summary>
    /// Defines the exception handling politics to use.
    /// </summary>
    public enum ExceptionHandlingPolitic
    {
        /// <summary>
        /// Represents the propagation politic. 
        /// This politic specifies that every exception will be passed to the caller without any transformation.
        /// </summary>
        Propagate,

        /// <summary>
        /// Represents the wrap politic. 
        /// This politic specifies that every exception will be wrapped inside another exception and then passed to the caller.
        /// </summary>
        Wrap,

        /// <summary>
        /// Represents the replacement politic. 
        /// This politic specifies that every exception will be replaced for another exception; then the new exception will be passed to the caller.
        /// </summary>
        /// <remarks>
        /// The original exception will be lost.
        /// </remarks>
        Replace
    }

Una vez establecido el atributo de intercepción, procedemos a crear el Processor que se encargará de manejar la inyección de código antes y después de la ejecución de los métodos interceptados. Para esto crearemos la clase ExceptionHandlingProcessor que implementará la interfaz IProcessor del framework.

Esta clase es la que dependiento del valor de la propiedad Politic y basado en el Microsoft Enterprise Library Exception Handling Application Block procederá a manejar la excepción interceptada acorde a la configuración del mencionado Application Block.

La parte interesante es que para el caso de la gestión de excepciones no se necesitará el método ProcessCallMessage, ya que las excepciones como tal sólo ocurren como un retorno de método, con lo cual toda la acción ocurrirá en el método ProcessReturnMessage.

    /// <summary>
    /// Intercep processor for the calling and returning messages of the methods decorated as interceptable by this component.
    /// </summary>
    internal class ExceptionHandlingProcessor : IProcessor
    {
        /// <summary>
        /// Constant that identifies the exception handling policy of propagation.
        /// </summary>
        private const string PROPAGATE = @"PROPAGATE";

        /// <summary>
        /// Constant that identifies the exception handling policy of replacement.
        /// </summary>
        private const string REPLACE = @"REPLACE";

        /// <summary>
        /// Constant that identifies the exception handling policy of wrap.
        /// </summary>
        private const string WRAP = @"WRAP";

        /// <summary>
        /// Processes the call message, which happens before the execution of the body of the interceptable or processable method.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Since the exception handling only occurs after the execution of the body of the interceptable or processable method, this
        /// method does nothing.
        /// </para>
        /// <para>
        /// This is because the exception type is contained in the <c>Method Return Message</c>.
        /// </para>
        /// </remarks>
        /// <param name="callMessage">The <c>Method Call Message</c> to process.</param>
        /// <param name="processable">The processable decorated object to process.</param>
        public void ProcessCallMessage(IMethodCallMessage callMessage, InterceptableAttribute processable)
        {
            // Do Nothing.
        }

        /// <summary>
        /// Processes the return message, which happens after the execution of the body of the interceptable or processable method.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Since the <c>Method Return Message</c> contains the exception type, this method processes such message to retrieve the exception
        /// information.
        /// </para>
        /// <para>
        /// This method leverages the Microsoft Enterprise Library Exception Handling Application Block.
        /// </para>
        /// </remarks>
        /// <param name="returnMessage">The <c>Method Return Message</c> to process.</param>
        /// <param name="processable">The processable or interceptable object.</param>
        public void ProcessReturnMessage(IMethodReturnMessage returnMessage, InterceptableAttribute processable)
        {
            if (returnMessage != null && returnMessage.Exception != null)
            {
                string policyName = null;

                switch (((ExceptionHandlingAttribute)processable).Politic)
                {
                    case ExceptionHandlingPolitic.Propagate:
                        policyName = PROPAGATE;
                        break;

                    case ExceptionHandlingPolitic.Replace:
                        policyName = REPLACE;
                        break;

                    case ExceptionHandlingPolitic.Wrap:
                        policyName = WRAP;
                        break;

                    default:
                        throw new InvalidOperationException(@"Invalid or not defined exception handling politic.");
                }

                // Call to the static main entrance of the Microsoft Enterprise Library Exception Application Block.
                if (ExceptionPolicy.HandleException(returnMessage.Exception, policyName))
                {
                    throw returnMessage.Exception;
                }
            }
        }
    }

Como puede apreciarse en el método ProcessReturnMessage lo primero es saber si el método interceptado a retornado una excepción, lo cual se puede determinar fácilmente si la priedad Exception de la interfaz IMethodReturnMessage (a la cual pertenece el parámetro returnMessage) no es nula (null).

De haber una excepción, basta con recuperar el valor de la propiedad Politic del atributo para saber que política aplicar a la excepción interceptada. La configuración de estas políticas están delegadas al archivo de configuración del Exception Handling Application Block, y su aplicación se realiza en la línea 79.

Como en artículos anteriores, aquí tienen el código de este aspecto para estudiarlo. Espero que les sea de utilidad.

Cargar Dinámicamente Configuraciones de Entidades en Entity Framework y Code-First

En estos días he estado muy activo empleando la nueva versión del Entity Framework de Microsoft.

Una de las cosas que hace poderoso a este framework y que en particular a mi me encanta es la posibilidad de definir y configurar todo el repositorio de datos (la base de datos per se) completamente desde código fuente gestionado, un enfoque que se conoce como Code-First.

A través de Code-First es posible definir las clases POCO y también configuradores (clases que bien heradan de EntityTypeConfiguration o de ComplexTypeConfiguration) y que nos permiten definir las restricciones sobre el modelo (como claves primarias y no nulidades) o los nombres de las tablas y sus columnas.

La parte interesante es que en modelos grandes y complejos un desarrollo termina llenándose de muchos configuradores que deben ser agregados al modelo en el momento de su creación (lo cual ocurre durante el evento OnModelCreating de la clase DbContext) y que termina incrementando dos factores muy poco positivos de un código: la complejidad ciclomática y el acoplamiento de clases, ambos elementos que son reportados por el Visual Studio a través del Code Analyzer como una violación a la regla CA1506.

Para evitar esto, lo ideal seria encontrar un mecanismo para cargar los configuradores de forma dinámica; pero el problema es que el método Add para el ModelBuilder que se emplea para cargarlos no admite como parámetro una clase base o genérica que pudiera ayudarnos a través de herencia, sino que explícitamente sólo acepta un EntityTypeConfiguration o un ComplexTypeConfiguration.

Por suerte, la plataforma .NET y el lenguaje C# cuentan con una palabra que logra salvar la patria: dynamic; que se encargará de indicar al compilador que no haga validaciones del tipo de dato/objeto que se está pasando como parámetro al método y que más bien este tipo de verificaciones se practiquen en tiempo de ejecución, es decir, que el compilador confíe en que nosotros como desarrolladores sabemos que estamos haciendo.

Así, el primer paso sería utilizar Reflection sobre nuestro ensamblado (que como ya está cargado en memoria durante la ejecución del evento OnModelCreating no impactará [negativamente] en el desempeño de nuestro aplicativo)

/// <summary>
/// Method calleded when the model for a derived context has been initialized, but before the model has 
/// been locked down and used to initialize the context.
/// </summary>
/// <param name="modelBuilder">The builder that defines the model for the context being created.</param>
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    if (modelBuilder != null)
    {
        IEnumerable<Type> entityTypeConfigurationTypes = Assembly.GetExecutingAssembly().GetTypes().Where(type => !type.IsAbstract 
        && (type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration) || type.BaseType.GetGenericTypeDefinition() == typeof(ComplexTypeConfiguration)));

        foreach (Type type in entityTypeConfigurationTypes)
        {
            // The 'Add' method of the DbModelBuilder accepts both "ComplexTypeConfiguration<TComplexType>" or "EntityTypeConfiguration<TEntityType>".
            // At first glance, the type of configurator is not know during compile time.
            // The dynamic type enables the operations in which it occurs to bypass compile-time type checking, in other words,
            // types are not resolved or checked by the compiler; instead, these operations are resolved at run time (when the explicit configuration
            // type is known).
            // Reference: http://msdn.microsoft.com/en-us/library/dd264741.aspx
            dynamic entityTypeConfigurationInstance = Activator.CreateInstance(type);
            modelBuilder.Configurations.Add(entityTypeConfigurationInstance);
        }
    }
}

De esta manera incluso podemos modificar el acceso a las clases de configuración como internal; sin embargo será entonces necesario ignorar el warning CA1812 del Code Analyzer (la cual podemos suprimir de forma segura ya que sabemos que sí son consumidas por Reflection).

Actualización 21/01/2013: En la nueva versión del Entity Framework, la 6.0, encontraremos en la clase ConfigurationRegistrar un nuevo método llamado AddFromAssembly que nos permitirá hacer exactamente lo que se describe en este artículo. La clase ConfigurationRegistrar habitualmente la accedemos desde el método/evento OnModelCreating a través de la propiedad Configurations.

Referencias:

Un Framework para Programación Orientada a Aspectos (AOP) en C#    Parte 2: Un aspecto para registro de eventos

Esta publicación es la tercera parte (aunque diga parte dos) de una serie de cuatro publicaciones que estaré realizando sobre programación orientada a aspectos en .NET empleando el lenguaje de programación C#.

El que es quizás sea el ejemplo más sencillo de un aspecto es el registro de eventos de un sistema o aplicación. Así mismo, resulta ser el más significativo también.

El típico infierno al que se enfrenta un arquitecto o líder técnico a la hora de establecer la política de registro de eventos en su diseño es la gobernabilidad de dicho diseño, y la monitorización de su cumplimiento por parte del equipo de desarrollo, cosa que se torna excesivamente complicada por la creatividad de algunos miembros del equipo que rompe la homogeneidad de los mensajes que se ha establecido como parte del modelo de eventos.

Otro típico incidente es que los desarrolladores, muchas veces culpando a las restricciones de tiempo del proyecto o a la urgencia de la solicitud en la implementación de un determinado requerimiento, omiten agregar las líneas de código que generan el registro de eventos, lo cual a veces puede resultar incluso difícil de detectar en revisiones de código (a través de prácticas como los peer reviews.

A través del enfoque de AOP, es posible esconder el mensaje del evento y reducir su implementación a colocar un atributo que decore el método que se desea loggear, lo cual permitirá establacer el formato del mensaje e impedir que los miembros del equipo lo modifiquen, reforzando la arquitectura y la gobernabilidad del proyecto, a la vez que se simplifica el proceso de desarrollo y de verificación del código.

Un Apropiado Soporte

Al crear un sistema de registro de eventos, no deberíamos partir desde cero, ya que existe un montón de excelentes productos y frameworks que nos simplificarían esta tarea. Para este caso, emplearé los Microsoft Libraries, en particular el Logging Application Block; sin embargo el enfoque de AOP y de este framework que he venido presentado permite emplear cualquier otra librería como log4net o NLog.

Implementación

Es importante que si no han leido las primeras partes de esta serie de artículos, aprovechen este momento para hacerlo, sobre todo la parte 1. A partir de este momento mis explicaciones considerarán que el conocimiento y los detalles técnicos explicados en esa parte ya son conocidos.

El primer paso es crear el atributo (Attribute) que decorará las clases/interfaces para capturar su ejecución e inyectar el código de registro de eventos. Nuestro atributo se llamará LogAttribute y extiende de InterceptableAttribute, la clase base en el framework de AOP que sirve para definir atributos de intercepción.

    /// <summary>
    /// A custom attribute for logging purposes under an Aspect Oriented Programming paradigm.
    /// </summary>
    /// <remarks>
    /// It applies only to methods.
    /// </remarks>
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public sealed class LogAttribute : InterceptableAttribute
    {
        /// <summary>
        /// A stopwatch to use then the verbority level is set to its highest value, in order to
        /// log the amount of time consumed by methods calls.
        /// </summary>
        private Stopwatch timer;

        /// <summary>
        /// The verbosity level to log.
        /// </summary>
        private VerbosityLevel verbosity;

        /// <summary>
        /// Initializes a new instance of the <see cref="LogAttribute" /> class.
        /// </summary>
        /// <param name="verbosity">The verbosity level to log.</param>        
        public LogAttribute(VerbosityLevel verbosity)
        {
            this.verbosity = verbosity;
            this.Processor = Activator.CreateInstance(typeof(LogProcessor)) as IProcessor;

            if (verbosity.Equals(VerbosityLevel.Full))
            {
                this.timer = new Stopwatch();
                this.timer.Reset();
            }
        }

        /// <summary>
        /// Gets the verbosity level to log.
        /// </summary>
        /// <value>The verbosity level of the log trace as defined in <see cref="VerbosityLevel"/>.</value>
        public VerbosityLevel Verbosity { get { return this.verbosity; } }

        /// <summary>
        /// Gets the this log timer.
        /// </summary>
        /// <remarks>
        /// If the <c>Verbosity</c> is different than <see cref="VerbosityLevel.Full"/> then this property will return <c>null</c>.
        /// </remarks>
        /// <value>
        /// An instance of a <see cref="Stopwatch"/> to retrieve execution time when logging with <see cref="VerbosityLevel.Full"/>.
        /// </value>
        /// <see cref="Stopwatch"/>
        /// <see cref="AOPLoggingApplicationBlock.VerbosityLevel"/>
        public Stopwatch Timer { get { return this.timer; } }
    }

Este atributo tiene dos (2) propiedades muy importantes. La primera, llamada VerbosityLevel permite establecer que tanta información se generará/almacenará cuando se registre eventos con cada intercepción. En principio para este ejemplo he definido cuatro (4) niveles de verbosidad:

  1. None: no se registrarán eventos.
  2. Light: una mínima, pero significativa cantidad de información será generada.
  3. Medium: una cantidad moderada de significante información será generada.
  4. Full: mucha información será generada, no necesariamente todoa ella significativa, pero sí útil.

La segunda propiedad se llama Timer no es más que un Stopwatch y que para el caso de VerbosityLevel.Full nos medirá cuanto ha tardado en ejecutarse un método interceptado (con lo cual podríamos identificar cuellos de botella en tiempos de producción por ejemplo).

Una vez establecido el atributo de intercepción, procedemos a crear el Processor que se encargará de manejar la inyección de código antes y después de la ejecución de los métodos interceptados. Para esto crearemos la clase LogProcessor que implementará la interfaz IProcessor del framework.

Esta clase es la que dependiento del VerbosityLevel y basado en el Microsoft Enterprise Library Logging Application Block procederá a escribir registros acorde a la configuración del mencionado Application Block. Los métodos ProcessCallMessage y ProcessReturnMessage se encargarán de crear el mensaje del evento de una manera estandard y pre-establecida (evitando que los desarrolladores decidan el mensaje y rompan con la gobernabilidad).

Lamentablemente la implementación de la clase LogProcessor es un tanto extensa como para ponerla en esta publicación, sin embargo está disponible para descargarse (y estudiarse) justo aquí.

Instalando la plataforma .NET 4.0.3

Como seguro saben, hace cosa de cuatro meses salió una revisión de la versión 4 de la plataforma .NET.

Con versión 4.0.3, esta revisión incluye en principio varias correcciones y nuevos miembros y tipos muy solicitados por la comunidad de desarrolladores entre las cuales destacan las siguientes:

Característica / Funcionalidad 4.0.1 4.0.2 4.0.3
Soporte a la ejecución de workflows con confianza parcial.    
Actividades de mensajería de Windows Workflow Foundation (WWF) habilitada para múltiples hospedajes (hosts).    
Nuevo enumerado GCLatencyMode que configuran el comportamiento del garbage collection.    
Soporte para identificadores corelacionados en conexiones de SqlClient.    
Soporte para las nuevas clases y librerías portables (portable classes de la plataforma .NET 4.    
Soporte para AlwaysOn en el SqlClient  
Soporte para la ejecución con el SqlClient para base de datos locales de SQL Server Express.  
Soporte para diseñar y ejecutar StateMachine.
Soporte para SqlWorkflowInstanceStore sobre SQL Azure.
Compensación y balanceo para hosts personalizados.

Para poder disfrutar de esta nueva versión existen tres (3) instalables:

  1. Para desarrollar aplicaciones en el Visual Studio 2010, instalar el paquete de diseño disponible aquí.
  2. Para ejecutar aplicaciones creadas con esta revisión, instalar el paquete de ejecución (run-time) disponible aquí.
  3. Si ya disfrutan y emplean el nuevo Visual Studio 2012, entonces se necesita el paquete multi-target disponible aquí.

Referencias:

La Noche desde… La Estación Espacial Internacional

Para celebrar la llegada y exitoso descenso en Marte del bio-laboratorio Curiosity, también conocido como Mars Science Laboratory (MSL), me gustaría compartir uno de eso increíbles videos que se publican con datos e imágenes de la NASA. En este caso, es un Time-Lapse creado por Knate Myers con música de John Murphy.

Música por John Murphy – Sunshine (Adagio In D Minor)

Las fotos empleadas para crear el Time-Lapse fueron todas tomadas por la tripulación de la Estación Espacial Internacional (ISS).

Al ver un video como este es imposible no maravillarse de la vastedad y soledad del universo, incluso dentro de nuestro propio sistema solar nos tomaría años llegar a otros mundos para tratar de colonizarlos. Y sin embargo, contamos con un mundo increíble que deberíamos cuidar y proteger. Un mundo que se merece algo más y mejor que nosotros mismos.

Nuestro mundo, ese que aparece en el video, merece seres mejores que no le hagan el daño que se aprecia en las siguientes fotografías tomadas por la Flota de Satélites de Observación de la Tierra, el cual en estos días ha cumplido 40 años como la misión de observación de nuestro planeta con más tiempo en operación.

Deforestación en Bolivia – En las fotos lo que está en rojo corresponde a la vegetación. mientras los puntos en amarillo corresponden a las edificaciones.

El Mar Aral entre Uzbekistan y Kazashtan – Este solía ser uno de los más grandes del mundo, sin embargo las imágenes muestran cómo ha venido decreciendo desde 1973 hasta el 2009.

Otra serie de imágenes del Mar Aral donde se pude apreciar su total desecación.

El Mar Caspio – Estas fotografías muestran cómo se ha desarrollado, el cual solía ser una de las fuentes de aguas internas más grande del mundo. Izquierda – 1972, centro – 1987 y derecha 2010.

Great Salt Lake en Utah – Aquí se evidencia la pérdia de agua desde 1985 (izquierda) hasta 2012 (derecha).

Evitar la ventana de «Adjuntar Advertencia de Seguridad»

Hoy día ya es casi asumible que todo sistema tendrá en su arquitectura uno o más componentes de servicios, habitualmente servicios web. En la plataforma .NET, los servicios web vienen en muchas formas siendo las dos más habituales los ASMX y los SVC (WCF Web Services).

Resulta que con el Windows 7 y el Visual Studio 2008/2010 cuando trabajamos con referencias a servicios web de WCF nos suele saltar la siguiente ventana al depurar la aplicación:

Particularmente esta ventana no supone nada malo. Es una simple advertencia del sistema operativo en la que nos informa de que un usuario X trata de depurar un proceso Y. El problema es que un proceso normal de desarrollo involucra incontables sesiones de depuración, lo que eventualmente conlleva a odiar esta advertencia…

La solución formal y correcta resulta ser bastante sencilla (más allá de estar tocando el registro de Windows). Hay que seguir los siguientes pasos:

  1. Abrir la cónsola de gestión del IIS (simplemente ejecutar el comando inetmgr).
  2. Posicionarse sobre el grupo de aplicaciones (Application Pool).
  3. Seleccionar el grupo de aplicaciones sobre el cual se ejecuta el componente de servicios web de nuestro sistema.
  4. Con el botón derecho del mouse elige la opción de «Opciones Avanzadas».
  5. En la ventana que aparece, buscamos el apartado de «Identidad» y hacemos click en el botón con los puntos suspensivos (‘…’).
  6. En la nueva ventana emergente, seleccionamos del desplegable de cuentas integradas la opción de «NetworkService».
  7. Salimos de estas ventanas, y desde una línea de comando con derechos de administrador ejecutamos un reset del IIS (simplemente ejecutar el comando iisreset).

Y santo remedio. Ahora cuando depuremos una aplicación que emplea referencias a servicios web de WCF o cualquier otra integración con otro sistema al cual deba anexarse el depurador no nos saldrá la advertencia de seguridad.

Como cambiar el navegador por defecto en el Visual Studio… sin perder la cabeza!

Los profesionales que trabajamos con el ecosistema de Microsoft y la plataforma .NET solemos estar más que confirmes con el Internet Explorer (excepto el nefasto Internet Explorer 6); sin embargo la mayoría de las veces cuando trabajamos en proyectos web, nuestros clientes nos exigen soportar más de un navegador.

Parte del proceso de soportar más navegadores que el Internet Explorer es que se necesita probar cada página para garantizar su correcto funcionamiento (a nivel de JavaScript) y apropiado renderizado gráfico (a nivel de imágenes, diagramación, estilos y CSS). Lo ideal sería poder probar las páginas directamente desde el Visual Studio, pero cambiar el navegador por defecto que se ejecuta con cada depuración puede llegar a ser algo… laborioso.

En realidad, cambiar el navegador por defecto en el Visual Studio no es difícil, pero tener que hacerlo cada vez que se quiera probar una página o funcionalidad con tres o cuatro navegadores diferentes, entonces empieza a ser un verdadero dolor en… la cabeza.

Algunas personas encontraron mecanismos para automatizar el proceso a través del Windows PowerShell como por ejemplo Scott Hanselman (@shanselman) en este artículo de su blog.

Fue gracias al trabajo de Scott que la gente de Clarius Consulting creó un add-on para el Visual Studio que agrega una nueva barra al menú con botones que permiten cambiar de forma rápida y sencilla el navegador por defecto con el cual queremos trabajar. Esta barra soporta los más nuevos y usados navegadores a parte de Internet Explorer, como por ejemplo: Opera, Safari, Chrome y Firefox.

Este add-on está disponible aquí. Cabe destacar que este add-on es sólo para el Visual Studio 2005, 2008 y 2010, ya que el nuevo Visual Studio 2012 ya incluye esta maravillosa funcionalidad built-in (incluso siendo capaz de levantar y trabajar con más de un navegador a la vez).

Cuando el reto es soportar más de una versión del Internet Explorer, el tema cambia debido a la limitación que tiene Windows de no permitir que diferentes versiones de su navegador convivan en una misma instancia del sistema operativo. Para esos casos en que tenemos que probar contra diversas versiones del IE, no nos queda otra que emplear máquinas virtuales. La parte positiva es que Microsoft sabe de estos escenarios y pone a disposición de la comunidad de desarrolladores y diseñadores web de forma gratuita máquinas virtuales de Virtual-PC con diferentes configuraciones de sistemas operativos y del navegador Internet Explorer. Estas imágenes están disponibles aquí.

Actualización 02-Agosto-2013

Resulta que Microsoft ha movido el tema de las imágenes de máquinas virtuales a un sitio web especializado en el tema de la creación y gestión de aplicaciones web que sean soportadas por varios navegadores. Las imágenes están disponibles en dicho sitio web: http://www.modern.ie/.