[Empleo] Buscamos gente buena en .NET, tanto seniors como juniors

Donde trabajo, estamos en pleno proceso de fichajes para el equipo .net, tanto seniors como juniors con poca o ninguna experiencia profesional. Dejo la propuesta por si alguien no está contento en su trabajo y se quiere venir a un equipo muy joven, internacional y con ganas de hacer las cosas bien. No es consultoria, tenemos producto propio, del cual sacamos releases cada muy poco, a un ritmo bastante frenético, con lo que se puede crecer, y mucho, dentro del equipo.

Dejo la oferta “oficial”, si alguien le interesa, que me escriba a cpsaez@gmail.com y quedamos para hablar, enseñar donde trabajamos y ese tipo de cosas. Es presencial para Madrid, zona Pio XII, bien comunicado, aunque se valoraria el teletrabajo.

Your responsibilities:

Design and develop new features and functionality for high transaction, large scale system

Create and extend public/private facing APIs

Participate in design and code reviews

Identify and address performance bottlenecks in the existing software

Design solutions that are modular, scalable and portable

Design and create unit test cases and make your code work seamlessly in a continuous integration environment

Comply with change control, source control and configuration management tools and practices

Follow and promote software development best practices and maintain the highest quality of delivered software

Provide 3rd line support and troubleshooting when required

 

Your Profile:

Demonstrable talent coding in C# with in real-time, multi-tier, multithreading, back-end systems where high performance and availability are key. (5+ years working experience on .Net technology is a must)

Strong technical background in software design patterns and architecture

Database development and design experience (ideally SQLServer)

Understanding of REST based architecture as well as SOAP/XML

Knowledge using version control systems (ideally TFS)

A bachelor’s degree in a traditional science subject, ideally computer science, engineering, or information systems

Ideally some experience in gambling applications

 

The ideal candidate would also have:

Knowledge of Web technologies and internet protocols (XML, HTTP, TCP/IP, ASP.NET)

Knowledge of WPF/HTML5/Javascript

Strong understanding of WCF and Entity framework

Good level in futbolin is strongly recommended 😉

SCRUM

[Empleo] Buscamos gente buena en .NET

Donde trabajo, estamos en pleno proceso de fichajes de cracks .net, se paga muy bien. Dejo la propuesta por si alguien no está contento en su trabajo y se quiere venir a un equipo muy joven, internacional y con ganas de hacer las cosas bien. No es consultoria, tenemos producto propio, del cual sacamos releases cada muy poco, con lo que se puede crecer, y mucho, dentro del equipo.

Dejo la oferta “oficial”, si alguien le interesa, que me escriba a cpsaez@gmail.com y quedamos para hablar, enseñar donde trabajamos y ese tipo de cosas.

Your
responsibilities:

Design and develop new features and functionality for
high transaction, large scale system

Create and extend public/private facing APIs

Participate in design and code reviews

Identify and address performance bottlenecks in the
existing software

Design solutions that are modular, scalable and
portable

Design and create unit test cases and make your code
work seamlessly in a continuous integration environment

Comply with change control, source control and
configuration management tools and practices

Follow and promote software development best practices
and maintain the highest quality of delivered software

Provide 3rd line support and troubleshooting when
required

 

Your
Profile:

Demonstrable talent coding in C# with in real-time,
multi-tier, multithreading, back-end systems where high performance and
availability are key. (5+ years working experience on .Net technology is a
must)

Strong technical background in software design
patterns and architecture

Database development and design experience (ideally
SQLServer)

Understanding of REST based architecture as well as
SOAP/XML

Knowledge using version control systems (ideally TFS)

A bachelor’s degree in a traditional science subject,
ideally computer science, engineering, or information systems

Ideally some experience in gambling applications

Fluency in English

 

The ideal candidate would also have:

Knowledge of Web technologies and internet protocols
(XML, HTTP, TCP/IP, ASP.NET)

Knowledge of WPF/HTML5/Javascript

Strong understanding of WCF and Entity framework

