Skip Ribbon Commands
Skip to main content

Roberto González

:

Home
Blog de Roberto González
March 14
Presentaciones en el CloudDay

El pasado Miércoles 9 de Marzo, estuvimos dando dos charlas (la chapa) en el evento de Microsoft sobre Azure y ALM.

Una de las charlas trataba sobre la gestión del ciclo de vida de una aplicación AZURE. En esta charla pudimos ver como automatizar una build para hacer despliegues planificados, integración continua, etc. Además pudimos ver intellitrace para depuración de aplicaciones en la nube.

En la otra charla dentro del track de Arquitectura pudimos ver algunas de las caraterísticas que nos proporciona AppFabric Service Bus y las novedades que ahora mismo están en “beta” y que estarán disponibles próximamente.

 

Os adjunto las ppts del evento así como un enlace a un post donde os explico de una manera detallada como desplegar mediante una build de TFS una aplicación a Azure.

http://www.thinkingtogether.net/blog/index.php/despliegue-a-azure-desde-build-de-tfs-2010-2/

PPTS:

ALM_AZURE 

Service Bus

March 13
Despliegue a Azure desde Build de TFS 2010

 

Si ya te has pegado con Azure, te habrás dado cuenta que desplegar una aplicación en sí, no tiene mucho misterio. A priori tenemos dos formas de hacerlo, o bien creamos un paquete de despliegue desde Visual Studio y posteriormente lo desplegamos desde el portal de Azure, o bien hacemos el despliegue directamente desde Visual Studio.

Ahora bien imaginémonos que todos los viernes a las 18:00 de la tarde, cuando ya todos los desarrolladores han subido al repositorio de código fuente (TFS) los últimos cambios, queremos desplegar de forma automatizada al servidor de staging nuestra aplicación para que cada lunes tengamos una nueva versión para probar. O bien tenemos a una persona no muy contenta a esas horas dándole al botón de despliegue, o bien lo automatizamos.

Para automatizar estos despliegues podemos basarnos en las Build de TFS 2010 que podremos planificar para que se ejecuten cuando nosotros queramos.

Azure publica una serie de APIs mediante REST que nosotros podremos invocar para realizar las mismas tareas que podemos ejecutar desde el portal. Para nuestro propósito estas APIs en formato REST resultan un poco engorrosas de utilizar desde una Build de TFS. Para solucionar este problema  vamos a descargamos desde la siguiente url http://archive.msdn.microsoft.com/azurecmdlets unas extensiones (CmdLets) de PowerShell para Azure. Estos comandos de Azure no son más que un Wrapper de las APIs REST mencionadas anteriormente, pero que nos simplificaran su uso desde la Build de TFS.

Estas extensiones de PowerShell debemos instalarlas en el servidor de compilación donde se ejecutará la Build.

 

Creación de aplicación a desplegar

Como primer paso vamos a crear una nueva aplicación la cual desplegaremos a Azure. Para ello creamos con Visual Studio 2010 una aplicación de tipo Windows Azure Project.

Creacion proyecto

En la siguiente pantalla, especificaremos el tipo de Role que queremos desplegar a Azure. En nuestro caso vamos a crear una aplicación web, para ello seleccionamos ASP.NET Web Role.

WebRole

Como podrás ver VS ha creado dos proyectos uno que es una aplicación Web normal y corriente y otro que es el proyecto de Azure que usaremos para configurar  como desplegaremos la aplicación a la nube.

Para finalizar este paso, deberemos subir el código fuente de estos proyectos al repositorio de TFS para que mas adelante podamos crear una build que los compile y despliegue automáticamente.

Creación de Certificado

Una vez que tenemos la aplicación que deseamos desplegar el siguiente paso es crear un certificado con el que nos podamos autenticar en Azure. Para ello ejecutamos en una ventana de Visual Studio Command Prompt el siguiente comando.

makecert -r -pe -a sha1 -n "CN=Windows Azure Authentication Certificate" -ss My -len 2048 -sp "Microsoft Enhanced RSA and AES Cryptographic Provider" –sr localmachine -sy 24 testcert.cer

Este comando además de crear el certificado en localmachine\Personal lo graba en el directorio local en el que nos encontremos.

Subida de Certificado a Azure

Una vez exportado el certificado ya lo podemos importar en Azure para securizar nuestras comunicaciones. Para ello vamos a http://windows.azure.com y seleccionamos la opción Management Certificates. A continuación pulsamos en el botón Add Certificate y seleccionamos el certificado que hemos creado anteriormente.

Creación de la Build

El siguiente paso es crear una build que automatice la compilación y despliegue de nuestro proyecto a Azure.

Para ello nos vamos al Team Explorer y en el Team Project pulsamos con el botón derecho en New Build Definition.

New Buidl

Esta acción abrirá un asistente donde debemos ir configurando como queremos que se comporte la Build:

  1. En General le especificamos el nombre de la Build, en nuestro caso Deploy To Azure.
  2. En Trigger especificamos cuando queremos que se ejecute la Build. Por ahora la dejamos como manual para lanzar nosotros la compilación cuando queramos.
  3. En Workspace automáticamente nos aparece la ubicación del código fuente de nuestro proyecto.
  4. En Build Defaults especificamos el controller encargado de gestionar nuestra Build. Además debemos especificar la carpeta compartida donde se va a dejar el resultado de la Build (logs, binarios, etc.). En mi caso \\Developer\Build.
  5. En Process es donde vamos a definir realmente los pasos que tiene que ejecutar la Build para desplegar nuestra solución a Azure.

        Antes de nada debemos tener en cuenta que el proceso por defecto de la build solo   compila y nosotros necesitamos que también cree el paquete de despliegue. Para ello en la sección 3. Advanced podemos definir argumentos a msbuild. Si especificamos /t:Publish a parte de compilar el proyecto, msbuild también creará el paquete de despliegue a azure y lo dejará dentro de una carpeta llamada Publish, en la carpeta compartida definida anteriormente (ej: \\Developer\Build\DeployAzure\DeployAzure_20110309.2\Publish).

Publish2

El siguiente paso es crear una plantilla de procesos nueva. Esta plantilla de procesos es un workflow donde se definen todos los pasos que va a ejecutar la compilación. Pulsamos en Show Details y posteriormente en New. El asistente creará una nueva plantilla en base a una existente. Como plantilla a copiar seleccionamos DefaultTemplate.xaml y al nuevo archivo (New File Name) le llamaremos DeployAzure.xaml.

 

NewBuildProcess

Con esto ya hemos creado una plantilla nueva, para editarla hacemos click en el enlace que apunta al archivo AzureDeploy.xaml en nuestro respositorio de código.

Una vez abierto el repositorio obtén la ultima versión del archivo AzureDeploy.xaml mapeándolo a una carpeta local. Esto abrirá una ventana para poder diseñar la plantilla.

Busca dentro de la plantilla la secuencia de actividades Try Compile, Test, and Associate Changesets and Work Items y arrastra debajo un objeto de tipo Sequence. Esto nos permitirá ejecutar diversas actividades secuencialmente.

despliegue secuencia

Dentro del objeto Sequence vamos a añadir una actividad llamada InvokeProcess y la renombramos a Ejecutar PS. Esta actividad será la encargada de ejecutar el script de powershell con el que realizaremos el despliegue a Azure.

