2011-05-03 16 views
8

Quiero ejecutar consultas FetchXML en un entorno CRM 2011 utilizando los CRM 2011 servicios web SOAP yJavaScript.¿Cómo ejecutar FetchXML en CRM 2011 usando un servicio web CRM 2011 y JavaScript?

He encontrado varios artículos like this one que muestran cómo usar el servicio web 4.0 que todavía está disponible en el entorno 2011, pero no quiero hacer esto.

This link parece indicar que IOrganizationService.RetrieveMultiple puede manejar FetchXML. Sin embargo, no quiero usar código administrado para esto.

Me he encontrado con this link que muestra esencialmente lo que quiero hacer en la función RetrieveMultiple, pero quiero poder pasar FetchXML existente que he escrito, no una nueva expresión de filtro.

Respuesta

7

para ejecutar consultas FetchXML con JavaScript un montón de marcos/bibliotecas están disponibles:

En lugar de escribir el código a mano estas bibliotecas proporcionan una forma simple de realizar varias operaciones y acceder a los resultados. Pero tenga en cuenta que no todas las bibliotecas (actualmente) admiten el navegador cruzado (Q2.2012).

+0

Gracias Thuld. No creo que estos estuvieran disponibles en el momento en que publiqué mi pregunta, pero parece que ahora hay algunas opciones geniales. – Paul

+0

¿Algún comentario sobre los pros/contras de los 3? Estoy pensando que debería empezar a usar uno, pero me pregunto qué debería considerar para decidir ... – keerz

+0

Ok, soy el autor del CrmFetchKit, así que prefiero este :) Pero, como siempre, depende. El XrmServiceToolkit es compatible con más operaciones/mensajes de texto, mientras que el CrmFetchKit ofrece compatibilidad con varios navegadores. – thuld

1

"REST es un estilo arquitectónico en el que cada recurso se aborda mediante el uso de un único URI". http://msdn.microsoft.com/en-us/library/gg334279.aspx

Usted no será capaz de utilizar el punto final de descanso si es necesario utilizar FetchXml.

La alternativa es construir un mensaje SOAP como viste en tus ejemplos de CRM4. Todavía no lo he hecho, pero tal vez podrías utilizar una herramienta como Fiddler para ver cómo es el mensaje SOAP para que puedas replicarlo en tu entorno, que es el FetchXml modificado.

De todos modos, solo una idea por ahora. Déjame saber cómo va, y si logras resolverlo, quizás publiques tu solución.

+0

Gracias por la aclaración sobre el punto final REST. Me aseguraré de publicar de nuevo una vez que encuentre esta. – Paul

2

La sección "Solicitud y respuesta HTTP de ejemplo de captura" de this MSDN article describe cómo obtener un mensaje SOAP que se envía a CRM 2011 desde el código administrado.

La sección "Ejecutar la consulta" de this MSDN article muestra un ejemplo del uso de IOrganizationService.RetrieveMultiple de 2011 en el código administrado para ejecutar una consulta FetchXML.

Usando estas muestras, puede extraer un mensaje SOAP de ejemplo para RetrieveMultiple que contenga una consulta FetchXML.

La sección "Crear una biblioteca JScript" de the first MSDN article muestra cómo realizar una petición de ejecutar JavaScript en contra del criterio de valoración 2011 SOAP. Reemplace la solicitud Asignar SOAP en este ejemplo con el mensaje Recuperar Múltiple SOAP que obtiene al ejecutar el código administrado.

Esto le permite ejecutar una solicitud FetchXML en JavaScript contra el punto final SOAP 2011.

Éstos son algunos fragmentos de una biblioteca JavaScript que escribí usando la información anterior:

