Dependency Injection con Microsoft.Practices.Unity

Marzo 11, 2010 :: Posted by - Emilio Torrens :: Category - , ,

Microsoft.Practices.Unity  nos permite mapear una Clase a un Interface a través de una configuración en el .config de la aplicación, de esta manera podemos cambiar el comportamiento o el escenario en el que esta se ejecuta la aplicación tocando solo esa configuración.

Aquí dejo un ejemplo básico:

1-Creamos el Interface

public interface IMessage
{
    string Get();
}

2-Creamos las clases que implementan el interface

public class Message1 : IMessage
{
    public string Get()
    {
        return "Desde Message 1";
    }
}

public class Message2 : IMessage
{
    public string Get()
    {
        return "Desde Message 2";
    }
}

3-Creamos la clase donde usaremos el Interface, en esta debemos definir un campo del tipo del interface marcado como [Dependency] y un método de load para cargar la clase que corresponde en el interface

public class Message
{
    [Dependency]
    public IMessage IMessage { get; set; }

    public static Message Instance
    {
        get
        {
            using (IUnityContainer container = new UnityContainer())
            {
                UnityConfigurationSection ConfigurationSection =
                    (UnityConfigurationSection)
                    ConfigurationManager.GetSection("DITest");
                ConfigurationSection.Containers.Default.Configure(container);
                Message objMessage = container.Resolve<Message>();
                return objMessage;
            }
        }
    }
}

4-Creamos el archivo de configuración donde hacemos el mapeo

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
  <section name="DITest"
           type="Microsoft.Practices.Unity.Configuration.
                       UnityConfigurationSection,
                 Microsoft.Practices.Unity.Configuration"/>
  </configSections>
  <DITest>
    <containers>
      <container>
        <types>
          <type type="DITest.IMessage,DITest"
                mapTo="DITest.Message2,DITest"/>
        </types>
      </container>
    </containers>
  </DITest>
</configuration>

5-Probamos el código desde la consola y vamos cambiando el “mapTo†del archivo de configuración para ir viendo el cambio

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(Message.Instance.IMessage.Get());
        Console.ReadLine();
    }
}

Exchange 2010 y Server 2008 R2

Febrero 24, 2010 :: Posted by - Emilio Torrens :: Category - , ,

Este fin de semana he estado liado con la gente de Viabit migrando el PDC de maquina y de SO y lo mismo con el Exchange, hemos pasado de W 2003 Server a W 2008 Server R2 y de Exchange 2003 a 2010.

Aunque las cosas han ido relativamente bien hemos pasado nuestros momentos de crisis, por lo que creo que hay 3 o 4 “trucos†que conviene compartir :)

imageNo deshabilites el protocolo IPv6 en el servidor 2008 en el que instales el Exchange ya que eso provoca un error 2114 en el arranque del servicio MSExchangeDSAccess que hará que el servidor no arranque, y todos los servicios de Exchange queden en Error.

imageCuando muevas los buzones del antiguo Exchange al nuevo la información de que buzón se esta moviendo, cual tiene error, que % esta completado la encontraras en el apartado de “Solicitudes de Trasladoâ€, además si un buzón acaba en error no te permitirá volver a intentar moverlo hasta que borres la solicitud de traslado que queda en error.

imageSi necesitas que el Exchange envié a través de algún programa de 3ros o que envié a diferentes sitios según el dominio o algo de eso necesitas crear un “enviar conectores†en el “trasporte de concentradoresâ€

imageSi necesitas cambiar el puerto de ese “conector†no te queda otra que usar el Shell del Exchange
image Si utilizas Sincronización con móviles vía ActiveSync, la url de sincronización cambia a http://tuserver//Microsoft-Server-ActiveSync y debes configurarlo en “Configuración del Servidorâ€/â€Acceso Clienteâ€

Y bueno ahora no me acuerdo de mas “detallitos†ya iré actualizando el POST si recuerdo algo mas, cualquier comentario o truquillo es bienvenido :)

SoapHeader, SoapExtensions y Herencia

Diciembre 03, 2009 :: Posted by - Emilio Torrens :: Category - , , ,

Hace unos días Jordi escribió sobre las SoapExtensions y yo sobre las SoapHeaders, hoy le añadimos herencia y vemos como ahorrarnos bastante código y trabajo en una capa de servicios. :)

La idea es que todos los métodos de todos los servicios web de la aplicación se autentifiquen en el mismo sitio y no tener que poner el código de autentificación en cada método, además no queremos usar cookies ni mantenimiento de sesión.