Pulsamos con el botón derecho en la actividad y seleccionamos la opción Properties para configurar los argumentos que le debemos pasar al script.

  • En la propiedad FileName escribiremos “PowerShell” para indicar que el script se debe ejecutar con la aplicación powershell.
  • En la propiedad Arguments indicaremos los argumentos que debemos pasar al script. Vamos a escribir la siguiente cadena:

        String.Format(" ""& '{0}' '{1}' '{2}' '{3}' '{4}' '{5}' '{6}' '{7}' "" ", DeploymentScript, SuscripcionAzure, Certificado, BinariesDirectory + "\Publish\", PackageName, ConfigName, ServiceName, StorageAccount)

Para poder pasar estos argumentos en la definición de la build vamos a tener que declararlos en esta plantilla. Para ello pulsamos la opción Arguments al final de la plantilla. Esto nos desplegará una ventana donde podremos ir dando de alta los argumentos con los que vamos a trabajar .

argumentos

  • DeploymentScript: url donde se encuentra el script de despliegue de powershell.
  • SuscripcionAzure: Id de Suscripción de Azure
  • Certificado: Thumbprint del certificado que hemos creado al principio de este post.
  • PackageName: nombre del paquete que desplegaremos. (Service Package file (.cspkg))
  • ConfigName: nombre del fichero de configuración a desplegar. (Service Package file (.cspkg))
  • ServiceName: servicio donde realizaremos el despliegue
  • StorageAccount: nombre de una cuenta de Azure Storage

Por último en caso de que se produzca algún error en el despliegue vamos a añadir una actividad de tipo WriteBuildError para que nos lo muestre en el log. Esta actividad la añadiremos dentro de “Ejecutar PS”. En la propiedad Message escribiremos errOuput que es la variable que contendrá el mensaje de error producido al ejecutar el script.

plantilla

Ya solo nos queda guardar esta plantilla y subirla al repositorio de código fuente para poder utilizarla en la definición de la build.

En la pantalla de definición de la build debemos pulsar el botón Refresh para que se muestren todos los argumentos que debemos proporcionar a la nueva plantilla.

plantilla2

Si nos fijamos, en el argumento DeploymentScript debemos especificar la url del archivo donde se encuentra el script de powershell que ejecutará el despliegue. Una posible solución es almacenarlo en una carpeta en el servidor de compilación, por ejemplo c:\Build\Deploy\deploy.ps1.

Script de PowerShell

Si abres el script de powershell Script Powershell verás que no es nada complicado.

  • Al principio del script se recogen los parámetros con los que trabajaremos a continuación.
  • Se comprueba si se han cargado los comandos de azure.

if ((Get-PSSnapin | ?{$_.Name -eq "AzureManagementToolsSnapIn"}) -eq $null)

{

  Add-PSSnapin AzureManagementToolsSnapIn

}

  • El siguiente paso es obtener información del hosted service donde vamos a desplegar

$hostedService = Get-HostedService $servicename -Certificate $cert -SubscriptionId $sub | Get-Deployment -Slot Staging

  • Si encontramos un hosted service válido, suspendemos el despliegue que tenga en staging y lo eliminamos.

$hostedService |  Set-DeploymentStatus 'Suspended' |  Get-OperationStatus -WaitToComplete

$hostedService |   Remove-Deployment |   Get-OperationStatus -WaitToComplete

  • Por último desplegamos nuestra aplicación

Get-HostedService $servicename -Certificate $cert -SubscriptionId $sub |

    New-Deployment Staging -package $package -configuration $config -label $buildLabel -serviceName $servicename -StorageServiceName $storageAccount |

    Get-OperationStatus -WaitToComplete

 

Get-HostedService $servicename -Certificate $cert -SubscriptionId $sub |

    Get-Deployment -Slot Staging |

    Set-DeploymentStatus 'Running' |

    Get-OperationStatus –WaitToComplete

 

Ya solo nos queda guardar la definición de la build y ejecutar una nueva compilación. Si todo va bien deberemos ver en el portal de azure un nuevo despliegue. Si algo va mal Sonrisa escribe un comentario y vemos que te ha pasado.

Adjunto la plantilla de proceso y el script de powershell.

Script Powershell Plantilla de Proceso

NOTA: Un posible error que puede pasar es que al ejecutar el script de powershell este no esté firmado.

Si ejecutas Set-ExecutionPolicy Unrestricted en powershell evitarás este error. Otra opción es firmar tu script con un certificado como indica en este post http://www.hanselman.com/blog/SigningPowerShellScripts.aspx.

February 11
TF30162: Task "SharePointPortal" from Group "Portal" failed

Creando un nuevo Team Project en TFS 2010 me ha saltado el siguiente error: TF30162: Task "SharePointPortal" from Group "Portal" failed. Viendo el log de errores para ver si encontraba algo un poco mas descriptivo :) he encontrado que realmente la excepción que se estaba produciendo es la siguiente The remote server returned an error: (413) Request Entity Too Large.

Lo he solucionado ampliando el tamaño de la propiedad uploadreadaheadsize 

 C:\Windows\System32\inetsrv>appcmd set config "SharePoint - 80" -section:system.
webserver/serverruntime /uploadreadaheadsize:xxxxxxxx /commit:apphost

 

Un saludo.

January 25
Evento WE Sharepoint Developer Roadshow

El día 3 de Febrero, se impartirá en Madrid el evento WE Sharepoint Developer Roadshow. Este evento tendrá lugar en el Hotel Melia Castilla impartido al 50% en inglés y 50% .

El registro es gratuito.

  • 9:00  Registro y entrega de documentación.
  • 9:30   Introduction to SharePoint 2010/BPOS development. (Inglés) Michael Koster. Microsoft.
  • 10:15 Light Up SharePoint with Silverlight Michael Koster. (Inglés) Microsoft.
  • 11:15 Coffee Break
  • 11:45  Professional SharePoint development with VS2010 (Castellano) Juan Carlos González Martin Arquitecto de Soluciones – MVP de SharePoint. Centro Innovación de Cantabria.
  • 12:45 Team Development and ALM for SharePoint projects (Inglés) 
  • 13:30 Comida
  • 14:30 Testing SharePoint solutions - Overview (Castellano) Test House.
  • 15:15 Partner Slot – Case Study or technical session (Castellano) Roberto Gonzalez. Aventia Renacimiento.
  • 16:15 Wrap-Up

Nos vemos en el evento.

January 24
Pruebas Unitarias SharePoint 2010 y Moles

El 12 de Enero he tenido el placer de impartir con Mario Cortes un evento sobre Gestión del ciclo de vida de una aplicación  basada en SharePoint 2010. En la charla pudimos ver conceptos de ALM y como aplicarlos mediante TFS 2010 a proyectos de SharePoint.

TFS 2010 se integra perfectamente con nuestras soluciones SharePoint 2010, pero cuando llega el momento de abordar el tema de las las pruebas unitarias se nos presentan una serie de problemas.

El código que implementamos en SharePoint 2010 como por ejemplo WebParts, Event Receiver, etc. tiene una dependencia muy alta con objetos de SharePoint como por ejemplo SPSite, SPWeb, SPList,  esto nos dificulta en gran manera las pruebas unitarias.

Una de las opciones que os podéis plantear es decir, bueno pues si mi prueba unitaria está testeando un Event Receiver y este crea instancias de objetos de SharePoint pues mejor :), así aprovecho y veo que mi código va a funcionar con las dependencias que tiene con SharePoint. En este caso personalmente creo que esto no es una prueba unitaria, sino que es una prueba de integración, tenemos además el inconveniente de que nuestro código puede estar muy bien desarrollado, pero en el caso de que la base de datos de SharePoint o el propio producto esté caído daría lugar a que el test no pasara, en resumen, que estamos metiendo demasiado ruido y posiblemente no vamos a saber si lo que falla es nuestro código o SharePoint.

Otro problema que tenemos en el caso de que hagamos estas pruebas de integración, es que debemos tener un entorno controlado en el que el resultado de las pruebas sea determinista, es decir que para una misma entrada obtengamos siempre la misma salida. Esto solo lo vamos a conseguir si una vez terminadas las pruebas hacemos siempre un rollback de todos los cambios que hayamos hecho para que el escenario siempre sea el mismo.

Como vemos que esta opción no es demasiado válida para abordar pruebas unitarias con SharePoint 2010, se nos puede ocurrir la idea de utilizar Mocks  para evitar tener dependencias con objetos de SharePoint, pero en este caso tenemos que lidiar con las siguientes limitaciones:

  • Los interfaces se usan mas bien poquito: si por ejemplo SPWeb implementara ISPWeb podríamos crear un objeto Mock que implementara ISPWeb y pasar este objeto a nuestro código en vez de SPWeb.
  • Las clases están selladas: otra técnica de creación de objetos Mock es extender el tipo que queremos “simular”  sobrescribiendo los métodos de estas clases. De esta forma podemos sustituir las instancias del objeto real por el objeto mock. Pero como las clases de nuestro amigo SharePoint son selladas pues tampoco podemos tirar por este camino.
  • Algunas colecciones no tienen el método Add como por ejemplo SPItemEventDataCollection con lo cual no podemos rellenar nuestro objeto mock con datos controlados.

Después de todo este rollo me diréis pero ¿hay  alguna forma de hacer pruebas unitarias con SharePoint? pues la respuesta es Si. Una de ellas es utilizar un producto de pago que se llama Typemock Isolator que es bastante bueno y que te permite probar al menos el 80% de tu código. Otra opción es usar Moles, que entre sus muchas virtudes una de ellas es que es gratis.

 

MOLES

Microsoft Moles 2010 es un add-in de visual studio que te ayuda a aislar tu código de dependencias externas. Con los Moles podemos reemplazar cualquier método llamado desde la clase de pruebas, con tu propio delegado. En el contexto de una prueba unitaria vamos a poder realizar un detour (desvío) de cualquier llamada a los objetos de SharePoint al delegado que hayamos definido.

Os recomiendo que le echéis un vistazo a la documentación que hay publicada sobre Moles donde podréis ver la diferencia entre Stub types y Moles types.

En nuestro ejemplo vamos a crear un Event Receiver que se ejecute cuando vayamos a eliminar un contacto de una lista, de tal forma que en vez de eliminar el contacto le asignemos una fecha de baja. Este método se llamará desde el evento ItemDeleting. Para no complicar el código vamos a usar siempre los mismos datos de prueba en vez de usar los que nos pasen en el parámetro properties.

 

   1:         public void EliminarContacto(SPItemEventProperties properties)
   2:         {
   3:             const string urlSite = "http://developer";
   4:             const int idListaContacto = 0;
   5:             const int idContacto = 25;
   6:   
   7:             using (SPSite site = new SPSite(urlSite))
   8:             {
   9:                  SPWeb web = site.OpenWeb();
  10:                  SPList listaContactos = web.Lists[idListaContacto];
  11:                  SPListItem contacto = listaContactos.GetItemById(idContacto);
  12:                  contacto["FechaBaja"] = System.DateTime.Now;
  13:             }
  14:         }
 
 

Ahora vamos a ver como podemos implementar las pruebas unitarias que validen que el código que hemos implementado aquí está libre de errores.

El primer paso es crear el proyecto de Testing, para ello pulsamos con el botón derecho en el proyecto de SharePoint y seleccionamos Pex –> Create Parameterized Unit Tests. Esto nos mostrará una ventana en la que podemos seleccionar el tipo de Framework que vamos a usar para probar, en nuestro caso Visual Studio Unit Test.