(function (window, undefined) { 
    var _window = undefined; 

    if (window.Xrm) 
     _window = window; 
    else if (window.parent.Xrm) 
     _window = window.parent; 
    else throw new Error("Unable to determine proper window"); 

    (function (Crm) { 
     (function (Service, $, JSON, Xrm) { 
      if (!Xrm) 
       throw new Error("Unable to locate Xrm"); 
      if (!JSON) 
       throw new Error("Unable to locate JSON"); 
      if (!$) 
       throw new Error("Unable to locate jQuery"); 

      Service.Create = function (ODataSetName, EntityObject) { 
       if (!EntityObject) { 
        throw new Error("EntityObject is a required parameter"); 
        return; 
       } 
       if (!ODataSetName) { 
        throw new Error("ODataSetName is a required parameter"); 
        return; 
       } 
       var jsonEntityObject = JSON.stringify(EntityObject); 

       var req = new XMLHttpRequest(); 
       req.open("POST", Service.GetODataEndPoint() + "/" + ODataSetName, false); 
       req.setRequestHeader("Accept", "application/json"); 
       req.setRequestHeader("Content-Type", "application/json; charset=utf-8"); 
       req.onreadystatechange = function() { 
        debuggingCallBack(this); 
       }; 

       req.send(jsonEntityObject); 

      }; 
      function debuggingCallBack(req) { 
       if (req.readyState == 4 /* complete */) { 
        if (req.status == 201 || req.status == 204 || req.status == 1223) { 
         //Success 
         //201 = create 
         //204 = update 
         //1223 = delete 
        } 
        else { 
         //Failure 
         debugger; 
        } 
       } 
      }; 


      Service.Fetch = function (FetchXML) { 
       var request = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"; 
       request += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">"; 
       request += "<s:Body>"; 
       request += "<RetrieveMultiple xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">"; 
       request += "<query i:type=\"a:FetchExpression\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">"; 
       request += "<a:Query>"; 
       request += Service.FetchEncode(FetchXML); 
       request += "</a:Query>"; 
       request += "</query>"; 
       request += "</RetrieveMultiple>"; 
       request += "</s:Body>"; 
       request += "</s:Envelope>"; 

       var req = new XMLHttpRequest(); 
       req.open("POST", Service.GetSOAPEndPoint(), false) 
       req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/RetrieveMultiple"); 
       req.setRequestHeader("Content-Type", "text/xml; charset=utf-8"); 
       req.setRequestHeader("Content-Length", request.length); 
       req.send(request); 

       results = Service.GetResults(req.responseXML); 

       return results; 
      }; 
      Service.Delete = function (ODataSetName, EntityID) { 
       if (!EntityID) { 
        throw new Error("EntityID is a required parameter"); 
        return; 
       } 
       if (!ODataSetName) { 
        throw new Error("ODataSetName is a required parameter"); 
        return; 
       } 

       var req = new XMLHttpRequest(); 
       req.open("POST", Service.GetODataEndPoint() + "/" + ODataSetName + "(guid'" + EntityID + "')", false) 
       req.setRequestHeader("Accept", "application/json"); 
       req.setRequestHeader("Content-Type", "application/json; charset=utf-8"); 
       req.setRequestHeader("X-HTTP-Method", "DELETE"); 
       req.onreadystatechange = function() { 
        debuggingCallBack(this); 
       }; 
       req.send(); 

      }; 


      Service.GetServerUrl = function() { 
       var serverUrl = null; 
       serverUrl = Xrm.Page.context.getServerUrl(); 
       if (serverUrl.match(/\/$/)) { 
        serverUrl = serverUrl.substring(0, serverUrl.length - 1); 
       } 
       return serverUrl; 
      }; 
      Service.GetODataEndPoint = function() { 
       return Service.GetServerUrl() + "/XRMServices/2011/OrganizationData.svc"; 
      }; 
      Service.GetSOAPEndPoint = function() { 
       return Service.GetServerUrl() + "/XRMServices/2011/Organization.svc/web"; 
      }; 

      Service.GetResults = function (responseXML) { 
       var sFetchResult = responseXML.selectSingleNode("//RetrieveMultipleResult").xml; 

       var oResultDoc = new ActiveXObject("Microsoft.XMLDOM"); 
       oResultDoc.async = false; 
       oResultDoc.loadXML(sFetchResult); 

       var oResults = new Array(oResultDoc.firstChild.firstChild.childNodes.length); 

       var iLen = oResultDoc.firstChild.firstChild.childNodes.length; 
       for (var i = 0; i < iLen; i++) { 

        var oResultNode = oResultDoc.firstChild.firstChild.childNodes[i]; 
        var oBE = new BusinessEntity(oResultNode.selectSingleNode("//a:LogicalName").text); 

        var iLenInner = oResultNode.firstChild.childNodes.length; 
        for (var j = 0; j < iLenInner; j++) { 
         var oRA = new Object(); 

         var value = null; 
         if (oResultNode.firstChild.childNodes[j].lastChild.childNodes.length == 3) { 
          if (oResultNode.firstChild.childNodes[j].lastChild.getElementsByTagName("a:Id").length == 1) 
           value = oResultNode.firstChild.childNodes[j].lastChild.getElementsByTagName("a:Id")[0].text; 
          if (oResultNode.firstChild.childNodes[j].lastChild.getElementsByTagName("a:Value").length == 1) 
           value = oResultNode.firstChild.childNodes[j].lastChild.getElementsByTagName("a:Value")[0].text; 
         } 
         if (!value) 
          value = oResultNode.firstChild.childNodes[j].lastChild.text; 

         oRA["value"] = value; 

         oBE.attributes[oResultNode.firstChild.childNodes[j].firstChild.firstChild.text] = oRA; 
        } 

        oResults[i] = oBE; 
       } 
       return oResults; 
      }; 

      Service.BusinessEntity = function BusinessEntity(sName) { 
       this.name = sName; 
       this.attributes = new Object(); 
      }; 

      Service.FetchEncode = function (FetchXML) { 
       var c; 
       var HtmlEncode = ''; 

       if (FetchXML == null) { 
        return null; 
       } 
       if (FetchXML == '') { 
        return ''; 
       } 

       for (var cnt = 0; cnt < FetchXML.length; cnt++) { 
        c = FetchXML.charCodeAt(cnt); 

        if (((c > 96) && (c < 123)) || 
          ((c > 64) && (c < 91)) || 
          (c == 32) || 
          ((c > 47) && (c < 58)) || 
          (c == 46) || 
          (c == 44) || 
          (c == 45) || 
          (c == 95)) { 
         HtmlEncode = HtmlEncode + String.fromCharCode(c); 
        } 
        else { 
         HtmlEncode = HtmlEncode + '&#' + c + ';'; 
        } 
       } 

       return HtmlEncode; 
      }; 
     } (Crm.Service = Crm.Service || {}, _window.jQuery, _window.JSON, _window.Xrm)); 
    } (_window.Crm = _window.Crm || {})); 
} (window)); 
+0