Good level in futbolin is strongly recommended 😉

SCRUM

 

Borrador del protocolo HTTP2

Tal como comento en Barrapunto, han publicado un nuevo borrador del protocolo HTTP2. Según el borrador, Http2 provee una forma eficiente de serializacion de la semantica HTTP, será capaz de multiplexar diferentes peticiones HTTP sobre una misma conexión y de forma concurrente mediante el uso de streams con control de flujo y priorización y, además, soportará server push, es decir, poder forzar que el servidor mande datos al browser o cliente sin que este los pida por encuesta, tal como se hace ahora. Otra de las novedades es que http y https podrá compartir puerto ya que sobre la misma URI podrán ser mandados diferentes streams. Como nota curiosa, dicho protocolo nos permite hacer ping directamente al servidor web. Si te interesa saber más, recomiendo la lectura directamente del borrador.

Todo esto realmente no es “nuevo” ya que desde hace tiempo existen dos propuestas sobre la mesa, SPDY de Google y S+M (Speed+Mobility) de Microsoft. La mayor diferencia es que el server push (enviar un mensaje del servidor al browser, adios javascript en background para actualizar datos en tiempo real), en el modelo del borrador y SPDY esta totalmente acoplado, pero en el de Microsoft es una extensión opcional para evitar, sobre todo, gastos de bateria y consumo de red en dispositivos móviles y redes “metered”.

No sabemos si está tecnología se acabará usando o si HTTP 1.1 será tan reticente a cambiar como IPv4, pero creo que no hay que perder de vista estas propuestas ya que, por lo que parece, IE 11 va a soportar SPDY (Chrome y Firefox ya lo hacen más o menos). Si te puede el ansia y quieres probarlo ya existe un modulo para Apache (que no he probado) pero para IIS, nada.

NopCommerce 3.0 beta

NopCommerce es una aplicación opensource (licencia NPL+) para montarte tu tienda Online bastante completa y con una comunidad alrededor bastante fuerte. Como “caracteristica” es que funciona en .NET. Llevo mirando el código fuente y haciendo modificaciones desde la versión 2.10 y la verdad que el trabajo que esta realizando esta gente es bastante sorprendente desde el punto de vista de arquitectura, complejidad y buen código y por tanto, merece la pena echarle un vistazo si te gusta programar en C#. IoC con Autofac, plugins autoinstalables, EF 5.0, MVC, diferentes views para dispositivos moviles, SEO friendly y ahora, con la nueva versión, multi-store. Vamos, que se puede aprender un monton. Este es el anuncio de la release

P2P en Web, conceptos básicos

Últimamente esta muy en boca las nuevas características de conexión p2p entre navegadores. Es decir, un browser se comunica directamente con otro, sin necesidad de servidores que intervengan durante todo el ciclo de la comunicación, solo para determinadas tareas, normalmente el inicio del dialogo entre los navegadores. Dichas características se están empleando sobre todo para realizar streaming de contenido multimedia entre navegadores. ¿Pero como es posible dicha mágia?.

Para establecer una conexión de un punto a otro, en redes IP, necesitamos una dirección, un puerto, un protocolo (TCP o UDP normalmente) y dos participantes, el iniciador o cliente y el que escucha (listener). El listener estará escuchando por un puerto y cuando el iniciador se conecte a el, empezara una serie de intercambios de información entre el iniciador y el listener. Esta es la teoría conocida por todos en conexiones punto a punto. ¿Cual es el problema?, que Internet hace tiempo que dejo de ser una topología de IPs donde todas se veían entre todas.

 

 

Internet clásico

image

A día de hoy la arquitectura predominante, por motivos de seguridad y de economía de direcciónes IP, son las subredes detras de routers haciendo NAT.

 

imageEs decir, que una conexión p2p desde el cliente 1 al cliente 3 que esté detras de un NAT, es complicado a no ser que abramos puertos en el NAT que apunten directamente al cliente, haciendo la traslación de red.

 

 