Para esto usaremos una Cabecera Soap donde el cliente nos enviara Usuario y Contraseña, debemos crear la clase cabecera:

public class SoapHeaderCredentials : SoapHeader
{
    public string Password = "";
    public string UserName = "";
}

Cada servicio web tiene que tener una propiedad con la Cabecera, para ahorrarnos el escribirlo cada vez, creamos una clase que herede de WebService, que contenga la propiedad y heredamos los servicios web de esa clase:

public class MyWebService : System.Web.Services.WebService
{
    public SoapHeaderCredentials soapHeaderCredentials;
}

public class Service : MyWebService

Después creamos una Extensión Soap de autentificación (en este caso la llamamos AuthenticationExtension), Jordi ya explica aquí como crearlas así que solo pongo el código que nos interesa, que es donde buscamos la Cabecera Soap en el Método ProcessMessage:

case SoapMessageStage.AfterDeserialize:
{
    var o = from h in message.Headers.Cast<SoapHeader>()
            where h.GetType() == typeof(SoapHeaderCredentials)
            select h ;
    SoapHeaderCredentials soapHeaderCredentials =
        (SoapHeaderCredentials) o.First();
    AuthenticateUser(
        new Credentials()
        {
          UserName = soapHeaderCredentials.UserName,
          Password = soapHeaderCredentials.Password,
        }, 
      );
    break;
}

Después solo queda añadir los dos atributos [SoapHeader("soapHeaderCredentials")]  y [AuthenticationExtension()] a nuestros WebMethods, eso hará que los métodos tengan la cabecera de usuario y contraseña y que ejecuten el código de autentificación al recibir un mensaje:

[WebMethod]
[SoapHeader("soapHeaderCredentials")]
[AuthenticationExtension()]
public string HelloWorld()
{
    return "Hello World";
}

Y listo :)

Serializar y Deserializar nuestras clases

Noviembre 30, 2009 :: Posted by - Emilio Torrens :: Category - , ,

Es sencillo obtener una representación XML de nuestras clases con el método ToString, solo hemos de sobrescribirlo por este:

public override string ToString()
{
    XmlSerializer ser = new XmlSerializer(this.GetType());
    StringWriter sw = new StringWriter();

    ser.Serialize(sw, this);

    sw.Flush();
    sw.Close();
    return sw.ToString();
}

También podemos crearlas desde su representación XML:

public static MyClass CreateFromXml(string xml)
{
    XmlSerializer ser = new XmlSerializer(typeof(MyClass));
    StringWriter sw = new StringWriter();

    return (MyClass) ser.Deserialize(new StringReader(xml));
}

Todo el Código de ejemplo:

public class MyClass
{
    public string Data1 { get; set; }
    public string Data2 { get; set; }

    public static MyClass CreateFromXml(string xml)
    {
        XmlSerializer ser = new XmlSerializer(typeof(MyClass));
        StringWriter sw = new StringWriter();

        return (MyClass) ser.Deserialize(new StringReader(xml));
    }

    public override string ToString()
    {
        XmlSerializer ser = new XmlSerializer(this.GetType());
        StringWriter sw = new StringWriter();

        ser.Serialize(sw, this);

        sw.Flush();
        sw.Close();
        return sw.ToString();
    }

    public void Test()
    {
        MyClass c = new MyClass();
        c.Data1 = "Hola";
        c.Data2 = "Como Estas";

        string xMyClass = c.ToString();

        MyClass copy = MyClass.CreateFromXml(xMyClass);
    }
}

Nos puede ser muy útil para temas de log, guardar los datos en las desconexiones, para debugear o para transportar la clases en XML entre aplicaciones.

Comunicar Servicios Win32 con WCF

Septiembre 25, 2009 :: Posted by - Emilio Torrens :: Category - , ,

WCFEstamos haciendo unos cambios en una de nuestras aplicaciones para que funcione relativamente bien en entornos de alta disponibilidad, uno de los cambios es que los Servicios Win32, que no pueden estar activos a la vez en varios servidores, se comuniquen entre ellos de manera que siempre uno, pero solo uno de la “granja†este activo.

Para eso hemos usado comunicación TCP con WCF, cada Servicio Win32 es servidor y cliente a la vez, de esa manera se comunican en forma de árbol para saber si tienen que activarse o no.

En este Post no me enrollare con todo el sistema solo sobre como hostear un servicio WCF en un Servicio Win32 y como crear un cliente para consumirlo.

