Error al recuperar DateTime: nos devuelve un día menos

Algo que puede producirte un gran quebradero de cabeza tiene que ver con los objetos tipo DateTime, con la zona horaria y con los objetos Retrieve que ejecutes desde tu código C#.

Resulta que existe un problema en CRM que por el cual al hacer una petición de un objeto DateTime para posteriormente ser utilizado en código, la fecha que recibimos es distinta a la que hay en el CRM guardada. Cuando pidamos una fecha veremos que nos devuelve un día menos del que hay en CRM guardado. Esto podrá variar en función de la hora local que tengamos configurada en el servidor y la hora local del cliente que realice la petición.

Vamos a ver un ejemplo de código que selecciona un contacto de nuestro CRM y nos devuelve la fecha de nacimiento:

Para la prueba he creado un contacto con mi nombre y fecha de nacimiento de “21/04/1959”.

Fecha devuelta equivale a un día menos

Fecha devuelta equivale a un día menos

Nota: en el CRM, la fecha que se ve es “04/21/1959”. Esto tiene que ver con la configuración de mi usuario que tiene por defecto idioma ingles y formato de fecha de USA, sin embargo esta fecha es exactamente la misma que “21/04/1959”.

Como vemos en la imagen, la fecha obtenida tiene un día menos que la fecha guardada en el CRM. ¿Como solucionamos esto?. Bueno, seguramente existan muchos métodos que tienen que ver con la configuración horaria de los DateTimes devueltos por el OrganizationService u otros parámetros. La forma fácil y que yo utilizo siempre desde que la aprendí es la siguiente:

Una vez tengamos la fecha en un String, le concatenamos una “Z” al final del mismo, y volvemos a convertir a DateTime. ¿Y esto por qué es así? bueno por lo que he podido leer, al incluir una “Z” al final de una hora equivale a convertirla a hora local UTC. La Z viene de ZULU, utilizado por la marina estadounidense.

Con todo esto, nuestro código debería quedar del siguiente modo:

Con este cambio, el resultado que obtenemos pasará a ser el siguiente:

Fecha devuelta correcta

Fecha devuelta correcta

 

Cómo saber a que DLL corresponde un Hosted Control

Existe un método muy sencillo y que no requiere de ninguna instalación especial para conocer el namespace y el tipo de cada uno de los hosted controls que hay definidos en la configuración de USD en CRM.

Muchas veces necesitaremos en nuestro código hacer referencia a uno de estos objetos especiales para modificar algún atributo o para captar un evento. Estos ojbetos especiales son los que aparecen listados en la configuración de USD cuando creamos un nuevo hosted control, en el campo USD Component Type.

Tipos de hosted controls predefinidos

Tipos de hosted controls predefinidos

Como ya hemos visto en otras entradas a veces necesitamos hacer referencia a alguno de estos objetos (en esta entrada al Debugger por ejemplo). Para capturar la instancia del objeto necesitamos dos cosas: el nombre del hosted control y el tipo. El nombre es el que elijamos en la configuración del USD en CRM. El tipo es en principio desconocido.

Bien pues vamos a ver cómo consultar el tipo de la manera más sencilla. Lo primero de todo es irnos a la configuración del USD en CRM y crear un nuevo hosted control (como en la imagen de arriba).

Luego en el desplegable de USD Component Type seleccionamos el objeto que queremos averiguar. En nuestro caso queremos averiguar por ejemplo la DLL y el tipo del objeto Debugger:

Selección de Hosted Control Debugger

Selección de Hosted Control Debugger

A continuación lo único que deberemos hacer es volver a pinchar sobre el campo USD Component Type y seleccionar la opción USD Hosted Control. Como veremos cuando hagamos esto, aparecerán debajo dos campos: Assembly URI y Assembly Type. Además aparecerán rellenos con el tipo del objeto que hayamos seleccionado en primer lugar (en nuestro caso el objeto Debugger).

Selección de USD Hosted Control

Selección de USD Hosted Control

Una vez que conocemos el tipo, en nuestro Custom Hosted Control podremos obtener la instancia del objeto del siguiente modo:

Con esto ya somos capaces de modificar cualquier atributo de la instancia cargada en nuestro USD de este objeto.

El motivo por el que ocurre esto es que al seleccionar cualquier tipo especial en el campo USD Component Type los campos Assembly URI y Assembly Type se auto rellenan y además se ocultan. El fallo está en que al cambiar el desplegable no se resetean estos valores.

Option Set: Obtener Label/Etiqueta en C#

Obtener la etiqueta de un Option Set de una entidad de CRM por código C# no es trivial. Para ello podemos utilizar dos métodos como veremos a continuación: descargar el meta o utilizar la propiedad formattedvalues

Lo que en otros lenguajes y entornos es conocido como ComboBox en CRM se le denomina Option Set. Se trataría de un desplegable de opciones disponibles que puede adoptar como valor un campo de un formulario.

La estructura de este tipo de campo constaría de una lista de parejas denominadas Label y Value. El Label correspondería a la etiqueta visible que se muestra en el formulario. Esta etiqueta será  con la que el usuario de CRM deberá interactuar y en general será de tipo String.

Además, por detrás, tenemos el Value. Esta variable identifica de modo único cada una de las opciones disponibles en el Option Set. No podrá haber dos Values iguales en el mismo Option Set puesto que este valor es el que se utiliza como clave primaria para la lógica que corre por detrás.

Campo Option Set CRM

Campo Option Set CRM

Por defecto CRM insertará los Values siguiendo una serie de reglas internas como que el prefijo sea único para cada solución. En general este dato no deberá preocuparnos y si nuestro trabajo termina en crear el formulario nos dará igual el valor de este campo aunque siempre podremos actualizarlo al valor que deseemos -cumpliendo que este valor entero sea único-.

Una aplicación en donde deberíamos cambiar los Values generados por CRM sería por ejemplo un listado de prefijos de teléfonos. En este caso sí que convendría actualizar cada item con su determinado valor (España – 34, Italia – 39, etc). En general se deberá de crear la correspondencia de Label – Value en función del alcance de nuestro desarrollo.

El motivo por el cual es bueno realizar esta correspondencia es que si accedemos mediante C# al valor de un Option Set obtendremos por defecto el Value, y no el Label. Para muchas aplicaciones con el Value será suficiente, pero para otras necesitaremos también conocer el Label del campo. Para acceder a este valor normalmente se utilizan dos métodos

El primero -y más lento- sería descargar previamente el Option Set que se desea analizar y guardarlo en un diccionario. A continuación se accederá al Value del campo en cuestión y se cruzará el valor obtenido con el diccionario obteniendo el Label correspondiente.

 

La segunda opción -más rápida- sería obtener directamente el Label del Option Set mediante la propiedad FormattedValues.

Ambas tienen sus pros y sus contras y en función de la aplicación que se esté desarrollando el programador deberá escoger cual le conviene más.

Las librerías necesarias para los objetos mostrados en los ejemplos se encuentran en la SDK 2015 de CRM. En particular hemos utilizado: