27 enero 2012

Plug-Ins en CRM 2011

Innovar Tecnologías ©

- El objetivo de este desarrollo es diseñar y programar un plug-in para su despliegue en nuestro servidor CRM 2011

- El proceso de despliegue de un plug-in en CRM 2011 se divide en los siguientes pasos:

· Compilar la herramienta de registro de plug-ins para uso con CRM 2011 incluida en el SDK
· Desarrollar y registrar el plug-in acorde a la lógica de nuestro proceso custom

- En primer lugar abriremos el proyecto de Plugin Registration Tool incluido en el SDK de Dynamics CRM 2011 para compilar la herramienta



- Compilamos el proyecto y establecemos conexión con nuestro servidor mediante el uso de nuestras credenciales:





- Una vez establecida la conexión desarrollaremos nuestro plug-in con código custom para realizar los procesos diseñados
- Mediante el uso de código personalizado en procesos de CRM, el rango de posibilidades para incluir lógica de negocio se amplia de forma muy considerable

- Los pasos para crear un plug in mediante Visual Studio 2010 son los siguientes:

· Crear un nuevo proyecto Class Library
· Agregar las siguientes referencias del SDK del CRM
>> Microsoft.Crm.Sdk.Proxy
>> Microsoft.Xrm.Sdk
· Agregar las siguientes referencias del framework de .NET
>> System.ServiceModel
>> System.Runtime.Serialization

· El ensamblado del plug-in debe estar firmado mediante strong-key para ser desplegado en el servidor CRM 2011



- Codificando la librería para nuestro plug-in:
· La clase que implementemos en nuestro plug-in heredará de la interface IPlugin del SDK

   
 public class MyPlugin: IPlugin



· Esto entonces nos permite implementar el método Execute, el cual, es la función Main() central que el plug-in ejecuta como parte del pipeline de mensajes de CRM

   
 public void Execute(IServiceProvider serviceProvider)


· Este método transfiere el objeto serviceProviderque contiene los detalles entrantes sobre CRM directos desde el pipeline de mensajes de CRM, mediante este objeto podemos derivar el contexto de ejecución del plug-in

- El plug-in de ejemplorealiza una pequeña validación en la creación de un nuevo registro de la entidad Cuenta, mediante el siguiente código:

   
public class MyPlugin : IPlugin
{

    public void Execute(IServiceProvider serviceProvider)
    {
        try
        {
            IPluginExecutionContext context =
                (IPluginExecutionContext)serviceProvider.GetService(
                 typeof(IPluginExecutionContext));

            Entity accountEntityImage = (Entity)context.InputParameters["Target"];

            string accountName = (string)accountEntityImage["name"];

            if (contieneNumeros(accountName))
            {
                string message = "El nombre de la cuenta no puede llevar números";

                throw new InvalidPluginExecutionException(message);
            }

        }
        catch (Exception ex)
        {
            throw new InvalidPluginExecutionException("CRM2011.Example Plug In 
                      --> Execute '" + ex.Message + "'");
        }
    }

    private bool contieneNumeros(string nombre)
    {
        bool contieneNums = false;

        for (int i = 0; i < nombre.Length; i++)
        {
            if (char.IsNumber(nombre[i]))
            {
                contieneNums = true;
                break;
            }
        }
        return contieneNums;
    }
}


- Compilamos la clase y estará lista para ser desplegada como parte integral de nuestro entorno CRM

- Los pasos para el registro y despliegue mediante la herramienta del SDK compilada y testada previamente, son los siguientes:

· Establecer conexión con nuestro servidor CRM 2011
· Registrar nuestro ensamblado
· Registrar los pasos de ejecución para el plug-in








- Las opciones de registro del ensambladode nuestro plug-in consisten en la elección del modo de aislamiento de nuestro proceso, en este caso modo seguro (Sandbox), y el lugar de almacenaje del ensamblado, en este caso en la base de datos de CRM

- En este punto registraremos un nuevo paso para nuestro plug-in





- Las propiedades que debemos configurar para nuestro plug-in son las siguientes:
· Message: es el evento de triggering del plug-in
· Primary Entity: la entidad para la cual se desencadena el plug-in
· Execution order: configurable para la secuencia de ejecución de 2 o más plugins
· Stage: en este caso la validación se realizará post-operation, ya que durante la operación Create (del mismo modo que comparándolo con un trigger de sql disparado para una operación de inserción, la tabla de pre insert no contiene datos), la pre-imagen no contiene datos del registro creado
· Execution mode: en este caso será síncrono, considérese el caso de ejecución asíncrona para casos de ejecución de procesos de carga de datos etc., en los que no se espera una respuesta del plug-in inmediata o los procesos de negocio que realiza el plug-in son de mayor embergadura
· Deployment: elegiremos los tipos de despliegue en los que se ejecutará el plug-in, al menos uno, es este caso Server


- Realizados estos pasos procederemos a probar el funcionamiento del plug-in






_


Desde la comunidad de developers de Dynamics CRM, queremos agradecer sus contribuciones a los creadores de los siguientes blogs y sitios web:

CRM Consultancy


Desde Innovar Tecnologías
esperamos que este documento les sea de ayuda en su desarrollo

Web de la empresa

25 enero 2012

Rollup 6 de CRM 2011

Ya está disponible el RollUp 6 de Dynamics CRM 2011 , aqui os dejo el enlace para descargarlo:
http://www.microsoft.com/downloads/es-es/details.aspx?familyid=e35f3e66-42ea-46af-9e79-4b4f7fa55cfe&displaylang=es

Al parecer no hay nueva funcionalidad en este RollUp sino la solucion de unos cuantos errores , se puede ver el detalle en :
http://support.microsoft.com/default.aspx?kbid=2600640

Seguimos a la espera del RollUp q incluya multinavegador!

22 enero 2012

Conexión al servidor CRM mediante aplicaciones ASPX

Innovar Tecnologías ©

En este ejemplo conectaremos una aplicación web ASPX con el servicio CRM a través de los siguientes objetos

- CrmConnection conexion;
- OrganizationService service;

El objetivo es la recuperación de datos de la entidad Contact, para mostrarlos en pantalla al usuario



Realizaremos la conexión con un servidor Dynamics CRM 2011


- El primer paso será preparar el diseño de la aplicación de conexión, en este ejemplo una sencilla página web para conectar con el servicio CRM y mostrar los datos de la entidad Contact en una tabla



- Lo siguiente será preparar la cadena de conexión a nuestro servidor CRM, para utilizarla como parámetro en el constructor de nuestro objeto CrmConnection

- Incluiremos nuestra cadena de conexión en el archivo web.config



- Ahora crearemos el objeto CrmConnection, para poder crear en base a este el objeto OrganizationService:
    conexion = new CrmConnection("Crm2011");
    service = new OrganizationService(conexion);


- Con nuestros objetos de conexión y servicio, podremos hacer uso del servicio para invocar a su método RetrieveMultiple(), el cual acepta como parámetro un objeto de tipo QueryExpression, y devuelve un objeto de tipo EntityCollection

- Al invocar a este método y asignar sus resultados a nuestra variable de tipo EntityCollection, utilizaremos un bucle foreach para recorrer nuestro conjunto de resultados
private void verContactos()
{
    QueryExpression qe = new QueryExpression();
    qe.ColumnSet = new ColumnSet(allColumns: true);
    qe.EntityName = "contact";
    EntityCollection ec = service.RetrieveMultiple(qe);
    foreach (Entity record in ec.Entities)
    {
        TableCell cellNombre = new TableCell();
        cellNombre.Text = record["firstname"].ToString();

        TableCell cellApellidos = new TableCell()
        cellNombre.Text = record["lastname"].ToString();
        
        TableCell cellId = new TableCell()
        cellNombre.Text = record["contactid"].ToString();

        TableRow row = new TableRow();
        row.Cells.Add(cellNombre);
        row.Cells.Add(cellApellidos);
        row.Cells.Add(cellId);

        tblContactos.Rows.Add(row);
    }
}


- Y el resultado en pantalla es el siguiente:




_


Desde la comunidad de developers de Dynamics CRM, queremos agradecer sus contribuciones a los creadores de los siguientes blogs y sitios web:

- Result On Demand

http://www.resultondemand.nl/support/sdk/2bdd259c-1003-4b37-a7db-61bf2278c7e4.htm

- Y a los siguientes sitios web de documentación oficial sobre CRM 2011

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


Desde Innovar Tecnologías
esperamos que este documento les sea de ayuda en su desarrollo

Web de la empresa

14 enero 2012

BUSINESS CONNECTIVITY SERVICES - SharePoint 2010

Innovar Tecnologías ©

DESARROLLANDO UN MODELO DE DATOS CUSTOM .NET DESDE EL PRINCIPIO

- En este ejemplo, iremos paso a paso en la implementación de un modelo de datos que publique una lista de marcas de ordenadores leída desde una base de datos, relacionada (asociada en términos BCS) con una lista de ordenadores de cada marca; este ejemplo leerá la base de datos utilizando LINQ to SQL.

1. Iniciando el proyecto

- Crea un nuevo proyecto en Visual Studio - SharePoint 2010 tipo Business Data Connectivity Model (Conexión a datos profesionales)
- Por definición este tipo de soluciones es full-trust y sólo permite despliegue a nivel de granja
- Aparece una ventana con un diseñador de modelos preconfigurado describiendo al archivo .bdcm, con una hipotética Entity1, junto con las clases relacionadas Entity1.cs y EntityService.cs
- Borra la Entity1 del modelo así como sus dos ficheros .cs relacionados.
- Para hacer desplegable el proyecto, desde este momento necesitamos configurar la feature que implementa el modelo de la siguiente forma, indicando la SiteUrl en las propiedades:

<?xml version="1.0" encoding="utf-8" ?>
    <Feature Scope="Farm" Id="{932263B8-BDF5-4415-ABAB-479C7B29CEE0}"
             xmlns="http://schemas.microsoft.com/sharepoint/">
      <Properties>
         <Property Key='SiteUrl' Value='http://sharepointserver:7822'>
         <Property Key='GloballyAvailable' Value='true'>
      </Properties>
    </Feature>

- Añade un modelo de clases LINQ to SQL al proyecto y define un enlaces a las tablas Marcas y Ordenadores definidas en la base de datos SQL Server objetivo. Configura las propiedades de los campos de ambas tablas en el modelo .dbml para dar soporte a concurrencia optimista (Update Check = Never)



- Renombra el modelo BCS BdcModel1 a un nombre más consistente, así como su fichero .bdcm relacionado al mismo nombre
- Añade una nueva entidad al modelo desde el Cuadro de Herramientas propio de BDCM, y ponle el nombre EntityMarcas. El diseñador generará por usted el fichero relacionado EntityMarcasService.cs



- Añade un nuevo identifier a la entidad, y añade también dos métodos, llamados ReadList y ReadItem



- Ahora necesitas configurar los dos métodos. El método ReadList corresponde al método Finder, mientras que el método ReadItem corresponde al método SpecificFinder

- Empecemos con el método ReadList. Selecciona el método en el diseñador y muestra la ventana BDC Method Details. Para añadir un nuevo parámetro, selecciona la sección Parameters y pulsa Agregar Parámetro



- Nombra al nuevo parámetro listaMarcas, asígnale dirección Return, y selecciona la columna listaMarcasTypeDescriptor para editar sus propiedades como se indica a continuación:
• Is Collection = true
• Despliega el valor de la propiedad TypeName para marcar la opción Is Enumerable, y seleccionar el tipo MARCAS del proyecto actual



- Los Descriptores de Tipo que corresponden a una colección, necesitan un Type Descriptor secundario del mismo tipo que representen a un ítem singular de la clase. De modo que seleccionamos listaMarcasTypeDescriptor en el Explorador de BDC y le agregamos un descriptor de tipo, y en sus propiedades le indicamos el Type Name correspondiente a la clase MARCAS publicada por LINQ to SQL, no enumerable, no colección



- Ahora es el momento de añadir una nueva instancia del método ReadList, configurando esa instancia como método Finder. Expande la sección de instancias del método ReadList en la ventana BDC Method Details, y agrega una instancia de tipo Finder

- Configura la instancia del método como es mostrado a continuación:



- Ahora configuraremos el método ReadItem, el proceso es similar al expuesto, sin embargo, para este método tendremos un parámetro llamado IdMarca, con dirección In, y un parámetro Marca, con dirección Return. La instancia del método para el método ReadItem tendrá un tipo de SpecificFinder

- Ahora es el momento de implementar el código del modelo. Si abres el código fuente del fichero MarcasService.cs, puedes ver que el diseñador ha generado el siguiente código de servicio

    public partial class EntityMarcasService
    {
        public static IEnumerable ReadList()
        {
            throw new System.NotImplementedException();
        }

        public static MARCAS ReadItem(string IdMarca)
        {
            throw new System.NotImplementedException();
        }
    }


- Reemplace la implementación de los métodos con código concreto, y estará listo para proveer a BCS de datos read-only. El siguiente listado muestra una implementación de código concreto:

        private static DataClasses1DataContext GetDataContext()
        {
            DataClasses1DataContext dataContext =
                new DataClasses1DataContext("Data Source=sharepointserver;Initial 
                    Catalog=SP_ORDENADORES;Integrated Security=True");

            return dataContext;
        }

        public static IEnumerable ReadList()
        {
            DataClasses1DataContext dataContext = GetDataContext();
            return (from m in dataContext.MARCAS select m);
        }

        public static MARCAS ReadItem(string idMarca)
        {
            DataClasses1DataContext dataContext = GetDataContext();
            return (dataContext.MARCAS.FirstOrDefault(m => m.IdMarca == 
                          Convert.ToInt32(idMarca)));
        }


- Ahora añadiremos los métodos Creator, Updater y Deleter

- El método Creator acepta un parámetro de tipo MARCAS con un valor de dirección In, y devuelve un resultado de tipo MARCAS de dirección Return

- El método Updater acepta al menos un parámetro de tipo MARCAS de dirección In, pero no devuelve nada, aunque es configurable para que tenga algún tipo de valor de retorno

- El método Deleter acepta un parámetro de tipo IdMarca con valor de dirección In, pero tampoco devuelve nada, aunque también es configurable para que tenga algún valor de retorno

- El siguiente listado muestra la implementación de los métodos de inserción, modificación y borrado en MarcasService.cs:

        public static MARCAS InsertItem(MARCAS marca)
        {
            DataClasses1DataContext dataContext = GetDataContext();

            dataContext.MARCAS.InsertOnSubmit(marca);
            dataContext.SubmitChanges();

            return marca;
        }

        public static void UpdateItem(MARCAS marca)
        {
            DataClasses1DataContext dataContext = GetDataContext();

            dataContext.MARCAS.Attach(marca, true);
            dataContext.SubmitChanges();
        }

        public static void DeleteItem(string IdMarca)
        {
            DataClasses1DataContext dataContext = GetDataContext();

            MARCAS marcaToDelete = dataContext.MARCAS.FirstOrDefault
                (m => m.IdMarca == Convert.ToInt32(IdMarca));

            dataContext.MARCAS.DeleteOnSubmit(marcaToDelete);
            dataContext.SubmitChanges();
        }


- Ahora repetimos el mismo proceso para la entidad EntityOrdenadores, de modo que nuestro diagrama .bdcm quede del siguiente modo:



- El siguiente paso en este proyecto es asociar las entidades, para navegar los datos a través de la asociación. De hecho, una asociación es un tipo particular de definición de instancia de método AssociatonNavigator. Así, tienes la capacidad de proveer parámetros de entrada y parámetros de filtro

- Para crear la asociación seleccionamos la entidad origen, en nuestro caso EntityMarcas, hacemos click derecho sobre ella, y en el menú contextual seleccionamos Agregar | Asociación



- Podemos elegir un nombre para el método de asociación en la columna método, cambiando el nombre suministrado por defecto EntityMarcasToEntityOrdenadores, por un nombre más descriptivo, por ejemplo VerOrdenadores, el cual aceptará un parámetro de tipo IdMarca para filtrar los ordenadores devueltos según la marca

- En nuestro ejemplo, la asociación será de tipo 1-n en sentido sólo de marcas hacia ordenadores (1 marca – n ordenadores), por lo que borraremos el método EntityOrdenadoresToEntityMarcas

- El punto clave de la asociación es la sección la casilla chequeable “Es una asociación de clave externa, que marcaremos a true, y consecuentemente la Asignación de identificadores, en la que indicaremos al Campo
ReadItem.IdOrdenador.IdOrdenadorTypeDescriptor que su Id de origen sea IdMarca (este campo obviamente está implementado en nuestra base de datos, en la tabla Ordenadores como foreign key referenciando a la tabla Marcas)

- El resultado de aplicar la configuración en el cuadro de diálogo es el siguiente:



- Comprobamos que ahora tenemos un método de asociación, llamado VerOrdenadores el cual debemos implementar para recuperar la lista de ordenadores de cada marca. El siguiente listado muestra la implementación:

        public static IEnumerable VerOrdenadores(string idMarca)
        {
            DataClasses1DataContext dataContext = GetDataContext();

            IEnumerable orderList = dataContext.ORDENADORES.Where
                (o => o.IdMarca == Convert.ToInt32(idMarca));

            return orderList;
        }


- Para desplegar nuestro proyecto podemos utilizar un Web Part que utilice las nuevas clases creadas




_

Documentación destacada sobre Business Connectivity Services:

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


Desde Innovar Tecnologías
, esperamos que este ejemplo les resulte de ayuda en su desarrollo

Web de la empresa

13 enero 2012

Incluir un botón custom en el ribbon


Innovar Tecnologías ©

- El objetivo de este ejemplo es customizar el ribbon de la entidad "Cuentas", insertando nuestro propio botón con su código correspondiente



- Vamos a crear nuestra propia solución, le vamos a incluir la entidad Cuentas original, y la vamos a exportar para obtener el código y los metadatos de la entidad.
- Al exportar nuestra solución, obtendremos un fichero .zip con los siguientes archivos:




- Nuestro archivo de interés para incluir nuestras propias extensiones es customizations.xml

- El área de customización será el nodo Entities, el cual contendrá los metadatos de despliegue de todas las entidades incluidas en la solución

- Una vez localizada la entidad a customizar, lo siguiente es encontrar el área del xml en el que operar, en nuestro caso es el nodo

- Prestemos atención al contenido de este nodo:



Paso 1: Despliegue del botón custom


- El nodo en el que incluiremos nuestro botón custom es el nodo <CustomActions>

- Cuando lleguemos al nodo <CustomActions/> lo encontraremos en principio sin ningún child node de acciones custom, por lo que tendremos que implementar el código manualmente, para ello necesitamos conocer la siguiente información:

• Id: el id de la acción custom, un id único, una cadena de texto con un valor único en el xml, por ejemplo, para nuestro caso GT.account.Form.ExportData.CustomButton
• Location: esta información debemos buscarla para indicar con precisión qué tab albergará nuestro botón, en nuestro caso Mscrm.Form.account.MainTab.ExportData.Controls._children
• Sequence: esta información debemos buscarla para indicar con precisión en qué orden aparecerá nuestro botón dentro de la tab especificada mediante el atributo Location, en nuestro caso 2

- Esta información la podemos encontrar en el archivo del sdk accountRibbon.xml en el archivo del sdk con la siguiente ruta de acceso:

• […]\sdk\resources\exportedribbonxml\accountRibbon.xml

- Este archivo contiene la información de despliegue inicial del ribbon de la entidad account, y nos será útil durante el desarrollo de este ejemplo para conocer los valores exactos que asignaremos a los atributos Location y Sequence mencionados anteriormente

- Archivo accountRibbon.xml:



- La zona marcada se corresponde con el MainTab del formulario de la entidad account, con los controles de exportación de datos, en despliegue la siguiente zona:



- Conociendo esta información, el valor del atributo Location de nuestra custom action será el siguiente: Location="Mscrm.Form.account.MainTab.ExportData.Controls._children"

- Observe la inclusión del sufijo ._children a la localización de la tab en la que estamos incluyendo el botón, indicando que se trata de un objeto child más de la zona de la ribbon

- Ahora implementemos el child node del nodo CustomAction, <CommandUIDefinition>, el cual contendrá al child node <Button>, nodo específico de nuestra implementación



- Como podemos observar, el id del botón se corresponde con el id de la custom action que contiene a nuestro botón

- El atributo Command será explicado más adelante durante la implementación del código del botón


Paso 2: Implementación del código para el botón


- El área de interés de nuestro fichero customizations.xml, es ahora el nodo <CommandDefinitions>



- El punto de interés principal para la implementación del código del botón, es el nodo <JavaScript>, el cual contiene los siguientes atributos:
• Library: indicando el recurso web tipo .js subido previamente al servidor
• FunctionName: indicando la función de la librería que ejecutará el botón al ser pulsado
(la implementación de este fichero js es un ejemplo a un mayor número de funciones de mayor complejidad)

- Ahora guardaremos el archivo customizations.xml con los cambios realizados, y lo empacaremos de nuevo en nuestro fichero de solución .zip para su importación



- Publicamos las personalizaciones y comprobamos el resultado




_

Desde la comunidad de developers de Dynamics CRM, queremos agradecer sus contribuciones a los siguientes sitios web y blogs:

- Nishant Rana´s weblog

http://nishantrana.wordpress.com/2010/11/04/adding-my-first-custom-button-in-crm-2011/">

- Erik Pool Xrm Development

http://erikpool.blogspot.com/2011/10/understanding-crm-ribbon-xml-part-1.html

Desde Innovar Tecnologías esperamos que este documento les sea de ayuda en su desarrollo

Web de la empresa

10 enero 2012

Consulta a entidades CRM mediante llamadas REST

Innovar Tecnologías ©

El objetivo de este ejemplo
es consultar asíncronamente la entidad “Actividades” con opciones de consulta personalizables



Este ejemplo hace uso de los siguientes recursos web:


· HTMLPage.htm
· restDataRetrieve.js
· json2.js
· SDK.REST.js


Lo primero que haremos será crear una sencilla página html para subirla a nuestro servidor de Dynamics CRM como recurso web

- La página web constará de los siguientes elementos:

- 1 elemento Select con 3 childNodes Option para seleccionar qué tipo de Actividad que deseamos recuperar

- 2 elementos de radio excluibles entre sí para seleccionar el estado de las Actividades que buscamos

- 2 elementos de texto para indicar el intervalo de fechas de las actividades que deseamos recuperar

- 1 elemento de texto para indicar el número máximo de registros que deseamos recuperar

A continuación subiremos la página .htm a nuestra biblioteca de recursos web de nuestro servidor de Dynamics

Seguidamente
subiremos las siguientes librerías necesarias para nuestro proyecto:

- ClientGlobalContext.js.aspx : esta librería nos dan acceso al contexto global de la sesión activa

- new_json2.js : esta librería habilita el uso de notación json

- new_sdkrest.js : en esta librería está implementada la función parametrizada SDK.REST.retrieveMultipleRecords

Edición del HTML en servidor para añadir las referencias a las librerías utilizadas:



Observe los nombres mediante los cuales referenciamos a las librerías, todos comienzan con el prefijo new_, pues es como de hecho están almacenados en el servidor, accesibles en todo momento en la ruta:


- [nuestroservidordynamics]/WebResources/new_{nuestroarchivo}.js


Ahora es el momento para codificar nuestro archivo de JavaScript principal, restDataRetrieve.js

Este archivo se compone de las siguientes funciones:

- Función in line para el manejo del evento de carga completa del documento, document.onreadystatechange

- Función getIdUsuario(), para utilizar el método de contexto getUserId, que devuelve el guid del usuario actual

- Función bringActivities(), la cual comprobará las opciones de consulta marcadas, creará una consulta de rest dinámica, y llamará a la función parametrizada de la librería SDK.REST.js SDK.REST.retrieveMultipleRecords

Y de las siguientes variables globales:

- bringButton: es el botón que realizará la llamada

- tableSpan: es el span que contendrá el elemento table que crearemos dinámicamente

- tabla: es la tabla en sí creada dinámicamente

- userid: es el id del usuario activo en la sesión

Vayamos paso a paso en la implementación del código de este archivo:

document.onreadystatechange = function () {
      if (document.readyState == "complete") {
         bringButton = document.getElementById("btnBring");
         bringButton.onclick = bringActivities;

         tableSpan = document.getElementById("tableSpan");

         getUserId();
      }
}


=> en el momento en que el documento se haya cargado completamente, asignaremos valores a las variables bringButton, al cual también añadiremos su manejador onclick, y a la variable tableSpan
=> es en este momento cuando identificamos al usuario activo llamando a nuestra función getIdUsuario

function getIdUsuario() {
  var context = GetGlobalContext();
  userid = context.getUserId();
}

function bringActivities() {

  userSpan.innerHTML = userid;

  var numActivities = document.getElementById("txtNumero").value;
  var tipo;
  switch (document.getElementById('Select1').selectedIndex) {
    case 0:
      tipo = "task";
      break;
    case 1:
      tipo = "phonecall";
      break;
    case 2:
      tipo = "opportunityclose";
      break;
  }

  var open;
  if (document.getElementById('RadioButtonList1_0').checked)
    open = "1";
  else
    open = "0";
 
  var fechaDesde = document.getElementById('txtDesde').value;
  var fechaHasta = document.getElementById('txtHasta').value;
 
  var consulta;
 
  consulta = "$select=OwnerId,ActivityTypeCode,StateCode,CreatedOn";
  consulta += "&$filter=ActivityTypeCode%20eq%20'" + tipo + "'";
  consulta += "%20and%20StateCode/Value%20eq%20" + open;
  consulta += "%20and%20CreatedOn%20ge%20datetime'" + fechaDesde + "'";
  consulta += "%20and%20CreatedOn%20le%20datetime'" + fechaHasta + "'";
  consulta += "%20and%20OwnerId/Id%20eq%20(guid'" + userid + "')";
  consulta += "&$top=" + numActivities;
  consulta += "&$orderby=CreatedOn%20desc";
 
  tabla = "<TABLE><TR><TD>OwnerId.Id";
  tabla += "</TD><TD>OwnerId.Name</TD>";   
  tabla += "<TD>ActivityTypeCode</TD><TD>";
  tabla += "StateCode.Value</TD><TD>CreatedOn";
  tabla += "</TD></TR>";

  SDK.REST.retrieveMultipleRecords(
    "ActivityPointer",
    consulta,
    function (resultados) {
      var actividades= resultados;
      for (var i = 0; i < numActivities; i++) {
        if (actividades[i]) {
        tabla = tabla + "<TR><TD>";
        tabla = tabla + actividades[i].OwnerId.Id;
        tabla = tabla + "</TD><TD>";
        tabla = tabla + actividades[i].OwnerId.Name;
        tabla = tabla + "</TD><TD>";
        tabla = tabla + actividades[i].ActivityTypeCode;
        tabla = tabla + "</TD><TD>";
        tabla = tabla + actividades[i].StateCode.Value;
        tabla = tabla + "</TD><TD>";
        tabla = tabla + actividades[i].CreatedOn;
        tabla = tabla + "</TD></TR>";
      }
    }
  },
  function () {
    alert("error en bring activities");
  },
  function bringComplete() {
    tabla = tabla + "</TABLE>";
    tableSpan.innerHTML = tabla;
  });
}


- Una vez tenemos los valores que usaremos en la llamada de rest, procedemos a crear el valor de la llamada rest en sí:

La llamada rest de nuestro ejemplo se compone de 4 cláusulas:


· select
· filter
· top
· orderby


- Cláusula select: para la proyección de la consulta

- Cláusula filter: equivalente a la cláusula where en dialectos sql

- Las cláusulas top y orderby, limitan el número de registros devueltos y los ordenan, respectivamente

- La siguiente línea asigna el valor inicial a la variable tabla, para su posterior inserción en la variable tableSpan, iniciada con la carga del documento en el punto anterior, esta línea crea la tabla y sus columnas de cabecera

A continuación iniciamos la llamada en sí, mediante la llamada a la función retrieveMultipleRecords de la librería SDK.REST.js, La firma de este método es la siguiente:

SDK.REST.retrieveMultipleRecords(
  "nombreEsquemaEntidad", 
  "llamadaREST", 
  función successCallBack, 
  función errorCallBack, 
  función OnCompleteCall);



Una vez codificado nuestro archivo restDataRetrieve.js, procedemos a incluirlo en nuestro servidor de Dynamics CRM como recurso web, y añadiremos su referencia en nuestra página HTMLPage.htm



_


Desde la comunidad de developers de Dynamics CRM, queremos agradecer sus contribuciones a los creadores de los siguientes blogs y sitios web:

- Gareth Tucker, de Microsoft CRM blog

http://gtcrm.wordpress.com/2011/02/22/adding-selection-criteria-to-rest-queries/

- Siva´s Dynamics CRM 2011 blog

http://dynamicscrm2011.wordpress.com/tag/crm-2011-web-resource

- Y a los siguientes sitios web de documentación oficial sobre CRM 2011

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


Desde Innovar Tecnologías
esperamos que este documento les sea de ayuda en su desarrollo

Web de la empresa