image  En la anterior figura, si un iniciador quiere conectarse al cliente 1, puerto 80, tendrá que conectarse en realidad a la IP 80.80.80.43, tambien llamada IP pública ya que el router, en su configuración NAT, todo que llege al puerto 80 por la IP pública lo enrutará a la IP del cliente 1, al puerto 80 u otro puerto.

Entonces, en una arquitectura así, ¿como es posible realizar p2p?. Si alguien ha trasteado con los tipicos clientes p2p, como torrent o emule, para tener la máxima velocidad habrán tenido que “abrir los puertos” en el router, es decir, configurar el NAT del router. Esta solución es un poco inviable ya que por cada aplicación que quiera usar las características p2p, deberíamos abrir un puerto en el router con los consiguientes problemas de administración de la red. Existen otras soluciónes más dinámicas y normalmente se trata de “engañar” al router. Para engañar al router se suelen seguir varias estrategias en función de si uno o los dos clientes están detras de un NAT.

 

 

 

Un cliente con IP pública y otro detras de NAT.

image

En este caso un dispositivo conectado a internet con una IP pública intenta establecer una conexión p2p con un dispositivo detras de un NAT y no puede ya que la IP privada no es accesible desde internet. Como no queremos abrir puertos en el NAT, se suele recurrir a una conexión pasiva con ayuda de un tercero.

 

 image

En el dibujo se puede ver como el dispositivo recurre a ayuda de un tercer, un servidor, para anunciar su disponibilidad de servicio, manteniendo una conexión con el servidor.

Cuando el dispositivo cliente o iniciador quiere conectarse, lanza la petición al servidor y el servidor comunica al listener que abra una conexión con el cliente. En el momento que el cliente detecta dicha conexión de entrada, empieza el intercambio de información como si la conexión la hubiese abierto el.

Dos clientes detras de NAT

Este es el escenario más habitual y más complejo de resolver, aunque a día de hoy ya con exito.

image

Dos dispositivos detras de NAT, con lo cual ninguno puede abrir una conexión con el otro. En este caso vamos a empezar en como se resuelve cuando queremos usar el protocolo UDP, el cual no está orientado a conexión, no garantiza la recepción ni el orden de llegada de los paquetes y es mas rápido, por lo tanto candidato ideal para hacer streaming donde no importa perder paquetes ni el orden, ya que como mucho tendremos peor calidad, pero seguiremos manteniendo la comunicación en tiempo real y con baja latencia.

UDP Hole Punching

Esta palabreja (UDP Hole Punching) nombra una técnica donde los dos clientes mantienen una conexión activa UDP anunciándose en un servidor Rendezvous o de citas. En el momento que un dispositivo quiere abrir una conexión p2p, preguntará al servidor Rendezvous su IP pública y empezará a inyectar paquetes por dicha conexión suplantando al servidor Rendezvous.

imageLa técnica tiene su intriga pero puede verse más información en esta url donde describen los pasos para saber si los dos dispositivos están detras del mismo NAT o no y diferentes tecnicas.

 http://www.brynosaurus.com/pub/net/p2pnat/

 

begin{figure*}centerline{epsfig{file=diffnat.eps, scale=0.34}}end{figure*}

 

 

 

 

 

 

 

Servidor STUN y STUNT

Un servidor STUN (Simple traversal of User Datagram Protocol) es simplemente un servidor rendezvous descrito en el punto anterior, pero estandarizado bajo la norma RFC 3489. STUNT, con T al final, es lo mismo pero aceptando el protocolo TCP, pero no suele ser muy habitual.

 

Por tanto, y volviendo al tema original, esta claro que si queremos conseguir una comunicación de browser a brwoser, necesitaremos un servidor STUN, entre otras cosas.

Y para que sirve todo esto

Hoy en dia existe una corriente muy fuerte para llevar el p2p al navegador y ya se van viendo proyectos donde usan dicha técnica para poder comunicarse, como pro ejemplo WebRTC

http://www.webrtc.org/