CreateParameterizedTest

Una vez finalizado el asistente vemos que se ha creado un proyecto con todas las referencias a los assemblies que necesitamos. Podemos ver que también se ha creado código de ejemplo que no vamos a necesitar así que limpiaremos el código de tal manera que dentro de la declaración del namespace nos quede lo siguiente:

   1:      [TestClass]
   2:      public partial class EventReceiverTest
   3:      {
   4:          [HostType("Moles")]
   5:          [TestMethod]
   6:          public void EliminarContacto_ValoresSimples()
   7:          {
   8:          }
   9:      }

 

El siguiente paso es crear el assembly con los moles que utilizaremos para sustituir las llamadas a los objetos de SharePoint. Para ello pulsamos con el botón derecho en el assembly Microsoft.SharePoint y seleccionamos la opción Add Moles Assembly. Esta acción creará el archivo Microsoft.SharePoint.Moles.dll y añadirá automáticamente una referencia para que lo podamos usar en nuestras pruebas unitarias. Lo único que tenemos que hacer nosotros es referenciar el assembly con un using.

Add Moles Assembly

Si nos fijamos veremos que ahora vamos a tener objetos como por ejemplo MSPSite, MSPWeb, MSPListItem. Es en estos objetos donde vamos, mediante delegados, a definir como queremos que se comporten los objetos SPSite, SPWeb, SPListItem, etc.

Ahora ya podemos empezar a añadir código a nuestras pruebas unitarias, para ello añadimos dentro de nuestro método de pruebas el siguiente código:

   1:  const string NombreCampo = "FechaBaja";   
   2:  const string urlSite = "http://developer";   
   3:  const int idListaContacto = 0;   
   4:  const int idContacto = 25;   
   5:  var fechaBorrado=System.DateTime.Now;   
   6:  MSPSite.BehaveAsNotImplemented();   
   7:  MSPWeb.BehaveAsNotImplemented();

las primeras líneas son declaraciones de constantes que vamos a necesitar, las dos últimas van a provocar que todos los métodos de MSPSite y MSPWeb lancen una excepción de tipo MoleNotImplementedException. De esta forma nos aseguramos que se produzca un error para todos aquellos métodos que no hayamos definido sus delegados correspondientes.

Si añadimos debajo del código anterior la llamada al método EliminarContacto() y ejecutamos la prueba unitaria,

   1:   var target = new EventReceiver();
   2:   target.EliminarContacto();
 

veremos que se produce un error indicando que no hemos definido el constructor del objeto SPSite. Esto se produce porque cuando se prueba la parte de código  SPSite site = new SPSite(urlSite) se intenta buscar el delegado correspondiente al constructor del objeto MSPSite y como no hay ninguno definido se produce esta excepción.

ErrorMoles

Para evitar que se produzca este error vamos a definir como queremos que se comporte el constructor de SPSite, para ello usamos el objeto MSPSite, como ya hemos dicho anteriormente.

   1:  MSPSite.ConstructorString = (site, _url) =>
   2:  {
   3:      new MSPSite(site)
   4:      {  
   5:      };
   6:   };

 

El código anterior es muy simple, cada vez que creamos un objeto SPSite en nuestro EventReceiver lo que va a hacer es ejecutar el código de esta lambda expression de tal forma que tenemos el control de como queremos que se comporten nuestros objetos :).

El siguiente paso es definir el delegado para SPSite.Dispose, el cual será ejecutado cuando finalice la sentencia using, para ello modificamos el código anterior, añadiendo dentro de la creación del objeto MSPSite un mole para Dispose. En este caso ignoramos la llamada y no hacemos nada.

   1:  MSPSite.ConstructorString = (site, _url) =>
   2:  {
   3:     new MSPSite(site)
   4:     {
   5:          Dispose =() => {},
   6:      };
   7:  };

 

El siguiente código que vamos a probar es SPWeb web = site.OpenWeb(). Como ya habrás deducido debemos definir un delegado para el método OpenWeb.

   1:  MSPSite.ConstructorString = (site, _url) =>
   2:  {
   3:      new MSPSite(site)
   4:      {
   5:          Dispose =() => {},
   6:          OpenWeb = () => new MSPWeb()
   7:          {         
   8:           }
   9:       };
  10:   };

El siguiente método que se ejecutará es SPList listaContactos = web.Lists[idListaContacto].

Como la colección Lists pertenece al objeto SPWeb, debemos modificar el código anterior para que cuando se construya este objeto, indiquemos como queremos que se comporte esta colección. Como la operación que estamos haciendo con la colección Lists es de lectura, vamos a definir un delegado para ListsGet.

   1:  MSPSite.ConstructorString = (site, _url) =>
   2:  {
   3:      new MSPSite(site)
   4:      {
   5:          Dispose =() => {},
   6:          OpenWeb = () => new MSPWeb()
   7:          {        
   8:              ListsGet = () => listas 
   9:           }
  10:       };
  11:   };
 

Añade el siguiente código antes de la definición del constructor de MPSite.

   1:  MSPListCollection listas = new MSPListCollection();
   2:  listas.ItemGetInt32 = (id) =>
   3:  {
   4:     Assert.AreEqual(idListaContacto, id);
   5:     return listaContacto;
   6:  };

 

Con este código definimos como queremos que se comporte la colección Lists y devolvemos un objeto de tipo MSPList siempre y cuando el idListaContacto que estamos probando sea el que nosotros esperamos, en caso contrario damos como errónea la prueba unitaria.

Estamos usando un objeto que aun no hemos declarado, este objeto al que hemos llamado listaContacto nos servirá para especificar como queremos que se comporte nuestro objeto de tipo SPList. Para ello justo encima del código anterior añadimos lo siguiente:

   1:  MSPList listaContacto = new MSPList();
   2:  listaContacto.GetItemByIdInt32=(itemId)=>
   3:  {
   4:      Assert.AreEqual(idContacto, itemId);
   5:      return itemContacto;
   6:  };

 

Con este código definimos el delegado que se tiene que ejecutar cuando se invoque al método GetItemById pasándole un entero. En el caso de que el id del elemento que estamos probando sea el esperado devolvemos dicho elemento, en caso contrario finalizamos la prueba con un error.

Por último debemos declarar itemContacto y especificar como se debe comportar este objeto de tipo SPListItem. Justo encima del código anterior añadimos lo siguiente:

   1:  MSPListItem itemContacto = new MSPListItem();   
   2:  itemContacto.ItemSetStringObject = (campo, dato) =>   
   3:  {   
   4:     Assert.AreEqual(NombreCampo, campo);   
   5:     Assert.AreEqual(dato, fechaBorrado);   
   6:  };

En este caso vamos a asignar un valor al objeto itemContacto con lo cual debemos definir el delegado correspondiente a ItemSetStringObject. Con ItemSetStringObject estamos definiendo que vamos a asignar un valor, que el indexador de esta colección de propiedades es una cadena y que el valor a asignar es un objeto. Podemos ver que hay otros métodos como ItemSetInt32Object el cual deberíamos usar si el indexador fuera la posición del campo en vez del nombre.

Este delegado va a recibir dos parámetros uno es el nombre del campo a modificar y otro el valor, si alguno de ellos no es el esperado finalizamos la prueba unitaria indicando un error.

Como está el código ahora mismo podemos ver que la fecha que se está asignando en el código como fecha de baja es la hora actual del sistema. Y la fecha que estamos utilizando en la prueba unitaria para ver si la fecha actualizada es la correcta, también es la fecha actual, pero no tienen porque coincidir porque haya un desfase de algún segundo en la ejecución del código. Para evitar esto lo que vamos a hacer es crear un mole también para System.DateTime.Now de tal forma que podamos controlar la fecha de baja.

Lo primero que tenemos que hacer es añadir el assembly de moles para mscorlib que es realmente donde esta definido el tipo DateTime. Para hacer esto pulsamos con el botón derecho en References y seleccionamos Add Moles Assembly for mscorlib.

mscorlib

El siguiente paso es compilar para que nos añada automáticamente la referencia a mscorlib.Moles. Ahora ya tenemos disponible el mole MDateTime. Recuerda hacer un using de System.Moles para poder usarlo.

En la zona de declaraciones vamos sustituir el código var fechaBorrado=System.DateTime.Now; por:

   1:  var fechaBorrado = new DateTime(2011,1,1);
   2:  MDateTime.NowGet = () => fechaBorrado;

 

Finalmente si ejecutamos la prueba unitaria veremos que nos sale un peloto verde indicando que el test ha pasado.

Si queréis profundizar mas en el tema a parte de la documentación oficial de Microsoft hay un proyecto en codeplex http://shweet.codeplex.com/ donde puedes ver como hacer pruebas unitarias en SharePoint 2010 con Pex y Moles usando además TDD.

En el siguiente enlace podéis descargaros la ppt de la charla así como el código de este ejemplo.

 

Saludos.

May 26
Workshop de AppFabric
El proximo Viernes 28 de Mayo hay un Workshop de AppFabric en las oficinas de Microsoft.
Puedes registrarte en la siguiente dirección:
 
Agenda:
 

Agenda (9:30 – 14:00):

- Introduction to AppFabric (Windows Server & Azure) – César de la Torre – Microsoft

