viernes, 16 de diciembre de 2016

String to hexadecimal and back

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
            string a = "secretpassword*";
            Console.WriteLine(a);
            string hex = ConvertStringToHex(a);
            Console.WriteLine(hex);
            Console.WriteLine(ConvertHexToString(hex));
        }
     
        public static string ConvertStringToHex(string asciiString)
        {
            string hex = "";
            foreach (char c in asciiString)
            {
                int tmp = c;
                hex += String.Format("{0:x2}", (uint)System.Convert.ToUInt32(tmp.ToString()));
            }
            return hex;
        }
   
        public static string ConvertHexToString(string HexValue)
        {
            string StrValue = "";
            while (HexValue.Length > 0)
            {
                StrValue += System.Convert.ToChar(System.Convert.ToUInt32(HexValue.Substring(0, 2), 16)).ToString();
                HexValue = HexValue.Substring(2, HexValue.Length - 2);
            }
            return StrValue;
        }
    }
}

source: rextester.com/

miércoles, 14 de diciembre de 2016

My first android app on Xamarin

Preparing installation

Install cross platform mobile options on visual studio setup


Install jdk java 8 for 64 bits



Update sdk android packages to version 25




Configuring environment

Change active jdk to 1.8 on settings on Tools / Options / Xamarin / Android Settings


Creating a project

Create new project selecting cross-platform and Blank Xaml App Xamarin Forms Portable.


Once the project was created, your most select the Droid project as Start Project. When you connect your android phone, it appears on run debug options as show on the example below as Samsung SGH.


Deploying project

Build solution. After that select deploy option.




sábado, 10 de diciembre de 2016

Get result from MVC controller method without parameters using jQuery when PageReady event occurs


Add call controller method without parameters: 

NOTE that url = '/<controller>/<method>'

<script type="text/javascript">

    $(document).ready(function () {

        $.ajax({
            type: "GET",
            url: '/Home/ValidateSession',
            data: param = "",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: successFunc,
            error: errorFunc
        });

        function successFunc(data, status) {
            if (!data) {
            $("#Modal").modal();
            }
        }

        function errorFunc() {
            alert('Ha ocurrido un error. Si el problema persiste contacte al proveedor de servicios.');
        }

    });

</script>


Add method on Home controller. This method returns true o false.

[HttpGet]
public ActionResult ValidateSession()
{
    var result = Session["ValidUser"] != null;
    return Json(result, JsonRequestBehavior.AllowGet);
}


The result value is returned to data for jQuery function that evaluate if it is true or false. If it is false the function shows an access-control popup window.

No useful for the example, but complementary. You can create popup window with bootstrap:

<div class="modal fade" id="Modal" role="dialog">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="well">
                ...
            </div>
        </div>
    </div>
</div>

Adding page navegation to a MVC button on click event using jQuery

Declare a button:

<button type="submit" id="btSubscription" >Obtener una suscripción</button>


After that, add jQuery function:

<script type="text/javascript">

    $(document).ready(function () {

        $("#btSubscription").click(function (event) {
            event.preventDefault();
            var url = '@Url.Action("Subscriptions", "Home")';
            window.location.href = url;
        });

    });

</script>

miércoles, 7 de diciembre de 2016

Estrategia de Organización de Código Fuente


Estrategia de Organización de Código Fuente
Recomendaciones de un experto de Microsoft NY

Proyectos

La compilación de la solución actualmente toma demasiado tiempo debido a la gran cantidad de proyectos en la solución. Esto también causa mucha complejidad cuando intentamos administrar las dependencias como los paquetes Nuget y cuando queremos hacer limpieza del código haciendo "refactoring". Ofrezco las siguientes recomendaciones para consolidar proyectos:

- Consolidar proyectos basándonos principalmente en unidades de instalación, por esto me refiero a esos componentes que se instalan por si solos como:
  • Webs (interfaces de usuarios)
  • APIs (interfaces con máquinas)
  • Servicios Asíncronos

- Luego, consolidar los proyectos según se necesiten compartir entre las unidades de instalación.

  • Por lo general no hay problema con tener solo un proyecto “DLL” que incluye todo el DAL y BL.
  • Puede que esto no sea posible en ciertos casos que se desea inyectar funcionalidad a la aplicación sin tener que recompilar todo, si este es el caso pues se permite tener una separación de DLLs mas estratégica. Pero aun así, rara la vez se necesitan más de unos 15 a 20 proyectos hasta para las soluciones más complejas.

- Añadir un nuevo proyecto no debe ser una decisión ligera y debe ser discutida con el equipo.

- Similarmente, añadir un paquete Nuget o implementar un nuevo patrón de arquitectura no se debe hacer en aislamiento y debe ser discutido por el equipo.

Bases de datos

Uso de Entity Framework (EF)

- Se recomienda el uso de EF para la mayoría de los casos de acceso a la base de datos, código que aun usa ADO.NET sin buena razón debe ser actualizado a EF.

- Consolidar uso de migraciones de EF o proyectos SSDT (SQL Server Data Tools) (Decidir si usar uno u otro).

- Las bases de datos tienen que ser mantenidas en código fuente y los cambios a las bases de datos de producción solo deben venir de un build que haya pasado todas las pruebas unitarias. Cualquier “hot fix” a la base de datos tiene que ser consolidado de inmediato al código fuente. 

Estrategia de Pruebas Unitarias

- Las pruebas unitarias deben correr sin problemas para un nuevo desarrollador que acaba de recibir la solución desde codigo fuente sin ningún tipo de configuración manual, o sea, la ejecución de la prueba unitaria se hace cargo de configurar automáticamente todas las dependencias y de limpiar el ambiente en caso de que una prueba falle.