Podemos añadir el servicio al proyecto con el témplate o añadirlo a mano, en realidad solo se trata de una clase, un interface y una nueva sección en el app.config

En el interface definimos el servicio y los métodos:

namespace Service
{
    [ServiceContract]
    public interface IMyTcpServer
    {
        [OperationContract]
        bool Ping();
    }
} 

La clase debe implementar el interface y es donde pondremos el código:

namespace Service
{
    public class MyTcpServer : IMyTcpServer
    {

        public bool Ping()
        {
            return true;
        }

    }
}

La sección del app.config donde definiremos que tipo de comunicación queremos, la dirección, el puerto, etc., en este caso comunicación tcp en el puerto 8731

<services>
  <service behaviorConfiguration="Service.MyTcpServerBehavior"
    name="Service.MyTcpServer">
    <endpoint address="" binding="netTcpBinding"
              contract="Service.IMyTcpServer">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexTcpBinding"
              contract="IMetadataExchange" />
    <host>
      <baseAddresses>
        <add baseAddress="net.tcp://localhost:8731/Service/MyTcpServer/" />
      </baseAddresses>
    </host>
  </service>
</services>

Ya tenemos el servicio configurado, solo nos queda poner código en el OnStart del servicio Win32 para arrancarlo, el código es el siguiente:

ServiceHost tcpHostServer = new ServiceHost(typeof(MyTcpServer));
tcpHostServer.Open();

Ya tenemos nuestro servicio Win32 con su método de ping para poder comprobar si esta funcionando o no.

La parte cliente es realmente sencilla, ya que añadimos una Referencia de Servicio, como hacíamos antes con una referencia web, y el IDE nos crea todo el código necesario para consumir el servicio, la única diferencia es que el cliente no tiene una propiedad para indicarle la dirección del servicio, para indicarle una dirección distinta a la que crea en app.config cuando añadimos la referencia hay que hacerlo de la siguiente manera:

NetTcpBinding netTcpBinding = new NetTcpBinding();
EndpointAddress endpointAddress =
    new EndpointAddress("net.tcp://direccion:elPuerto/ElServicio/");
using (MyTcpServerClient client =
       new MyTcpServerClient(netTcpBinding, endpointAddress))
{
    return client.Ping();
}

Y listo :)
            

Buscas el w3wp de un Application Pool?

Julio 21, 2009 :: Posted by - Emilio Torrens :: Category - ,

ProcesosW3WP Si tienes un servidor de producción con muchos Aplications Pools en el IIS es complicado saber cual es cual en el Administrador de Tareas (mas si todos se ejecutan con NETWORKSERVICE), el otro día un w3wp se nos ponía en mas de un giga de memoria y necesitaba localizar que aplicación estaba haciendo eso, puedes ir parando Pools y ver que pasa o puedes usar el script iisapp.vbs que encontraras en system32, el te dará la información del id de proceso del w3wp y a que Application Pool pertenece.

Aquí el resultado

ResultadoIISAPP

Antes de los comentarios, los nombres de los Application Pools no se pueden repetir, he retocado la imagen quitando el nombre de nuestros clientes :)

Interfaces y Diferentes contextos de Datos

Julio 14, 2009 :: Posted by - Emilio Torrens :: Category - ,

El otro día en el trabajo se nos presento un problema, teníamos una librería que se encargaba de convertir un XML de un cliente a un formato interno nuestro, esta librería era compartida por varias de nuestras aplicaciones, resulta que el cliente hace un cambio de especificaciones por lo que necesitamos acceder a unos datos históricos a fin de poder seguir convirtiendo su XML a nuestro formato, pero el modo y de donde obtener esos datos cambia según en el contexto en el que se este ejecutando la DLL.

La solución, añadirle un parámetro al método de conversión, un Interface que sea el que encargado de obtener esos datos, luego en cada contexto le pasamos la clase que nos interese que tiene que implementar el Interface.

Un Ejemplo en PseudoCodigo :)

//El interface que usaremos para obtener los datos
public interface IObtenerLosDatos
{
    XmlDocument DameLosDatos();
}

//El metodo que convierte el XML
public XmlDocument ConvierteXml(XmlDocument xmlDoc,
                                IObtenerLosDatos BuscardorDatos)
{
    XmlDocument xDatosHistoricos =
        BuscardorDatos.DameLosDatos();
    //Codigos
    //Codigos
    //Codidos
    return new XmlDocument();
}

//Una clase para obtener el historico desde el disco
public class DatosDesdeDisco: IObtenerLosDatos
{
    public XmlDocument DameLosDatos()
    {
        XmlDocument xmlDocument = new XmlDocument();
        xmlDocument.Load(@"C:\Historico.xml");
        return xmlDocument();
    }
}