Este proyecto está basado sobre todo en la transmisión multimedia, con lo que dentro de su arquitectura ya contempla diferentes codecs de audio y video.

 

Si nos fijamos en la capa de transporte, sección p2p, veremos STUN, además de una extensión llamada TURN y ICE, un protocolo de agentes que se apoyan en STUN/TURN.

 

Espero que con esta pequeña introducción ya no sea tan mágico como funciona las conexiones p2p hoy en día.

Integración continua más alla de TFS

Integración continua es tener un sitio donde, periódicamente, tus proyectos se compilen y se lancen los tests para que el código fuente este sano, es decir, que cualquiera que se lo baje sepa que esta funcionando y nos olvidemos de “en mi máquina funciona”.

 

En el  mundo .NET es muy habitual tener un TFS y las builds configuradas dentro del mismo, pero si no tenemos un TFS por lo que sea, podemos usar HUDSON para montarnos nuestro entorno de CI.

 

Hudson es un veterano del mundo UNIX/Linux que ha sido portado a Windows en forma de ejecutable stand-alone, para lanzarlo manualmente cuando lo necesitemos, o como servicio de Windows donde está disponible continuamente, ademas de poseer un montón de módulos y plugins para conectarlo con cualquier repositorio que se te ocurra y realice una compilación de casi cualquier lenguaje. Todo ello manejado desde una simple interface web.

 

¿Y como lo instalamos?

Hudson está echo en JAVA así que lo primero que toca es bajarse la ultima máquina virtual si no la tienes ya e instalarla. Después nos bajamos el último war de la web de Hudson  y lo descomprimimos en una carpeta donde tengamos mucho espacio ya que por defecto, las builds se ejecutaran dentro del mismo (se puede configurar). Si lo piensas montar como servicio, déjalo en el escritorio, abre una consola (cmd) y ejecuta

 

java –jar hudson.war.

 

En estos momentos Hudson lanzará un sencillo servidor web en el puerto 8080, entrando con nuestro navegador favorito a http://localhost:8080 nos aparecerá un menú tal que así:

 

image

Pinchando en instalarlo como servicio, ahora sí, tendremos que especificar una carpeta donde quedará instalado permanentemente

 

image

Una vez instalado el mismo nos da la opción de parar la instancia actual de Hudson, que recordemos es plenamente funcional, y logarnos en nuestra nueva instalación de Hudson como servicio.

image

 

Si nos vamos a los servicios del sistema, veremos a la nueva criatura

image

Yo recomiendo dejarlo como arranque automático.

image

Si queremos que Hudson escuche en otro puerto diferente a 8080, nos tenemos que ir a la carpeta de instalación y cambiar dentro del fichero Hudson.xml la siguiente linea:

<arguments>-Xrs -Xmx256m -Dhudson.lifecycle=hudson.lifecycle.WindowsServiceLifecycle -jar “%BASE%hudson.war” –httpPort=8050</arguments>

 

Cambiando el puerto al 8050 por ejemplo

 

Hudson habla con nuestro .NET

Para configurar que Hudson pueda compilar .NET, tenemos que activar el plugin correspondiente, no tenemos que instalar nada ya que se baja automáticamente.

Nos vamos al panel de control de Hudson

http://localhost:8080

Pulsamos en Manage Hudson y en Manage Plugins

 

image

Buscamos el MSBuild Plugin y el MSTest plugins (si queremos tener en cuenta tests unitarios), los marcamos y pulsamos en instalar.

 

Una vez instalados los plugis debería quedar el listado de Installed tal que así:

 

image

Hay un montón de plugins así que si os parece util la herramienta, conviene darle un vistazo a la lista de disponibles, sobre todo si usamos repositorios como TFS o Sourcesafe, que no vienen activos por defecto.

Una vez tenemos los plugins listos, tenemos que configurar la compilación con MSBuild (el plugin que acabamos de instalar), con lo que nos vamos a configure system

 

image

donde veremos una sección de MSBuild. Aquí hay que ponerle el path al ejecutbale MSBuild.exe, en mi caso:

C:WindowsMicrosoft.NETFramework64v4.0.30319MSbuild.exe

 

y darle un nombre identificativo.

 

Podemos configurar más de un entorno de compilación, por si queremos usar .NET 2.0 o .NET 4.0 indistintamente

 

También conviene darle un repaso a todas las opciones pero una muy util es las configuraciones por mail (al final del todo). Si cuando acabe una build y esta falla, queremos avisar a quien a enviado la build, conviene configurar el Email suffix escribiendo por ejemplo “@midominio.com”. Si bob hace un checkin al código y rompe la build, Hudson enviará un correo a bob@midominio.com

Cuando terminemos de configurar todo no hay que olvidar de darle al boton save al final de la página.

 

Creando un nuevo trabajo:

Vamos a ordenar a nuestro nuevo mayordomo una nueva tarea, que es la compilación de un proyecto que tenemos en el SVN cada vez que alguien haga checkin y suba nuevos cambios.

 

Navegamos hasta https://localhost:8080 ( o la ip del servidor) y pulsamos en New Job

Damos un nombre al trabajo, por ejemplo: Branch-8876 o “mi superbuild”  (es solo una descripción) pulsamos en Build free-style software project. (podemos clonar un trabajo existente, muy util si cambiamos solo la rama donde esta nuestro proyecto en el repositorio).

Pulsamos en ok y en la siguiente página tendremos que configurar las propiedades de nuestra tarea. Yo recomiendo modificar las siguientes:

-Discard old builds para tener solo la compilación mas reciente y no usar espacio en disco duro de forma innecesaria

-Source code management: En mi caso va a acceder a una rama de SVN, con lo que poniendo la dirección http del servidor de source safe bastaría, ejemplo:

 

https://ip/svn/main/……

 

Y como quiero integración continua, usaré la estrategia Use svn update as much as possible y Clean checkout folders and then checkout para que cada vez que se lance una compilación me baje todo el código de nuevo.

 

En los disparadores de la build, si queremos que se ejecute en cada checkin, hay que elegir Poll SCM y en el schedule la siguiente opción “* * * * *”. Si quisiéramos lanzarla cada día a las 2 y media de la noche, escribiríamos “2 30 * * *” por ejemplo.

 

En el apartado build debemos elegir el que configuramos previamente y como fichero de build, elegiremos nuestro fichero sln que contiene la solución. Hudson lanzará “MSBuild fichero elegido” y entenderá el output del mismo, indicando si ha habido algún error o ha ido todo bien.

 

Cuando terminemos no olvidemos pulsar el botón save.

 

Y ya está, en la pantalla principal podremos ver todas las builds que están ejecutándose y si alguna ha ido mal con su icono rojo correspondiente ( en esta nueva versión si va todo bien aparece un sol y si va mal un icono de tormenta)

 

Image:Hudson-working.png

 

Ah, decir que es una aplicación inmensa y que tiene soporte de esclavos para distribuir los diferentes builds en escenarios complejos.

 

Ya no tenemos excusa para no montar un entorno de integración continua en nuestro entorno en una tarde y empezar a usarlo desde el primer día. Con una máquina modesta nos servirá para lanzar una build cada cinco minutos y dejar de esperar ese TFS que nunca llega por falta de recursos, máquinas disponibles o pánico a la nube del nuevo cloud TFS.

 

[Trabajo] Microsoft Dynamic en Irlanda

Hola.

Aqui donde estoy trabajando, en Irlanda, están DESESPERADOS por encontrar gente que controle de Microsoft Dynamics. Si piensas que tu ingles es regulero, no importa, son comprensivos. Si te interesa trabajar en una zona tranquila, de 9:00 a  17:30 en un buen ambiente y controlas de Dynamic tanto version 4 como 2011 y te apetece venirte para Irlanda, contacta conmigo en cpsaez@gmail.com.

Saludos.

 

AppDomain.CurrentDomain.UnhandledException–Ese gran desconocido