- Debemos configurar tantas pruebas unitarias como sea posible para que corran con el build diario. Esto envuelve implementar muy bien el punto anterior de la configuración automatizada.

- Se recomienda usar la estrategia “fail fast” con un mensaje de error claro donde evitamos tragarnos las excepciones y en vez las reportamos tan pronto es posible.

Estrategia para "Refactoring"

Hay que sacar tiempo en todas las iteraciones de desarrollo para hacer “refactoring” para limpiar el código y mejorar la lectura y comprensión del mismo. Recomiendo que los desarrolladores saquen un 10% de su tiempo para esto. Nunca combinen tareas de “refactoring” con tareas de nueva implementación. Todo “refactoring” debe hacerse con el apoyo de pruebas unitarias que nos dirán si el “refactoring” ha roto la aplicación.

Una guía que recomiendo para hacer “refactoring” es repite el mismo código hasta dos veces, a la tercera no lo repitas más y haz “refactoring” para reusar el mismo codigo. Si seguimos esta simple guía nuestro código ira mejorando mucho. Recuerden, si estamos haciendo mucho “copy/paste” lo más seguro necesitamos hacer “refactoring” en vez.

Estrategia DevOps

Una vez tenemos un build estable y pruebas unitarias confiables podemos comenzar a configurar el empaque de la solucion y la transferencia a los otros ambientes como QA y Producción. 

Para esto recomiendo usar la funcionalidad de “Releases” de VSTS que podemos usar para automatizar la creación de paquetes de instalación o hasta automatizar completamente la instalación a los ambientes QA y hasta PROD.  

martes, 5 de enero de 2016

Basic Transation ADO.NET

using System;
using System.Configuration;
using System.Data.SqlClient;
using System.Diagnostics;

namespace ERMX.TE.CFDIValidation.Data
{  /// <summary>
  /// Representa clase base para acceso a datos
  /// </summary>
  public abstract class BaseDataAccess: IDisposable
  {    private readonly Enterprise.USA.Monitor.Tools.EventLogWriter.EventWriter eventWriter =
      new Enterprise.USA.Monitor.Tools.EventLogWriter.EventWriter();
   
    /// <summary>
    /// Objeto de conexión de base de datos.
    /// </summary>
    private SqlConnection connection;

    /// <summary>
    /// Cadena de conexión a la base de datos
    /// </summary>
    public string StringConnection { get; internal set; }

    /// <summary>
    /// Objeto de transacción con la transacción actual/activa
    /// </summary>
    internal SqlTransaction ActiveTransaction { get; set; }

    /// <summary>
    /// Instancia un acceso a datos
    /// </summary>
    public BaseDataAccess()
    {      this.StringConnection =
        ConfigurationManager.ConnectionStrings["ConnectionStringTE"].ConnectionString;
    }     protected bool Connect()
    {      bool bolResult = false;

      if (this.connection != null &&
          this.connection.State == System.Data.ConnectionState.Open)
        return true;

      try
      {        if (this.connection == null)
        {          this.connection = new SqlConnection();
          this.connection.ConnectionString = this.StringConnection;
        }
        this.connection.Open();
        bolResult = true;

      }
      catch (SqlException ex)
      {        bolResult = false;
        eventWriter.WriteEvent(ex.HResult, EventLogEntryType.Error, ex.Message);
      }
 
      return bolResult;


    }     /// <summary>
    /// Método para crear un comando
    /// </summary>
    /// <returns></returns>
    protected SqlCommand CreateCommand()
    {      SqlCommand command = this.connection.CreateCommand();

      if (this.ActiveTransaction != null)
      {        command.Transaction = this.ActiveTransaction;
      }
      return command;

    }

    /// <summary>
    /// Inicia una transacción en base a la conexion abierta.
    /// Lo que se ejecute luego de esta invocación estará
    /// dentro de una transacción.
    /// </summary>
    /// <returns>El estado de la trasancción</returns>
    public TransactionState CreateTransaction()
    {
      TransactionState result = TransactionState.TransactionExists;

      if (this.ActiveTransaction == null)
      {
        result = TransactionState.Error;
        if (this.connection == null ||

            this.connection.State != System.Data.ConnectionState.Open)
        {       
          if (!this.Connect())
            return result;

        } 
        this.ActiveTransaction = this.connection.BeginTransaction();
        result = TransactionState.Succes;

      }
 
      return result;


    }

    /// <summary>
    /// Metodo para confirmar una transacción
    /// </summary>
    public void Commit()
    {
      ActiveTransaction.Commit();
    }
    /// <summary>

    /// Método para deshacer una transacción
    /// </summary>
    public void Rollback()
    {
      ActiveTransaction.Rollback();
    }
 
    /// <summary>

    /// Método para abrir la conexión a base de datos
    /// </summary>
    protected void Open()
    {      this.connection.Open();
    }     /// <summary>
    /// Coloca las llamadas Dispose(true)
    /// </summary>
    public void Dispose()
    {          Dispose(disposing: true);
      GC.SuppressFinalize(this);
    }     /// <summary>
    /// Realiza limpieza de código y se lleva a cabo en Dispose (bool)
    /// </summary>
    /// <param name="disposing"></param>
    public virtual void Dispose(bool disposing)
    {      if (disposing)
      {        if (this.connection != null)
        {          if (this.ActiveTransaction != null)
          {            this.ActiveTransaction.Dispose();
          }           this.connection.Close();
          this.connection.Dispose();

        }
      }
    }
   }
  /// <summary>
  /// Estado de la transaccion.
  /// TransactionExists (2) -> Ya existe una transacción iniciada.
  /// Succes (1) -> La transaccion se inicio correctamente.
  /// Error (0) -> No existe una transacción
  /// </summary>
  public enum TransactionState
  {
    Error = 0,
    Succes = 1,
    TransactionExists = 2

   }

}