//Una clase para obtener el historico desde la base de datos
public class DatosDesdeSQL: IObtenerLosDatos
{
    public XmlDocument DameLosDatos()
    {
        XmlDocument xmlDocument =
            SqlHelper.Instance.GetXmlDocument();
        return xmlDocument;
    }
}

//Convertimos el XML
static void Convierte(XmlDocument xmlCliente)
{
    Program p = new Program();

    //Convertimos el XMl con el Historico desde Disco
    DatosDesdeDisco datosDesdeDisco = new DatosDesdeDisco();
    XmlDocument xmlConvertido1 =
        p.ConvierteXml(xmlCliente, datosDesdeDisco);

    //Convertimos el XMl con el Historico desde SQL
    DatosDesdeSQL datosDesdeSQL = new DatosDesdeSQL();
    XmlDocument xmlConvertido2 =
        p.ConvierteXml(xmlCliente, datosDesdeSQL);
}

Performance en LINQ 2 Objects

Junio 25, 2009 :: Posted by - Emilio Torrens :: Category - , ,

Estaba comprobando el performance de una aplicación con ANTS Profiler y me he dado cuenta que tienes que ir con mucho ojito cuando trabajas con los resultados de una sentencia LINQ, en el código que os pego reglaCol es el resultado de una sentencia LINQ a Objetos:

Podéis ver que se ejecuta dos veces, una vez cuando la uso en el foreach:

image

y otra cuando la copia a una Lista:

image

Hasta ahora yo creía que la segunda vez que accedías no se ejecutaba si no que tenia la información en algún cache, pero se ve que no, así que copiándola a la lista antes del foreach y usando la lista en el foreach hay una mejora importante de rendimiento sin hacer prácticamente nada.

Si esto no es así que alguien me corrija pls, porque me he quedado a cuadros …

Eliminar repetidos con IEqualityComparer

Junio 19, 2009 :: Posted by - Emilio Torrens :: Category - , ,

Estaba escribiendo un POST sobre usar IEqualityComparer para eliminar los objetos repetidos de una colección sin demasiado código, pero no funciona !!!

Hemos estado probándolo en un código aquí en el trabajo y eso no va, o no hace lo que esperabamos :(

Al final la manera que hemos usando es usando un ExtensionMethod y una Método de comparación, siguiendo lo que hemos leído en este blog:
http://blog.jordanterrell.com/post/LINQ-Distinct()-does-not-work-as-expected.aspx

La idea es crear la extensión en una clase estática:

namespace MyNameSpace
{
    public static class  ExtensionMethods
    {
        public static IEnumerable<T> RemoveDuplicates<T>
             (this IEnumerable<T> source, Func<T, T, bool> equater)
        {
            List<T> result = new List<T>();

            foreach (T item in source)
            {
                if (result.All(t => !equater(item, t)))
                {
                    result.Add(item);
                }
            }

            return result;
        }

    }
}

Esto hará que este método se añada a las colecciones de clases que estén en el mismo espacio de nombres, luego solo hay que crear el método que usaremos para comparar las clases, en mi caso uno que mira si los campos son iguales:

public static bool MyClassEquals(MyClass rec1, MyClass rec2)
{
    Type t = rec1.GetType();
    FieldInfo[] fi = t.GetFields();

    for (int i = 0; i < fi.Length; i++)
    {
        if (fi[i].GetValue(rec1).ToString() !=
            fi[i].GetValue(rec2).ToString())
            return false;
    }

    return true;
}

Y ya estamos listos para usarlo :)

foreach (MyClass c in MyClassList.RemoveDuplicates(MyClassEquals))

LINQ to SQL, orderby y Take

Mayo 12, 2009 :: Posted by - Emilio Torrens :: Category - , , ,

Con LINQ 2 SQL y usando Take, es realmente sencillo obtener los últimos o los primeros registros de una Tabla, simplemente tenemos que ordenarla como nos interese con el order by y usar el método Take para indicar cuantos registros queremos.

Aquí dejo un ejemplo para coger los últimos registros de una tabla.

   public List<object> GetLastRecords(int NoOfRecords)
        {
            var records =
                (from r in DataClassesDataContext.Table
                 orderby r.Pk descending select r).Take(NoOfRecords);

            List<object> Result = new List<object>();

            foreach (Record record in records)
            {
                Result.Add(records);
            }

            return Result;
        }