- Distributed Cache using AppFabric-Cache (aka. codename ‘Velocity’) – César de la Torre – Microsoft

-- Coffee time

- Hosting & Monitoring WCF Services (aka. codename ‘Dublin’) – Roberto Gonzalez - Renacimiento

- Hosting Workflow-Services 4.0 (aka. codename ‘Dublin’) – Unai Zorrilla – Plain Concepts

April 28
Nueva versión de Microsoft NLayer
Como recordareis, Microsoft ha creado una aplicación de ejemplo basándose en la arquitectura DDD para que todo aquel que quiera, pueda ver como aplicar los conceptos de DDD a un caso real.
 
Hace unos días han liberado la versión 0.7 compatible con VS 2010 RTM y Framework 4.0.
 
Además han añadido la siguiente funcionalidad:
 
  • Cliente desarrollado con Silverlight 4.0 

          -Version alpha. Solo se ha implementado una pantalla por  ahora.
          -Proyecto 100% Blend friendly
          -Liberías de clases con código de lógica de entidades para procesos STE

  • IOC

          -Registro por código en vez de usar un fichero de  configuración

  • Clases de Dominio agrupadas por Servicios de Dominio
  • Se ha refactorizado el código

En el enlace anterior además de descargaros la aplicación podéis ver también los requisitos software.


  

April 16
Evento de Windows Azure
El día 14 Aventia-Renacimiento en colaboración con Microsoft hizo un evento sobre Cloud Computing. El evento se dividió en dos partes, por la mañana fue orientado a negocio y contamos con la colaboración de un abogado especializado en aspectos legales en Cloud Computing. Por la tarde el evento fue totalmente técnico donde se impartieron varias charlas de Desarrollo en AZURE, SQL Services y se terminó con unos laboratorios que pudieron realizar in situ los asistentes que así lo desearon.
 
En la siguiente carpeta de sky drive http://cid-99fb7d3a483b374f.skydrive.live.com/browse.aspx/Evento%20de%20Azure os dejo el material, tanto las charlas como los laboratorios.
 
Tengo que agradecer al departamento de DPE de Microsoft por habernos facilitado el material de los laboratorios.
 
Un saludo.
March 25
Nueva Web de Microsoft sobre Arquitectura y en Español
Microsoft acaba de abrir un portal en msdn sobre Arquitectura. http://msdn.microsoft.com/es-es/architecture/default.aspx.
 
Ayer presentaron también un libro de Arquitectura DDD bastante interesante en la que Renacimiento ha participado en su revisión.
 
Para los que no habéis podido asistir os podeis descargar toda la documentación de esta arquitectura en la siguiente url:
 
 
Además podéis acceder al código de ejemplo:
 
Saludos.
 
March 22
Pasar de Boot Nativo a HyperV

Por si os ocurre que con Windows 7 o Windows Server 2008 R2 habéis montado una máquina virtual de arranque nativo y la queréis abrir en HyperV solo tenéis que hacer lo siguiente:

1.     Ejecutar Diskpart

2.     Dentro de Diskpart ejecutar los siguientes comandos:

·         Select vdisk file=C:\<VHDFILENAME>.VHD

·         Attach Vdisk

·         select part 1

·         active

·         Assign letter=Z

·         Exit

3.     En el command prompt, cambiar a Z:\Windows\System32.

·         Ejecutar BCDboot.exe Z:\Windows /s Z:\

·         Ejecutar BCDedit /store Z:\boot\BCD /set {bootmgr} device boot

·         Ejecutar BCDedit /store Z:\boot\BCD /set {default} device boot

·         Ejecutar BCDedit /store Z:\boot\BCD /set {default} osdevice boot

·         Exit

4.     Abrir Diskpart de nuevo y ejecutar los siguientes comandos:

·         Select vdisk file=C:\<VHDFILENAME>.VHD

·         detach vDISK

·         Exit

Una vez hecho esto ya podéis abrir el vhd desde HyperV.

 

February 19
Instalación de SharePoint 2010 RC

En el caso de que estés instalando la RC de SharePoint 2010 después de desinstalar la beta, puede ser que te encuentres con que SharePoint te dice que la Product Key introducida no es válida.

Esto es porque la instalación de la beta a un permanece en la caché.

Para solucionar esto (gracias Manuel por la info) solamente tienes que ir a la ruta C:\Users\Usuario Instalación\AppData\Local\Temp y localizar un archivo similar a SharePoint Server Setup(2010020513575012B4...).

Si editas este archivo encontrarás la ruta donde se almacenan los archivos de instalación cacheados, en mi caso C:\Program Files (x86)\MSECache\oserver2010. Borrando esta carpeta SharePoint ya aceptará tu Product Key de la RC.

Saludos.

July 02
MVP por tercer año

 

Pues parece ser que los señores de Microsoft han tenido a bien, volverme a dar el MVP de BizTalk por tercer año consecutivo.

La verdad es que cada año me hace la misma ilusión que el primero.

Espero que dentro de muy poco tengamos a otro MVP mas en Renacimiento.

Saludos.

June 23
TFS 2008 y VS2010 Beta1

 

Algunos usuarios han intentado conectarse a TFS 2008 con la beta1 de VS2010 y se han encontrado con el siguiente error:

TF31001: Cannot connect to Team Foundation Server at xxx.com. The server returned the following error: The ServicePointManager does not support proxies with the https scheme.

El problema radica en que el valor por defecto de BypassProxyOnLocal (esto indica si el servidor de proxy debe ser evitado para direcciones locales) en TFS 2008 es false, mientras que en 2010 esto cambia por motivos de rendimiento siendo true el valor por defecto.

Si quieres solucionar tu problema solo tienes que seguir las indicaciones de este post:

http://blogs.msdn.com/ablock/archive/2009/05/20/for-tfs-2010-beta-1-resolving-tf31001-the-servicepointmanager-does-not-support-proxies-with-the-https-scheme.aspx

Un saludo.

June 08
WhitePaper WCF LOB Adapter SDK y Biztalk Adapter Pack

 

En la siguiente url WCF LOB Adapter SDK and the BizTalk Adapter Pack, podéis descargaros un whitepaper sobre desarrollo de adaptadores con WCF LOB Adapter SDK y su posterior consumo tanto desde aplicaciones .NET, como desde Biztalk, MOSS, etc.

Este documento a parte de contarte como crear adaptadores basados en WCF te explica como funciona el modelo de canal de WCF.

Os recomiendo su lectura.

 

Un saludo.

June 02
Arquitectos de software que no desarrollan

El otro día estuve dando una charla en Microsoft sobre novedades de Visual Studio 2010 para Aqrquitectos. Mi charla en concreto era sobre Test Driven Development.

El evento estaba enfocado sobre todo a Arquitectos.

Hadi Hariri preguntó a la audiencia que cuantos de ellos desarrollaban y hacían pruebas unitarias. Lo curioso de esta pregunta fue la respuesta: de unas 150 personas levantaron la mano unas 10 personas.

Esto quiere decir que de todos los asistentes que la mayoría eran arquitectos, jefes de proyecto, etc. solo 10 desarrollaban.

Mi pregunta es ¿puedes ser un buen arquitecto de software y no desarrollar?. Por poner un ejemplo, ¿cómo puedes recomendar usar Entity Framework si en la vida lo has usado y no sabe los problemas (ni los beneficios reales) que te puede dar?.

Entiendo que la misión de un Arquitecto no es la desarrollar, pero sí que a mi modo de ver, un arquitecto siempre debería estar actualizado y no debería desconectarse nunca de la parte técnica participando en el desarrollo en determinados proyectos (no con una gran carga evidentemente).

Pienso que leyendo solamente, no obtienes el conocimiento suficiente como para poder definir que componentes, tecnologías o productos son los mas adecuados para desarrollar una aplicación.

Ya me diréis que opináis vosotros.

Saludos.

May 29
OSLO CTP Mayo 2009

Se acaba de liberar la CTP de Mayo de OSLO.

 

Como todos sabréis OSLO es una herramienta de modelado de Microsoft.

