Как выполнить FetchXML в CRM 2011 с помощью веб-сервиса CRM 2011 и JavaScript?

Я хочу выполнить запросы FetchXML в среде CRM 2011, используя CRM 2011 SOAP web services и на JavaScript.

Я нашел несколько статей как это показывает, как использовать веб-службу 4.0, которая все еще доступна в среде 2011, но я не хочу этого делать.

этой ссылке кажется, указывает, что IOrganizationService.RetrieveMultiple может обрабатывать FetchXML. Тем не менее, я делаю не хочу использовать для этого управляемый код.

я наткнулся этой ссылке это показывает, по существу, что я хочу сделать в функции RetrieveMultiple, но я хочу иметь возможность передать существующий FetchXML, который я написал, а не новое выражение фильтра.

4 ответов


для выполнения запросов fetchxml с JavaScript доступна куча фреймворков / библиотек:

вместо написания кода вручную эти библиотеки предоставляют простой способ выполнения нескольких операций и доступа к результатам. Но учтите, что не все библиотеки (в настоящее время) поддерживают кросс-браузер (В2.2012).


из ссылки, которую вы разместили в Microsoft SDK, вы увидите, как подключиться к службе ODATA. Как вы, возможно, уже обнаружили, ODATA не позволяет выполнять fetch.

вместо этого вам нужно будет использовать службу SOAP (/XrmServices/2011 / Организация.svc) и передайте свою выборку, используя Retrieve Multiple.

вот более подробный взгляд на использование сервиса 2011 года через JavaScript: http://blog.customereffective.com/blog/2011/05/execute-fetch-from-javascript-in-crm-2011.html

вот еще одно сообщение в блоге, которое анализирует возвращенный XML и создает легко потребляемый объект JavaScript: http://blog.customereffective.com/blog/2011/05/parsing-and-consuming-the-crm-2011-soap-service-inside-javascript.html

служба организации 2011 года сильно отличается в своем возвращении, поэтому это не будет plug-n-play от вашего 4.0 материала; тем не менее, конечная точка 2011 имеет много хороших улучшений.


раздел" захват образца HTTP-запроса и ответа"эта статья MSDN описывает, как получить сообщение SOAP, отправленное в CRM 2011 из управляемого кода.

раздел" выполнить запрос"эта статья MSDN дает пример использования IOrganizationService 2011 года.RetrieveMultiple в управляемом коде для выполнения запроса FetchXML.

используя оба этих примера, можно извлечь образец сообщения SOAP для RetrieveMultiple, который содержит запрос FetchXML.

раздел" создать библиотеку JScript"первая статья MSDN показывает, как выполнить запрос Execute в JavaScript для конечной точки SOAP 2011. Замените запрос Assign SOAP в этом примере сообщением RetrieveMultiple SOAP, полученным при выполнении управляемого кода.

Это позволяет выполнить запрос FetchXML в JavaScript для конечной точки SOAP 2011.

вот некоторые фрагменты из библиотеки JavaScript, я написал, используя информацию выше:

(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));

"REST-это архитектурный стиль, в котором каждый ресурс рассматривается с помощью уникального URI." http://msdn.microsoft.com/en-us/library/gg334279.aspx

вы не сможете использовать конечную точку REST, если вам нужно использовать FetchXml.

альтернативой является создание сообщения SOAP, как вы видели в примерах CRM4. Я еще не сделал этого сам, но, возможно, вы могли бы использовать такой инструмент, как Fiddler, чтобы увидеть, что SOAP-сообщение выглядит так, что вы можете реплицировать их в своей среде, которая была изменена FetchXml.

в любом случае, пока только идея. Дайте мне знать, как это происходит, и если вам удастся решить его, возможно, опубликуйте свое решение.