jueves, 20 de agosto de 2009

Búsqueda rápida de registros inactivos

Al realizar una búsqueda rápida en MSCRM, solo aparecen aquellos registros que estén activos.
Por ejemplo:


Para habilitar que la "Búsqueda rápida" de una entidad busque también por registros inactivos, se debe hacer lo siguiente (el ejemplo en con las Cuentas):
1) Exportar las personalizaciones de la entidad.
2) Quitar el siguiente texto de la vista de "Búsqueda rápida de cuentas activas" (dentro de la "SavedQuery"):





3) Volver a importar la personalización y publicar.

Tener den cuenta que esta modificación es una modificación no soportada.

martes, 18 de agosto de 2009

Direcciones de envío de los Emails

Muchas veces enviamos emails desde el propio MSCRM (no mediante el Outlook), que como saben son enviados a la dirección que tenga predefinida el "Customer" o Usuario, como "emailaddress1".
Ahora bien, una vez que se pincha en "enviar" desde MSCRM, se marca como para enviar, pero es posible que quede en estado "pendiente", hasta que el proceso asíncrono de EmailRouter haga efectivamente el envío, o que se quede pendiente de sincronizar con un cliente de Outlook.
Entre un momento y otro, puede pasar un tiempo, y es posible que por ejemplo el email de la Cuenta haya sido modificado.
Entonces, ¿a que dirección se enviará el Email?, para esto habría dos opciones:
1) Que se envie a la dirección que tenía al momento de crear el email.
2) Que se envíe a la dirección que tiene al momento efectivo de realizar el envío.

Bueno, la respuesta es que antes del Rollup 4 de MSCRM 4.0, ocurría lo primero, y a partir del Rollup 4, ocurre lo segundo.

¿Como funciona entonces?
Al crear un Email, se crea un registro en la tabla "ActivityParty", con el campo "addressused" con el valor que tenga en ese momento.
Esto se puede comprobar fácilmente realizando la siguiente consulta:

SELECT addressused FROM FilteredActivityParty

Una vez que se actualiza el Email del registro en cuestión (por ejemplo una Cuenta), se actualiza tambien en cascada en la tabla "ActivityParty" en campo "addressused".

Los Rollups, muchas veces resulven temas, añaden funcionalidad y otras tantas cambian cosas, que pueden no estar documentadas, por esto mucho cuidado al instalar Rollups y probar todos los desarrollos previamente en un entorno que no sea de producción para así evitarse posibles dolores de cabeza.

domingo, 16 de agosto de 2009

Valores de los "Picklists" desde SQL Server

A veces tenemos la intención de acceder a los metadatos de CRM, pero simplemente para identificar los valores posibles de un campo de tipo "Picklist" o desplegable.
Esta información además de poder accederse con la propia SDK a través de los métodos disponibles de el MetadataService, también pueden ser accedidos de forma mas rápida y sencilla desde el propio SQL Server.
La consulta es muy simple (sólo habría que modificar los campos del "WHERE"):


SELECT AttributeValue, Value
FROM StringMap
WHERE AttributeName='accountcategorycode' AND ObjectTypeCode=1
ORDER BY DisplayOrder

viernes, 14 de agosto de 2009

Control de Errores en llamadas a la SDK

Muchas veces al hacer una llamada a un método de un web service de CRM, nos devuelve un error, que si lo recogemos como la simple "Exception", no nos dice exactamente el error que devuelve el CRM, sino un simple error genérico de web service.
Se debe capturar en el "catch" el error System.Web.Services.Protocols.SoapException, y con eso, acceder a "soexp.Detail.InnerText".

Para capturar correctamente los errores devueltos por el CRM, se debe de hacer de la siguiente forma:


try
{
Guid guidAccount=service.Create(nuevacuenta);
}
catch (System.Web.Services.Protocols.SoapException soexp)
{
Console.WriteLine("La descripción del error soap es:" + soexp.Detail.InnerText);
throw soexp;
}
catch (Exception ex)
{
Console.WriteLine("La descripción del error es:" + ex.Message);
throw ex;
}

jueves, 13 de agosto de 2009

"Soportado" vs "No Soportado"

Muchas veces, nos surge la idea de hacer cosas que el CRM de forma natural no lo hace, o que lo hace de una manera que puede no servirnos, ya sea por la velocidad, o que por el propio funcionamiento del CRM no encaja con lo que quiere el cliente.
Para esto se debe hacer algun desarrollo adicional para que cubra dicha necesidad.
Estos desarrollos o extensiones puedes hacerse de una forma "soportada" o de una forma "no soportada" por Microsoft.
Las personalizaciones "no suportadas" son las siguientes:

  • Modificar o añadir cualquier fichero del directorio virtual de CRM o del directorio de instalación del CRM.

  • Modificaciones en el sitio virtual del CRM.

  • Cualquier modificación en la base de datos SQL Server (tablas, vistas, procedimientos almacenados, etc), salvo la actualización o creación de índices.

  • Referenciar directamente a las DLLs del CRM.

  • Reutilización de los controles de usuario propios del CRM.

  • Utilización de javascripts propios del CRM.

  • Hacer personalizaciones fuera de las herramientas de personalización del CRM.

  • La utilización de "HttpModules" para inyectar HTML dinámico en los formularios de CRM.


  • Ahora bien, ¿qué consecuencias podría tener hacer cosas "no soportadas"?. Las consecuencias podrían ser las siguientes:

  • Que alguna actualización de CRM pueda cambiar el funcionamiento y hacer que nuestro desarrollo no funcione.

  • Se podría perder el soporte de Microsoft, ya que se han realizado cosas "no soportadas".

  • Podríamos tener problemas en futuras migraciones a próximas versiones de CRM.

  • Las personalizaciones no soportadas podrían causar funcionamientos no esperados.


  • A pesar de esto, muchas veces no nos queda otra opción que hacer cosas "no soportadas".
    las personalizaciones "no soportadas" yo las califico entre "totalmente no soportadas" y otras que son un poco mas "light". Las diferencias entre unas y otras estan claras, las primeras podrían causar problemas graves, y las segundas no tanto, o que podrian ser modificadas con relativa facilidad en futuras versiones.
    A continuación pongo algunos ejemplos:

    miércoles, 12 de agosto de 2009

    Eliminación masiva de registros en MSCRM

    Muchas veces necesitamos eliminar toda la información de una entidad específica. Si son pocos registros, no hay problema, los eliminamos de forma manual con el propio CRM.
    Ahora, si los registros son muchos, Microsoft CRM nos da la posibilidad de llamar a unos trabajos asíncronos de eliminación, de forma que podemos dispararlos, y dejarlos hasta que acaben de eliminar todos los registros.
    Recomiendo no eliminar nunca registros "a mano" en la base de datos SQL salvo que sea extrictamente necesario. Además tener en cuenta que si se borra directamente en SQL Server, toda la funcionalidad que se le haya definido a la entidad en cuando a relaciones en cascada, los workflows, y los plugins, no se dispararán. Además, como saben, no esta soportada la eliminación de registros directamente en la base de datos.

    La siguiente función hace exactamente eso, borra todos los registros de una entidad a traves de un trabajo del sistema asíncrono. Está hecho de una forma soportada y documentada en la SDK de MSCRM 4.0:


    public static void BorradoMasivo(string crmServerUrl, string orgName, string Entidad, string Usuario, string Password, string Dominio)
    {
    CrmAuthenticationToken token = new CrmAuthenticationToken();
    token.OrganizationName = orgName;
    CrmService service = new CrmService();
    service.Credentials = new System.Net.NetworkCredential(Usuario, Password,Dominio);
    service.Url = crmServerUrl;
    service.CrmAuthenticationTokenValue = token;

    QueryExpression bulkDeleteQuery = new QueryExpression();
    bulkDeleteQuery.EntityName = Entidad;

    BulkDeleteRequest bulkDeleteRequest = new BulkDeleteRequest();
    bulkDeleteRequest.JobName = "Eliminacion de: " + Entidad;
    bulkDeleteRequest.QuerySet = new QueryBase[] { bulkDeleteQuery };

    bulkDeleteRequest.StartDateTime = new CrmDateTime();
    bulkDeleteRequest.StartDateTime.Value = DateTime.Now.ToString();

    bulkDeleteRequest.RecurrencePattern = string.Empty;
    bulkDeleteRequest.SendEmailNotification = false;
    Guid[] emptyRecipients = new Guid[0];
    bulkDeleteRequest.ToRecipients = emptyRecipients;
    bulkDeleteRequest.CCRecipients = emptyRecipients;

    BulkDeleteResponse bulkDeleteResponse = (BulkDeleteResponse)service.Execute(bulkDeleteRequest);
    }

    Este proceso puede tardar mucho en caso de haber muchos miles (o millones) de registros.

    A medio camino del "delete" en la base de datos y de la utilización de la SDK, existe una posibilidad, no soportada también, de eliminar registros.
    Al eliminar un registro en MSCRM 4.0, realmente no se elimina de la base de datos, sino que simplemente se marca como para borrar poniendo el campo "deletionstatecode=2", para que luego el proceso asíncrono se encargue de eliminar todos los registros marcados. De esta forma podríamos "eliminar" registros del CRM a traves de un "UPDATE" en la base de datos. Esto no esta soportado, así que esto se debería probar que se eliminan correctamente.

    Así, por ejemplo, podríamos eliminar todas las Cuentas:

    UPDATE AccountBase SET DeletionStateCode=2

    Las eliminaciones masivas de registros pueden ser muy lentas si se hacen de forma soportada, pero para utilizar formas no soportadas, se debería estar muy seguro de lo que se hace y realizar exhaustivas pruebas de que eso funcion correctamente y no tiene consecuencias secundarias.

    Espero pueda servirles,

    Saludos

    domingo, 9 de agosto de 2009

    Como aumentar la cantidad de registros al exportar a Excel

    Cuando se exporta a Excel mediante una Hoja de Calculo dinámica, por defecto solo se exportan los primeros 10.000 registros.
    Esta cantidad puede ser ampliada haciendo un "Update" en la base de datos.
    Para aumentar dicha cantidad, se debe actualizar el registro de la base de datos correspondiente a la organización de la siguiente forma:


    UPDATE OrganizationBase SET MaxRecordsForExportToExcel=<numero_de_registros> WHERE Organizationid = '<Guid_de_la_Organizacion>'


    Luego se debe hacer un IISRESET (reiniciar el IIS), y listo.