Si bien este método le permite ejecutar una solicitud FetchXML en JavaScript con respecto al punto final SOAP 2011, no devuelve XML en el mismo formato que el servicio web 4.0. Esperaba poder actualizar las llamadas de FetchXML para un proyecto de migración de CRM 4.0 a 2011, pero no va a ser tan fácil. – Paul

+0

En la función Service.Fetch, ¿dónde se definen los "resultados" antes de que se devuelva? – musefan

+0

buena captura. Echaré un vistazo a la fuente y me pondré en contacto con usted sobre eso. – Paul

2

desde el enlace que envió a la Microsoft SDK, verá cómo conectar con el servicio OData. Como ya puede haber encontrado, ODATA no le permite ejecutar la búsqueda.

En su lugar, tendrá que utilizar el servicio SOAP (/XrmServices/2011/Organization.svc), y pasar su ir a buscar utilizando Recuperar múltiple.

He aquí un vistazo más detallado a utilizar el servicio de 2011 a través de JavaScript: http://blog.customereffective.com/blog/2011/05/execute-fetch-from-javascript-in-crm-2011.html

Aquí es otra entrada del blog que analiza el XML devuelto y construye un objeto fácilmente consumible JavaScript: http://blog.customereffective.com/blog/2011/05/parsing-and-consuming-the-crm-2011-soap-service-inside-javascript.html

El 2011 Servicio de Organización es bastante diferente en su retorno, por lo que no será plug-n-play de sus cosas 4.0; sin embargo, el punto final 2011 tiene muchas mejoras agradables.

+0

La migración con la que estoy trabajando usa Ascentium CRM Helper para el servicio web 4.0. Creé un asistente similar para los servicios web de 2011 que devuelve el mismo objeto de negocio que el asistente de Ascentium. Creo que hay margen de mejora en la conversión al objeto de negocio, pero hasta ahora parece funcionar para mi proyecto actual. Estoy interesado en leer su publicación ascendente. Tal vez podríamos comparar nuestros enfoques? – Paul

+0

Guau, me gustan los servicios de Ascentium y curiosamente hay algunos elementos similares, así que con suerte los cambios serán mínimos. Esto es solo buscar en este momento. Por cierto, si no está usando en línea, puede comentar un poco de su código CreateXMLHTTP y conectarse localmente sin tener que publicar (lo cual es bastante conveniente). Debería poder copiar el código CreateXMLHTTP y las 3 clases auxiliares y conectarlas a las cosas que publiqué. –

Cuestiones relacionadas