Normalmente, cuando hacemos una aplicación de escritorio o servicio de Windows, intentamos, mediante try – catch de los métodos principales, evitar fallos catastróficos. Pero lo que se suele desconocer es que hay una última barrera de defensa en esta propiedad llamada UnhandledException de nuestro app domain.

En este ejemplo estoy blindado la ejecución de un servicio. Si algo falla que no esté controlado, antes de que se pare el servicio, nuestro código del segundo método se ejecutará sí o sí:

   1:          static void Main()
   2:          {
   3:              ServiceBase[] ServicesToRun;
   4:   
   5:              ServicesToRun = new ServiceBase[] { new BatcherService() };
   6:              AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
   7:              ServiceBase.Run(ServicesToRun);
   8:          }
   9:   
  10:          static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
  11:          {
  12:              ...
  13:          }

 

Ideal para esos logs de ultima hora que nos pueden servir para ver por qué realmente ha fallado. En el argumento e tenemos toda la información de la excepción tal como vemos en esta captura de la ayuda contextual.

image

Esto también sirve en aplicaciones WPF, Winforms etc… Espero que a alguien le sea útil.

Nota: Es conveniente que el código que metamos aquí sea ultra ligero para evitar problemas como matar el proceso a mano porque el servidor sql encargado de guardar los logs da time – out por ejemplo 😉

 

Update: Si queremos la aplicación termine evitando las molestas ventanas de error, debemos usar el método Enviroment.Exit()

 

   1:          static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
   2:          {
   3:              try
   4:              {
   5:                  Exception ex = (Exception)e.ExceptionObject;
   6:                  // logeamos
   7:              }
   8:              finally
   9:              {
  10:                  Environment.Exit(…);
  11:              }
  12:          }

Con ello, terminaremos la ejecución, dicho de forma rápida, antes de que la excepción llegue hasta el S.O y saqué dichas ventanas.

Contexts de EF e Interceptors de Unity, que pasa con las excepciones?

Todo el mundo sabe que es un contexto de entity framework… ok

http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.aspx

 

Todo el mundo sabe que son los interceptors de Unity… ¿ok? (Es un mecanismo para poder lanzar código antes y después de que un método se ejecute)

http://msdn.microsoft.com/en-us/library/ff647107.aspx

 

Si interceptamos un contexto con Unity tal que así

 

   1:              container.RegisterType<MyEntities, MyEntities>(
   2:                  "auditable",
   3:                  new PerThreadLifetimeManager(),
   4:                  new InjectionConstructor(),
   5:                  new Interceptor<VirtualMethodInterceptor>(),
   6:                  new InterceptionBehavior<AuditableContextBehavior>());

 