Las herramientas de modelado de OSLO incluyen:

  • A runtime de almacenamiento (basado en SQL Server 2008) donde se almacenarán los esquemas e instancias de de datos.
  • Una herramienta visual de modelado (Microsoft code name “Quadrant”).
  • Un lenguaje de modelado (Microsoft code name “M”).

     

    Lo bueno de esta CTP es que es la primera vez que se pone a disposición del público Quadrant. Hasta ahora solo podíamos crear modelos mediante “M”.

     

    El link para bajarla CTP es este http://go.microsoft.com/?linkid=9648442.

    Para algo mas de información de la release tenéis este enlace http://msdn.microsoft.com/en-us/oslo/releasenotes.aspx.

     

    Saludos.

  • April 28
    REST y WCF

     

    REST define un estilo de arquitectura centrada en recursos. Estos recursos son accedidos mediante el uso de URI’s y verbos HTTP (GET, POST, PUT y DELETE) en vez de basarnos en el SOAPAction como lo hace SOAP.

    Algunos de los beneficios de REST son:

    • Ligereza. No se incluye xml extra como ocurre en los paquetes SOAP.
    • El resultado devuelto por REST es fácilmente entendible. Como se suele decir es Human Readable.
    • No se necesitan toolkits para su uso.
    • Simple. Tiene menos funcionalidad evidentemente que un servicio basado en soap/WS-*, pero en muchos casos nos debería sobrar con esa funcionalidad.

    Si quisiéramos invocar a un web service que nos devolviera un cliente con identificador 25 y este web service fuera RESTful, la URI necesaria para invocar a ese recurso sería la siguiente:

    http://demo/ventas.svc/cliente/25

    En cambio en el caso de un web service basado en SOAP, mediante la URI solamente podríamos identificar el endpoint del servicio:

    http://demo/ventas.svc

    y como mucho la operación a invocar:

    http://demo.ventas.asmx?op=ObtenerClientes

    Una vez que ya “sabemos” en que consiste REST, vamos a implementar un servicio RESTFul basándonos en WCF.

     

    Creación del Servicio

     

    1. Lo primero de todo va a ser crear un nuevo servicio, para ello vamos a basarnos en la plantilla por defecto de VS 2008. Llama al proyecto RESTService.

    image 

     

    2. Renombrar el archivo IService1 por ICalculadora y modifica el contenido de éste con el siguiente código:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    using System.ServiceModel.Web;
     
    namespace RESTService
    {
     
        [ServiceContract]
     
        public interface ICalculadora
        {
            [OperationContract]
            [WebGet(
             BodyStyle = WebMessageBodyStyle.Bare,
             ResponseFormat = WebMessageFormat.Xml,
             UriTemplate="/Sumar/{op1}/{op2}")]
            string Sumar(string op1,string op2);
        }
    }

    La única diferencia con un Servicio WCF es que hemos añadido el atributo WebGet al método Sumar. Este atributo indica que la operación es de recuperación y que puede ser llamada mediante el modelo de programación web. Además estamos indicando que la URI para acceder al recurso es del estilo http://servidor/RESTService.Calculadora.svc/Sumar/25/50.

    Nota: Veréis que los parámetros en este caso son string aunque deberían ser numéricos. Esto es porque UriTemplate nos lo exige así.

    En el caso de que la operación no sea de recuperación, sino de modificación el atributo que deberemos usar es [WebInvoke].

    Ejemplo:

       1: [OperationContract]
       2: [WebInvoke(Method="DELETE",UriTemplate="/Producto/{idProducto}")]
       3: public void EliminarProducto(string idProducto)
       4: {
       5:  // eliminar el producto cuyo identificador se pasa como parámetro
       6: } 

    3. Renombra el archivo Service1.cs por Calculadora.cs y modifica el contenido de éste con el siguiente código:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
     
    namespace RESTService
    {
        public class Calculadora : ICalculadora
        {
            public string Sumar(string op1, string op2)
            {
                int operando1=0;
                int operando2=0;
                string sResultado = "";
                if ((int.TryParse(op1, out operando1)) && (int.TryParse(op2, out operando2)))
                {
                    sResultado= string.Format("El resultado de la suma es: {0}", operando1 + operando2);
                }
                return sResultado;
            }
        }
    }

     

    Como se puede apreciar, el código implementa un método sumar que toma como entrada dos parámetros y devuelve como resultado la suma de estos. Aquí no hay diferencia entre un Servicio “normal” y uno RESTful.

    4. Verifica que en el archivo app.config se han reflejado todos los cambios de nombres que hemos hecho a los archivos de código.

    5. Localiza la definición del endpoint y modifica el binding wsHttpbinding por webHttpbinding. Al final debes tener algo parecido a lo siguiente:

    <endpoint address="" binding="webHttpBinding" 
    contract="RESTService.ICalculadora" behaviorConfiguration="WebBehavior">

    6. Añade dentro del nodo <behaviors> el siguiente xml:

    <endpointBehaviors>
        <behavior name="WebBehavior">
            <webHtpp/>
        </behavior>
    </endpointBehaviors>

     

    El binding webHttpbinding indica que este servicio debe ser expuesto a través de peticiones HTTP que expongan Plain old XML (POX) en vez de mensajes basados en SOAP. Este binding se usa en conjunción con el behavior WebHttp para habilitar el modelo de programación web para un servicio WCF.

    Con esto ya hemos creado un servicio RESTFul.

     

    Consumo del Servicio

     

    Un servicio RESTful se puede invocar de dos maneras:

      1. Invocando directamente al servicio a través del objeto WebChannelFactory.
      2. Añadiendo una referencia al servicio y modificando mínimamente el proxy.

    A mi la que mas me gusta es la segunda, ya que queda todo mucho mas limpio y además seguimos invocando a todos los servicios de la misma forma con independencia de la forma en que estos se expongan.

     

    Método 1 (WebChannelFactory)

     

    1. Crea un proyecto de consola que utilizaremos para probar el Servicio RESTFul.

    2. Añade una referencia al namespace System.ServiceModel.Web.

    3. Añade una copia del archivo ICalculadora.cs a este proyecto.

    4. Añade el siguiente código para consumir el servicio:

       1: WebChannelFactory<ICalculadora> factory = new WebChannelFactory<ICalculadora>(new Uri("ruta de tu servicio")); 
       2: ICalculadora proxy = factory.CreateChannel(); 
       3: string response = proxy.Sumar("25","70"); 
       4: ((IDisposable)proxy).Dispose(); 
     

    Acuérdate de modificar “ruta de tu servicio” por la URL donde esté tu servicio RESTFul.

    Este método de invocación no necesita una referencia al servicio, solo es necesario poder acceder al Interface del servicio.

     

    Método 2 (Add Services Reference)

     

    1. Crea un proyecto de consola que utilizaremos para probar el Servicio RESTFul.

    2. Añade una referencia al namespace System.ServiceModel.Web.

    3. Añade una referencia al servicio RESTFul que quieres consumir.

    4. Abre el archivo Reference.cs que contiene el código proxy de invocación al servicio. Localiza el método Sumar y añade el siguiente atributo encima:

       1: [WebGet( 
       2: BodyStyle = WebMessageBodyStyle.Bare, 
       3: ResponseFormat = WebMessageFormat.Xml, 
       4: UriTemplate = "/Sumar/{op1}/{op2}")]

    Con este atributo le decimos al proxy como debe invocar al servicio.

    5. Abre el archivo app.config y localiza el nodo <client> donde añadiremos la definición del endpoint del servicio a consumir:

       1: <endpoint address="ruta de tu servicio" behaviorConfiguration="test" 
       2:     binding="webHttpBinding" contract="ServiceReference1.ICalculadora" 
       3:     name="WebHttpBinding1"/>

     

    6.Inmediatamente después del cierre del elemento </client> añade el siguiente xml:

       1: <behaviors>
       2:     <endpointBehaviors>
       3:         <behavior name="test">
       4:             <webHttp/>
       5:         </behavior>
       6:     </endpointBehaviors>     
       7: </behaviors>

     

    Una vez hechas estas modificaciones ya podemos invocar al servicio como siempre:

       1: CalculadoraClient calc = new ConsoleApplication2.ServiceReference1.CalculadoraClient("WebHttpBinding1"); 
       2: string response = calc.Sumar("25","70"); 

     

    Finalmente vamos a usar fiddler para ver las trazas del intercambio de llamadas HTTP entre el cliente y el servicio.

    En el caso de la llamada al servicio REST vamos a obtener la siguiente traza:

       1: GET /RESTService.Calculadora.svc/Sumar/25/70 HTTP/1.1
       2: Content-Type: application/xml; charset=utf-8
       3: VsDebuggerCausalityData: uIDPo8iVuDxtWzVIoOWhMWz8d6cAAAAAQQ14Z3Np/kGe9oMjdzTKnIAB0WdKCntFi092ERAO19oACQAA
       4: Host: xxxxxx
       5: Connection: Keep-Alive

     

    En el caso de la llamada a un servicio SOAP vamos a obtener la siguiente traza:

       1: POST /WcfServiceLibrary1.Service1.svc HTTP/1.1
       2: Content-Type: text/xml; charset=utf-8
       3: VsDebuggerCausalityData: uIDPo9JShnIh9h9LnpM3i3SLcV8AAAAADD0BBgGqLkCAeQs6rXWB4Cv3lHKbfRpOq02eDFtYkC4ACQAA
       4: SOAPAction: "http://tempuri.org/IService1/GetData"
       5: Host: xxxxxxxx
       6: Content-Length: 158
       7: Expect: 100-continue
       8: Connection: Keep-Alive
       9:  
      10: <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
      11:   <s:Body>
      12:     <GetData xmlns="http://tempuri.org/">
      13:       <value>25</value>
      14:     </GetData>
      15:   </s:Body>
      16: </s:Envelope>

     

    Si comparamos una traza con otra, veremos que en el servicio “REST” es la operación GET la que define el método a invocar y los parámetros que queremos pasarle, no existe el SOAPAction, mientras que en el servicio “SOAP” necesitamos un SOAPAction donde definamos el método a invocar a parte de un envelope donde definimos los parámetros que le pasamos a este método.

     

    La respuesta del servicio “REST” será la siguiente:

       1: HTTP/1.1 200 OK
       2: Content-Type: application/xml; charset=utf-8
       3: Server: Microsoft-IIS/7.0
       4: X-Powered-By: ASP.NET
       5: Date: Mon, 27 Apr 2009 14:33:52 GMT
       6: Content-Length: 92
       7:  
       8: <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">El resultado de la suma es: 95</string>

    La respuesta del servicio “SOAP” será la siguiente:

       1: HTTP/1.1 200 OK
       2: Content-Type: text/xml; charset=utf-8
       3: Server: Microsoft-IIS/7.0
       4: X-Powered-By: ASP.NET
       5: Date: Mon, 27 Apr 2009 14:28:00 GMT
       6: Content-Length: 203
       7:  
       8:  
       9:  
      10: <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
      11:   <s:Body>
      12:     <GetDataResponse xmlns="http://tempuri.org/">
      13:       <GetDataResult>You entered: 25</GetDataResult>
      14:     </GetDataResponse>
      15:   </s:Body>
      16: </s:Envelope>

     

    Como vemos en las trazas, la respuesta de un servicio “REST” es mucho mas simple y de menor tamaño que la respuesta de un servicio “SOAP”.

     

    En en el siguiente enlace RESTService.zip  tienes los archivos del ejemplo disponibles. Es un ejemplo muy simple pero que explica las bases para la creación de un servicio REST.

    Por último solamente queda decir que Microsoft ha publicado en codeplex un Starter Kit (Preview 2) que proporciona clases y plantillas para la creación de servicios RESTFul.

    En otro post veremos como crear y consumir un servicio usando este Starter kit.

    Saludos.

    April 28
    Nuevo sitio Talking about Windows

     

    Microsoft ha abierto un nuevo sitio llamado Talking about Windows www.talkingaboutwindows.com donde el equipo de producto de Windows 7 irá publicando información que no esté bajo NDA.

    El sitio contiene algunos videos que luego se pueden comentar.

    Un saludo.

    April 07
    Biztalk Development Center

     

    Microsoft acaba de liberar un espacio para compartir recursos sobre Biztalk.

    En esta web podremos ver links a información del producto, web cast, etc.

    http://msdn.microsoft.com/en-us/biztalk/default.aspx

    Saludos.

    April 07
    Lanzamiento campaña WCF Champs

     

    Microsoft acaba de lanzar una campaña para aquellos desarrolladores que desconocen los beneficios de WCF o que lo han probado en el pasado y no se han decido a utilizarlo en sus aplicaciones.

    La campaña tiene dos componentes principales:

    1. Tres videos web:

         Estos videos tienen como temática común la competición entre web services desarrollados mediante WCF y la forma tradicional de siempre.

    2. Web Site

         Sitio web con recursos para incrementar la curva de aprendizaje sobre WCF.

    La url para acceder a esta campaña es la siguiente www.microsoft.com/net/wcf/champ.

     

    December 09
    Biztalk Server 2009 Beta
    Microsoft acaba de liberar una versión beta de BizTalk Server 2009.
    Algunas de las mejoras de esta versión son el soporte de Visual Studio 2008 SP1, .NET Framework 3.5 SP1, SQL Server 2008 y TFS.
    El soporte de TFS nos permitirá una gestión completa del ciclo de vida de una aplicación BizTalk. Podremos gestionar entre otras cosas las pruebas unitarias, integración continua y despliegues automatizados.
    Estará disponbile un nuevo SDK para el desarollo de adaptadores basados en WCF ( LOB Adapter SDK).
    Si queréis probar el producto pasaros por connect.microsoft.com.
     
    Saludos.
    November 07
    Montando un VHD como una unidad de disco

     

    Cuantas veces no hemos tenido que arrancar una máquina virtual porque necesitamos por ejemplo un archivo o código que hemos implementado en esa máquina.

    Buscando el otro día una forma de evitar esto, me encontré con que Virtual Server 2005 R2 te permite montar archivos VHD como si fueran unidades de disco.

    Para ello no hace falta instalar todo Virtual Server solamente con instalar la opción para montar unidades nos vale.

    Para montar la unidad solamente tendremos que ejecutar lo siguiente "C:\Program Files\Microsoft Virtual Server\Vhdmount\vhdmount.exe" /m "ruta archivo vhd".

    Si queremos desmontar la unidad deberemos ejecutar lo siguiente "C:\Program Files\Microsoft Virtual Server\Vhdmount\vhdmount.exe" /u "ruta archivo vhd".

    October 30
    Evento CEUS

     

    Ayer he estado impartiendo una charla en la Conferencia de usuarios de Sharepoint organizada por Microsoft,  donde hemos visto como construir aplicaciones RIA basándonos en MOSS y Silverlight 2.0.

    Aquí os dejo la presentación y las demos que se vieron en la charla.

    http://cid-99fb7d3a483b374f.skydrive.live.com/browse.aspx/CEUS%20IV%20-%20Silverlight%20MOSS?uc=2

    Muchas gracias a todos los asistentes.

    October 13
    Evento de ALM'08 - Gestión del ciclo de vida de soluciones Sharepoint

    Este Jueves 16 de Octubre participaré como ponente en el evento de ALM que organiza Mcrosoft.

    En esta charla veremos como gestionar el ciclo de vida de soluciones Sharepoint usando Visual Studio 2008 y TFS.

    Veremos como gestionar de una forma automatizada las compilaciones diarias, pruebas unitarias y despliegues de soluciones basadas en Sharepoint.

    Espero veremos por alli.

     
    July 01
    MVP de Microsoft por segundo año consecutivo

    Acabo de recibir un mail comunicándome la renovación del MVP de Biztalk por segundo año consecutivo.

    Es una inyección de moral para seguir colaborando con la comunidad y aprendiendo de todos vosotros.

    Saludos.

    June 26
    Poster Interactivo con las capacidades de Biztalk

    Microsoft ha publicado hace tiempo la siguiente página http://www.microsoft.com/biztalk/capabilities/reader/ construida con Silverlight que permite ir navegando de forma interactiva por un poster con las capacidades de Biztalk Server 2006 R2.

    Si hacemos click en cada funcionalidad del poster se abrirá una ventana explicando dicha capacidad con enlaces al msdn de microsoft por si queremos completar la explicación.

    Saludos.

    June 17
    Como crear un adaptador con WCF LOB Adapter SDK

    He encontrado muy poca información en español sobre el desarrollo de adaptadores con WCF LOB Adapter SDK. Con este post intento poner mi granito de arena para intentar arrojar algo de luz sobre este tema.

    ¿Porqué la necesidad de WCF LOB Adapter SDK?

    Los adaptadores desarrollados hasta ahora eran dependientes tanto del consumidor como de la aplicación destinataria, es decir un adaptador desarrollado para comunicar Microsoft Biztalk Server con SAP no nos vale para comunicar Sharepoint con SAP.

    WCF LOB Adapter SDK soluciona esta limitación, permitiendo que el adaptador que desarrollemos para obtener información de una aplicación de línea de negocio pueda ser consumido desde Biztalk, desde SQL Server, desde Microsoft Office Sharepoint Server o por ejemplo desde una aplicación .NET personalizada.

    ¿Qué es WCF LOB Adapter SDK?

    Es un conjunto de herramientas y componentes que nos van a facilitar el desarrollo de adaptadores para aplicaciones de línea de negocio.

    Las principales características de WCF LOB Adapter SDK son las siguientes:

    1. Proporciona un Wizard que facilita la creación de nuevos adaptadores guiando al desarrollador paso a paso.
    2. Expone el adaptador como si fuera un binding de WCF.
    3. Proporciona un Add-in que permite añadir referencias a adaptadores desde aplicaciones .net desarrolladas con Visual Studio 2005.
    4. Crea un contrato dinámicamente en tiempo de diseño.

    WCF LOB Adapter SDK está basado en el modelo de Canal de WCF.

     

    ASDK_Comparison_Outbound 

    El modelo de canal de WCF consiste en una pila con uno o varios canales que se encargan de procesar los mensajes que fluyen entre ellos. Es muy parecida a la pila de TCP.

    WCF LOB Adapter SDK utiliza el modelo de extensibilidad de canales exponiendo los adaptadores mediante binding personalizados.

    Pasos para la creación de un adaptador

    En la siguiente url podemos descargarnos el SDK con el Service Pack 1.

    A continuación vamos a empezar a desarrollar un adaptador de que nos permitirá obtener correos mediante el protocolo POP3. Este adaptador lo podremos usar independientemente en aplicación .net o por ejemplo en Microsoft Biztalk sin modificar una sola línea de código.

    Asistente de creación del adaptador

    Lo primero que debemos hacer es crear un nuevo proyecto en con Visual Studio 2005 y seleccionar la plantilla WCF LOB Adapter.

    image

    Una vez creado el proyecto se lanzará un asistente que nos irá guiando paso paso en la creación del adaptador.

    1. En el primer paso debemos definir los siguientes campos:
      • Scheme: esquema usado para el protocolo de transporte del binding del adaptador. Por ejemplo el binding WSHttpBinding usa HTTP como esquema. Nosotros deberemos rellenar esta caja de texto con el valor mail.

      • Project namespace: todas las clases creadas por el asistente pertenecerá al namespace que pongamos aquí. Nosotros usaremos el namespace ejemplo.adaptadorwcf.

      • Service namespace: La concatenación del esquema más el namespace del proyecto dará lugar al namespace del WSDL generado por el adaptador. En nuestro caso el namespace del servicio será mail://ejemplo.adaptadorwcf. Si quisiéremos modificar el namespace propuesto por el wizard solamente tenemos que marcar la opción Overwrite default service namespace y modificar el valor por el que deseemos.

    image

       2.  En el siguiente paso debemos definir la dirección del flujo de datos soportado por el adaptador:

      • Synchronous outbound: el adaptador soporta el envío de mensajes al sistema destino.
      • Asynchronous outbound: el adaptador soporta el envío de mensajes de forma asíncrona al sistema destino.
      • Synchronous inbound: el cliente recibe información del sistema destino vía adaptador.
      • Asynchronous inbound: el adaptador soporta la recepción de mensajes del sistema destino de forma asíncrona.

             Además debemos definir las opciones de metadatos soportada por el adatador:

      • Retrieval: Genera la definición de las operaciones y tipos complejos del sistema destino. Esta información será utilizada por el adaptador para la generación del contrato del servicio.
      • Browse: Permite que el usuario navegue de forma jerárquica por los metadatos del sistema destino para seleccionar las operaciones que desea invocar.
      • Search:Permite que el usuario realice una búsqueda en los metadatos del sistema destino para seleccionar las operaciones que desea invocar.

    image

        3.  En el siguiente paso debemos definir las propiedades del adaptador:

      En nuestro caso no definiremos nada aquí.

        3.  En el siguiente paso debemos definir las propiedades de conexión con el sistema destino:

    image 

    Las propiedades necesarias para la conexión son el servidor, el usuario y el password.

    La gestión de credenciales utilizada en este ejemplo no es ni mucho menos la ideal, ya que se muestra el usuario y el password en texto plano en la URI. Os invito a que modifiquéis el adaptador para dar una solución mas eficiente y segura a la gestión de credenciales.

    Finalmente se mostrará un resumen de la configuración del adaptador que hemos ido estableciendo en los pasos precedentes. Si estamos conformes pulsaremos en el botón Finish para que el Wizard cree las clases necesarias para implementar el adaptador.

    Gestión de la conexión con el sistema destino

    El adaptador crea por nosotros el esqueleto de las clases necesarias para poder gestionar la conexión con el sistema destino.

    La clase Pop3AdapterConnectionUri.cs es la encargada de parsear y construir la cadena de conexión de la aplicación de línea de negocio destino.

    El desarrollador del adaptador usará esta clase para parsear la URI de conexión proporcionada por el cliente y extraer de ella todos los parámetros de conexión necesarios.

    public override Uri Uri
    {
       get
       {
           //Validación de las propiedades de conexión
           if (Servidor == string.Empty)
           {
               throw new InvalidUriException("Parámetro Servidor no válido");
           }
           if (Usuario == string.Empty)
           {
               throw new InvalidUriException("Parámetro Usuario no válido");
     }
           if (Password== string.Empty)
           {
                throw new InvalidUriException("Parámetro Password no válido");
           }
    
           return new Uri(Pop3Adapter.SCHEME + "://" +
                          Servidor + "/" + Usuario + "/" + Password);
                                            
       }
       set
       {
          string[] datosUri = value.AbsoluteUri.Split('/');
                    Servidor = datosUri[2];
                    Usuario = datosUri[3];
                    Password = datosUri[4];
                   
       }
    }

    La clase Pop3AdapterConnectionFactory.cs es la responsable de definir y crear la conexión con el sistema destino.

    Para ello debemos modificar el método CreateConnection para que devuelva un objeto de conexión con el servidor de correo.

    public IConnection CreateConnection()
    {
      return new Pop3AdapterConnection(conexionUri.Usuario,conexionUri.Password,
         conexionUri.Servidor, this);
    }

    El constructor de la clase Pop3AdapterConnectionFactory pasa en uno de los parámetros un objeto de tipo ConnectionUri con la información de conexión con el sistema destino. El problema es que el wizard no asigna ese objeto a ninguna propiedad de la clase con lo cual se pierde la información. Para solucionar este problema debemos declarar una variable privada llamada conexionUri y modificar el constructor de la clase para asignar a esta propiedad la información de conexión.

    public Pop3AdapterConnectionFactory(ConnectionUri connectionUri
                , ClientCredentials clientCredentials
                , Pop3Adapter adapter)
    {
        this.clientCredentials = clientCredentials;
        this.adapter = adapter;
        this.conexionUri = (Pop3AdapterConnectionUri)connectionUri;
    }

    Por último la clase Pop3AdapterConnection.cs es la encargada de realizar las llamadas a bajo nivel para gestionar la conexión con el sistema destino.

    Debemos modificar el constructor de la clase para inicializar el objeto de conexión con el servidor de correo. La clase Pop3 es una clase gratuita obtenida de la web Codeproject en la url http://www.codeproject.com/KB/IP/despop3client.aspx que emplearemos para obtener los mail del servidor de correo.

    public Pop3AdapterConnection(string Usuario,string Password, string Servidor, 
        Pop3AdapterConnectionFactory connectionFactory)
    {
        this.connectionFactory = connectionFactory;
        this.connectionId = Guid.NewGuid().ToString();
        objConexionPop3 = new Pop3.Pop3Client(Usuario,Password,Servidor);
    }

    Debemos modificar los métodos que se encargan de abrir y cerrar la conexión:

    public void Close(TimeSpan timeout)
    {
        objConexionPop3.CloseConnection();
    }
    
     public bool IsValid(TimeSpan timeout)
    {
        return true;
    }
     public void Open(TimeSpan timeout)
    {
        objConexionPop3.OpenInbox();
    }
    Gestión de metadatos

    La clase Pop3AdapterMetadataBrowseHandler.cs se encargará de mostrar de forma jerárquica las categorías y operaciones de la aplicación de línea de negocio al consumidor para que este seleccione las operaciones que desea invocar.

    Debemos implementar el método Browse de esta clase para mostrar la operación de Monitorización de correo al consumidor.

    Como podemos ver en el siguiente código, este método devuelve cada una de las operaciones y categorías del sistema destino como una lista de objetos de tipo MetadataRetrievalNode.

     

    public MetadataRetrievalNode[] Browse(string nodeId
                , int childStartIndex
                , int maxChildNodes, TimeSpan timeout)
    {
     List<MetadataRetrievalNode> lista = new List<MetadataRetrievalNode>();
           //Nodo raiz
           if (MetadataRetrievalNode.Root.NodeId.Equals(nodeId))
           {
    
              MetadataRetrievalNode nodo = new MetadataRetrievalNode("Operaciones");
              nodo.Direction = MetadataRetrievalNodeDirections.Inbound;
              nodo.DisplayName = "Operaciones";
              nodo.IsOperation = false;
              return new MetadataRetrievalNode[] { nodo };
           }
           else
           {
              MetadataRetrievalNode nodoInbound = new MetadataRetrievalNode("MonitorizacionCorreo");
              nodoInbound.DisplayName = "MonitorizacionCorreo";
              nodoInbound.IsOperation = true;
              nodoInbound.Direction = MetadataRetrievalNodeDirections.Inbound;
              lista.Add(nodoInbound);
    
              return lista.ToArray();
           }
    }

    La clase Pop3AdapterMetadataSearchHandler.cs nos permite buscar operaciones en la aplicación de línea de negocio para su posterior invocación.

    El usuario introducirá un criterio de búsqueda en el asistente del adaptador y el método Search de la clase Pop3AdapterMetadataSearchHandler.cs se encargará de realizar la búsqueda de metadatos en el sistema destino utilizando dicho criterio.

    La implementación del método Search es muy similar al del método Browse. El método debe devolver como resultado una lista de objetos de tipo MetadataRetrievalNode que el adaptador usará para mostrar las operaciones encontradas al usuario para su posterior consumo.

    En este caso concreto comparamos el criterio de búsqueda introducido por el usuario con la palabra "monitorizacioncorreo" devolviendo, si hay coincidencia, una lista con un nodo que contendrá la operación MonitorizacionCorreo.

    Este es el caso mas simple que nos podemos encontrar, lo ideal es permitir al usuario que introduzca caracteres comodín para que la búsqueda sea mas sencilla para el.

    public MetadataRetrievalNode[] Search(string nodeId
      , string searchCriteria
                 , int maxChildNodes, TimeSpan timeout)
    {
     List<MetadataRetrievalNode> lista = new List<MetadataRetrievalNode>();
           
           if (searchCriteria.ToLower() == "monitorizacioncorreo")
           {
              MetadataRetrievalNode nodoInbound = new MetadataRetrievalNode("MonitorizacionCorreo");
              nodoInbound.DisplayName = "MonitorizacionCorreo";
              nodoInbound.IsOperation = true;
              nodoInbound.Direction = MetadataRetrievalNodeDirections.Inbound;
              lista.Add(nodoInbound);
           }
           return lista.ToArray();
    }

    La clase Pop3AdapterMetadataResolverHandler.cs es la encargada de obtener la definición de las operaciones y tipos complejos de estas operaciones, para que el adaptador pueda generar en base a esta información el contrato del servicio.

    Esta clase tiene dos métodos que debemos desarrollar:

      • ResolveOperationMetadata: este método es el responsable de obtener los metadatos que representan las operaciones ofrecidas por el sistema destino.
      • ResolveTypeMetadata: este método es el responsable de obtener los metadatos de los tipos complejos usados por el sistema destino.

    En el método ResolveOperationMetadata vamos a crear un objeto de tipo ParameterizedOperationMetadata que va a contener la definición de la operación.

    Una vez creado el objeto que contiene la operación, vamos a ir añadiendo a la colección Parameters de este cada uno de los parámetros del la operación.

    public OperationMetadata ResolveOperationMetadata(string operationId, TimeSpan timeout, 
         out TypeMetadataCollection extraTypeMetadataResolved)
    {
      extraTypeMetadataResolved = null;
    
      string nombreOperacion = "MonitorizacionCorreo";
      ParameterizedOperationMetadata operationMetadata = 
      new ParameterizedOperationMetadata(operationId, nombreOperacion);
      operationMetadata.DisplayName = "RecibirNuevoCorreo";
      operationMetadata.OriginalName = "Evento_RecibirNuevoCorreo";
    
      OperationParameter asuntoCorreo = new OperationParameter("asuntoCorreo", 
       OperationParameterDirection.In, 
       QualifiedType.StringType, false);
      asuntoCorreo.Description = "Asunto del correo";
      operationMetadata.Parameters.Add(asuntoCorreo);
    
      OperationParameter cuerpoCorreo = new OperationParameter("cuerpoCorreo", 
         OperationParameterDirection.In, 
         QualifiedType.StringType, false);
      asuntoCorreo.Description = "Contenido del correo";
      operationMetadata.Parameters.Add(cuerpoCorreo);
    
      OperationParameter remitente = new OperationParameter("remitente", 
         OperationParameterDirection.In, 
         QualifiedType.StringType, false);
      asuntoCorreo.Description = "Remitente del correo";
      operationMetadata.Parameters.Add(remitente);
    
      OperationParameter destinatario = new OperationParameter("destinatario", 
          OperationParameterDirection.In, 
          QualifiedType.StringType, false);
      asuntoCorreo.Description = "Destinatario del correo";
      operationMetadata.Parameters.Add(destinatario);
    
    
      operationMetadata.OperationResult = null;
      return operationMetadata;
    }

    En nuestro caso no tenemos ningún tipo complejo por lo tanto no implementaremos el método ResolveTypeMetadata.

    Ejecución de las operaciones

    Ya por último solo nos queda añadir la lógica que monitorizará el correo y enviará los mensajes obtenidos al consumidor del adaptador.

    Para ello vamos a implementar los siguientes métodos:

    • StartListener: lógica de escucha de mensajes asociados a una operación en concreto (action).
    • StopListener: fin de la escucha de mensajes.
    • TryReceive: intenta recibir un mensaje de entrada de la aplicación de negocio destino. Este método devuelve un valor booleano indicando si se ha podido obtener el mensaje del sistema destino o no.
    • WaitForMessage: espera un mensaje de entrada de la aplicación de negocio destino.

    En el método StartListener crearemos una cola de mensajes que contendrán todos los mails del servidor de correo pendientes de notificar al consumidor.

    Para monitorizar el servidor de correo vamos a crear un timer que cada 10 segundos compruebe los mails que hay.

    public void StartListener(string[] actions, TimeSpan timeout)
    {
           colaMensajesEntrada = new Queue<Message>();
           foreach (string action in actions)
           {
              if ("MonitorizacionCorreo".Equals(action))
              {
                 delegado = new TimerCallback(Monitoriza);
                 objThread = new Timer(delegado, null, 1000, 10000);
              }
           }
    }

    En el método StopListener pararemos la monitorización del servidor de correo.

    public void StopListener(TimeSpan timeout)
    {
     objThread.Dispose();
    }

    En el método TryReceive comprobaremos si la cola de mensajes tiene algún correo pendiente de notificar al consumidor del adaptador. La notificación la realizaremos mediante el parámetro de salida message que tiene el propio método. Además debemos de devolver como resultado de la función true en el caso que estemos devolviendo un mensaje o false si no tenemos nada pendiente que notificar del sistema destino.

    public bool TryReceive(TimeSpan timeout, out System.ServiceModel.Channels.Message message, 
       out IInboundReply reply)
    {
           reply = new Pop3AdapterInboundReply();
           message = null;
    
           if (colaMensajesEntrada.Count != 0)
           {
              message = colaMensajesEntrada.Dequeue();
              if (message != null)
              {
                  return true;
              }
            }
            return false;
    }

    El método encargado de monitorizar la entrada de nuevos correos obtendrá la conexión del servidor de correo de las propiedades del adaptador e irá encolando cada uno de los mensajes que reciba.

    private void Monitoriza(Object stateInfo)
    {
      int contadorMail=0;
      Pop3Client email = this.Connection.Conexion;
      while (email.NextEmail(contadorMail))
      {
         string asuntoCorreo = email.Subject;
         string cuerpoCorreo = email.Body;
         string remitente = email.From;
         string destinatario = email.To;
    
         Message msg = CrearMensajeRecepcionPedido(asuntoCorreo,cuerpoCorreo,remitente,destinatario);
         colaMensajesEntrada.Enqueue(msg);
         contadorMail++;
      }
                
    }

    El mensaje que debemos enviar al consumidor del adaptador para notificarle de la llegada de nuevos correos debe cumplir un formato concreto.

    En el siguiente método podemos ver como transformar la información obtenida del servidor de correo en un formato que podamos enviar al consumidor a través del adaptador.

    private Message CrearMensajeRecepcionPedido(string asuntoCorreo, string cuerpoCorreo, 
         string remitente, string destinatario)
    {
      Pop3Adapter adapter = this.Connection.ConnectionFactory.Adapter;
    
      String xmlData = String.Format(@"<RecibirNuevoCorreo xmlns=""{0}""><asuntoCorreo>" + asuntoCorreo 
      + "</asuntoCorreo><cuerpoCorreo>" + cuerpoCorreo + "</cuerpoCorreo><remitente>" + remitente 
      + "</remitente><destinatario>" + destinatario 
      + "</destinatario></RecibirNuevoCorreo>", adapter.ServiceNamespace);
      XmlReader reader = XmlReader.Create(new StringReader(xmlData));
    
      Message msgResultado = Message.CreateMessage(MessageVersion.Default, 
                              "MonitorizacionCorreo", reader);
      return msgResultado;
    }
    Despliegue del adaptador

    Una vez desarrollado el adaptador, debemos firmarlo con un strong name y subirlo al Global Assembly Cache. Debemos copiar la clave pública del assembly una vez que lo hayamos subido al GAC ya que lo necesitaremos luego para registrar el adaptador en el fichero de configuración.

    El adaptador lo podremos registrar tanto en el machine.config en el caso que queramos que el adaptador esté disponible para todos los proyectos de la máquina, o lo podemos registrar en el fichero de configuración del proyecto donde vayamos a consumir el adaptador.

    Nosotros en este ejemplo vamos a registrarlo en el machine.config para que esté accesible desde todos los proyectos.

    • Vamos a registrar el adaptador como un elemento de binding. Para ello en la sección   <system.serviceModel><extensions><bindingElementExtensions> añadiremos el

    siguiente xml:

    <add name="AdapterPOP3" type="ejemplo.adaptadorwcf.Pop3AdapterBindingElementExtensionElement,
    Pop3Adapter, Version=1.0.0.0, 
    Culture=neutral, PublicKeyToken=447f918ac099d73e" />

     

    • También podemos registrar el adaptador como un binding. Para ello añadiremos el siguiente XML en la sección  <system.serviceModel><extensions><bindingExtensions>.:
    <add name="AdapterPOP3Binding" type="ejemplo.adaptadorwcf.Pop3AdapterBindingCollectionElement,
    Pop3Adapter, Version=1.0.0.0, 
    Culture=neutral, PublicKeyToken=447f918ac099d73e" />

    Una vez registrado el adaptador ya podemos utilizarlo en un endpoint de cliente. Para ello en la sección <system.serviceModel><client> vamos a añadir el siguiente XML:

    <endpoint binding="AdapterPOP3Binding" contract="IMetadataExchange"
            name="AdaptadorPOP3" />

    Debemos asegurarnos que el nombre del binding que pongamos en el endpoint sea el mismo que hayamos utilizado al registrar el binding.

    En los próximos días publicaré un post indicando como consumir este adaptador desde una aplicación .NET.

    Adjunto un archivo con el código fuente para que os quede un poco mas claro la implementación del adaptador. Solamente decir que este código ha sido implementado para servir de apoyo al post y en ningún momento está optimizado ni ha sido pensado para poder utilizarse en un entorno real.

    Pop3Adapter.rar

     

    June 02
    Información sobre Windows 7
    Ya empieza a aparecer por la red información sobre la siguiente versión del sistema operativo Windows 7.
     
    Steve Ballmer y Bill Gates resaltaron las características relativas a multi-touch.
     
    Podemos ver características de manejo de imágenes con las manos desde el programa de dibujo paint, un programa que permite tocar el piano directamente en la pantalla, ...
     
     
    En el siguiente video se pueden observar algunas de las características mencionadas anteriormente:
     
     
    A tirar todos el teclado y el ratón.
     
    May 16
    Lanzamiento Blogs de Renacimiento
    A partir de ahora iré posteando en este blog artículos técnicos así como novedades de Biztalk, OSLO, WCF y tecnología .NET en general.
     
    Agradecer a Enrique Blanco si cuya participación estos blogs no se habrían hecho realidad.
     
     
     

     About this blog

     
    About this blog
    Welcome to SharePoint Blogs. Use this space to provide a brief message about this blog or blog authors. To edit this content, select "Edit Page" from the "Site Actions" menu.