(MyEntities es algo que hereda de ObjectContext y tiene un método llamado SaveChanges que vamos a auditar.(

 

Y AuditableContextBehavior es algo tal que así:

 

   1:   public class AuditableContextBehavior : Microsoft.Practices.Unity.InterceptionExtension.IInterceptionBehavior
   2:      {
   3:          /// <summary>
   4:          /// Gets a value indicating whether this behavior will actually do anything when invoked.
   5:          /// </summary>
   6:          public bool WillExecute
   7:          {
   8:              get
   9:              {
  10:                  return true;
  11:              }
  12:          }
  13:   
  14:          /// <summary>
  15:          /// Returns the interfaces required by the behavior for the objects it intercepts.
  16:          /// </summary>
  17:          /// <returns>
  18:          /// The required interfaces.
  19:          /// </returns>
  20:          public IEnumerable<Type> GetRequiredInterfaces()
  21:          {
  22:              return Type.EmptyTypes;
  23:          }
  24:   
  25:          /// <summary>
  26:          /// Implement this method to execute your behavior processing.
  27:          /// </summary>
  28:          /// <param name="input">Inputs to the current call to the target.</param>
  29:          /// <param name="getNext">Delegate to execute to get the next delegate in the behavior chain.</param>
  30:          /// <returns>
  31:          /// Return value from the target.
  32:          /// </returns>
  33:          public Microsoft.Practices.Unity.InterceptionExtension.IMethodReturn Invoke(Microsoft.Practices.Unity.InterceptionExtension.IMethodInvocation input, Microsoft.Practices.Unity.InterceptionExtension.GetNextInterceptionBehaviorDelegate getNext)
  34:          {
  35:              if (input == null)
  36:              {
  37:                  throw new ArgumentNullException("input");
  38:              }
  39:   
  40:              if (getNext == null)
  41:              {
  42:                  throw new ArgumentNullException("getNext");
  43:              }
  44:   
  45:              // Audit the entities, the new entities will be delayed.
  46:              IEnumerable<ObjectStateEntry> entriesDelayed = this.PreSaveChanges(input);
  47:   
  48:              // get next handler
  49:              IMethodReturn message = getNext()(input, getNext);
  50:   
  51:                  // Audit the delayed entities
  52:              this.PostSaveChanges(entriesDelayed);
  53:   
  54:              // return the result of the interceptors
  55:              return message;
  56:          }
  57:   
  58:          /// <summary>
  59:          /// Execute code after the method
  60:          /// </summary>
  61:          /// <param name="input">The input.</param>
  62:          /// <returns>Entities delayed to audit</returns>
  63:          [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "We can never stop the execution for a error in this method")]
  64:          private IEnumerable<ObjectStateEntry> PreSaveChanges(Microsoft.Practices.Unity.InterceptionExtension.IMethodInvocation input)
  65:          {
  66:              IEnumerable<ObjectStateEntry> entriesToAdd = null;
  67:   
  68:              try
  69:              {
  70:                  if (input.MethodBase.Name == "SaveChanges")
  71:                  {
  72:                     ...
  73:                      }
  74:                  }
  75:   
  76:   
  77:              }
  78:              catch (Exception ex)
  79:              {
  80:              ...
  81:              }
  82:   
  83:              return entriesToAdd;
  84:          }
  85:   
  86:          /// <summary>
  87:          /// Execute code after the method SaveChanges.
  88:          /// </summary>
  89:          /// <param name="entriesToAdd">The entries to add.</param>
  90:          [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "We can never stop the execution for a error in this method")]
  91:          private void PostSaveChanges(IEnumerable<ObjectStateEntry> entriesToAdd)
  92:          {
  93:              // the entries marked to added must be logged at the end of the method to log the state
  94:              if (entriesToAdd != null && entriesToAdd.Count() > 0)
  95:              {
  96:               ...
  97:              }
  98:          }
  99:      }

 

¿Que ocurre cuando el método interceptado lanza una excepción? ¿Se para todo?

 

Pues no, si el método getNext devuelve una excepción, PostSaveChanges tambien se ejecutará y en mi caso no tiene sentido. Para evitar eso hay que hacer una comprobación tal que así (en amarillo)

 

   1:             if (input == null)
   2:              {
   3:                  throw new ArgumentNullException("input");
   4:              }
   5:   
   6:              if (getNext == null)
   7:              {
   8:                  throw new ArgumentNullException("getNext");
   9:              }
  10:   
  11:              // Audit the entities, the new entities will be delayed.
  12:              IEnumerable<ObjectStateEntry> entriesDelayed = this.PreSaveChanges(input);
  13:   
  14:              // get next handler
  15:              IMethodReturn message = getNext()(input, getNext);
  16:   
  17:              // if an exception is produced in the SaveChanges method of the context, it doesn't make sense save the state of the entities
  18:              if (message.Exception != null)
  19:              {
  20:                  // Audit the delayed entities
  21:                  this.PostSaveChanges(entriesDelayed);
  22:              }
  23:   
  24:              // return the result of the interceptors
  25:              return message;

 

Tenerlo en cuenta porque la inercia es usar el result para logear o lo que sea pensando que siempre está disponible y no, en caso de excepción, la vida sigue en el interceptor y luego, dentro del método interceptado, es cuando saltará la excepción, nunca antes