Чтож, приведу примеры для версии MS CRM 2011. Примеры, потому, что можно запрашивать данные с клиента двумя способами. Не скажу, что способы кардинально разные, но подходы в них рознятся.
Способ 1:
X++:
// Функция возврата значения lookup-атрибута на основе SOAP-запроса к связанной сущности
function GetLookupByEntityId(entityName, entityId, attributeName) {
// Определение параметров запроса Retrieve для отправки
var xml = '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">' +
'<s:Body>' +
' <Retrieve xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">' +
' <entityName>' + entityName + '</entityName>' +
' <id>' + entityId + '</id>' +
' <columnSet xmlns:a="http://schemas.microsoft.com/xrm/2011/Contracts">' +
' <a:AllColumns>false</a:AllColumns>' +
' <a:Columns xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/Arrays">' +
' <b:string>' + attributeName + '</b:string>' +
' </a:Columns>' +
' </columnSet>' +
' </Retrieve>' +
'</s:Body>' +
'</s:Envelope>';
// Формирование и отправка POST-запроса
var req = new XMLHttpRequest();
req.open('POST', Xrm.Page.context.getServerUrl() + '/XRMServices/2011/Organization.svc/web', false);
req.setRequestHeader('Accept', 'application/xml, text/xml, */*');
req.setRequestHeader('Content-Type', 'text/xml; charset=utf-8');
req.setRequestHeader('SOAPAction', 'http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Retrieve');
req.send(xml);
// Обработка результата запроса
var retValue = null;
if (req.status == 200) {
var doc = req.responseXML;
// обработка результата запроса в общем случае - есть парсинг массива полученных атрибутов:
var lAttrList = doc.getElementsByTagName('a:Attributes');
if (lAttrList != null) {
// но т. к. мы определили для вывода единственный атрибут по имени, то в массиве атрибутов
// интересует первый элемент (под индексом 0), который должен содержать массив пар "ключ-значение":
var lAttrPairs = lAttrList[0].getElementsByTagName('a:KeyValuePairOfstringanyType');
for (var i = 0; i < lAttrPairs.length; i++) {
if (lAttrPairs[i].selectSingleNode('b:key').nodeTypedValue == attributeName) {
// Интересующая пара найдена по значению ключа соотв. названию атрибута,-
// значит её значение содержит запрашиваемый объект
var refData = lAttrPairs[i].selectSingleNode('b:value');
var newRef = new Object();
newRef.entityType = refData.selectSingleNode('a:LogicalName').nodeTypedValue;
newRef.id = refData.selectSingleNode('a:Id).nodeTypedValue;
newRef.name = refData.selectSingleNode('a:Name').nodeTypedValue;
retValue = new Array(newRef);
break;
}
}
}
} // В случае, если результат отправки неудовлетворителен т. е. req.status != 200 - можно предусмотреть:
// а). инструкцию, выдающую предупреждение о невозможности получения данных; и/или:
// б). фиксацию отрицательного результата в предусмотренном для этого логе
return retValue;
}
Способ 2 (изощренный и требующий тщательного разбора):
X++:
// Вспомогательная функция 1 (привел в таком виде, ибо неохота было вычленять нужное из рабочих скриптов)
function InitArray(arrayData) {
var array = new Array();
if (arrayData && arrayData.length > 0)
for (var i = 0; i < arrayData.length; i++) {
array.push(arrayData[i]);
}
if (array.all) array.all = array;
if (!array.Type) array.Type = 'Array';
if (!array.ForEach) array.ForEach = function (method, array) {
if (!array) array = this;
else InitArray(array);
for (var i = 0; i < array.length; i++) {
if (method(array[i]) == 'stop') break;
}
return array;
};
if (!array.Get) array.Get = function (index) {
if (this.length <= index || index < 0) return null;
return array[index];
};
if (!array.First) array.First = function () {
return this.Get(0);
};
if (!array.Last) array.Last = function () {
return this.Get(this.length - 1);
};
return array;
}
// Функция возврата значения lookup-атрибута на основе запроса к связанной сущности
function GetEntityLookupAttrib(entityName, entityId, attributeName) {
// Объект - запрос
var XmlHttp3Request = {
/*Описывает возможне методы отправки запроса через XmlHttpRequest*/
ENUM_Methods: {
Get: 'GET', //Данный метод используется при первом запросе ресурса, дальнейшие одинаковые запросы берутся из кэша
Post: 'POST', //Данный метод предотвращает любое кэширование, его можно использовать для одинаковых запросов, которе необходимо НЕ кэшировать
Head: 'HEAD' //Данный метод используется для полученя заголовков и информации о размере ответа
},
/*
ОПИСАНИЕ: Отправляет запрос через XmlHttpRequest
ПАРАМЕТРЫ:
params
{
Url, //+URL на который отправляется запрос
CallBack, //+Метод выполняемый при успешном завершении запроса function(XmlHttpRequest oReq)
ErrorCallBack, //+Метод выполняемый при НЕ успешном завершении запроса function(XmlHttpRequest oReq)
Method, //-Значение XmlHttp3Request.ENUM_Methods (по умолчанию XmlHttp3Request.ENUM_Methods.Get)
Async, //-Если true то запрос будет асинхронным
Body, //-Если метод POST то содержимое данного параметра будет отправлено в теле сообщения
Headers //-Массив объектов { Name: n, Value: v }
}
*/
Send: function (params) {
if (!params.Url) throw 'Please specify "params.url" property!!!';
if (!params.CallBack) throw 'Please specify "params.callBack" property!!!';
if (!params.ErrorCallBack) throw 'Please specify "params.errorCallBack" property!!!';
if (!params.Method) params.Method = "GET";
if (!params.Async) params.Async = false;
var oReq = new ActiveXObject('MSXML2.XMLHTTP.3.0');
oReq.open(params.Method, params.Url, params.Async);
if (params.Headers) {
params.Headers.ForEach(function (h) {
oReq.setRequestHeader(h.Name, h.Value);
});
}
oReq.onreadystatechange = function () {
if (oReq.readyState == 4 /* complete */) {
if (oReq.status == 200) {
params.CallBack(oReq);
}
else {
params.ErrorCallBack(oReq);
}
}
};
switch (params.Method) {
default:
case XmlHttp3Request.ENUM_Methods.Get:
oReq.send();
break;
case XmlHttp3Request.ENUM_Methods.Post:
if (params.Body) oReq.setRequestHeader('Content-Length', params.Body.length);
oReq.send(params.Body);
break;
}
}
};
var retValue = null;
var salt = '&salt=' + (new Date()).toUTCString();
var oData = "$select=" + attributeName + "&$filter=" + entityName + "Id eq (guid'" + entityId + "')";
XmlHttp3Request.Send({
Async: async,
Url: Xrm.Page.context.getServerUrl() + '/XRMServices/2011/OrganizationData.svc/' + entityName + 'Set?' + oData + salt,
Method: XmlHttp3Request.ENUM_Methods.Get,
CallBack: function (oReq) {
var xmlDoc = new ActiveXObject('Microsoft.XMLDOM');
xmlDoc.async = false;
xmlDoc.loadXML(oReq.responseText);
var data = xmlDoc.selectSingleNode('//d:' + attributeName);
if (data && data.text.length > 0) {
var newRef = new Object();
newRef.entityType = data.selectSingleNode('//d:LogicalName').text;
newRef.id = data.selectSingleNode('//d:Id).text;
newRef.name = data.selectSingleNode('//d:Name').text;
retValue = new Array(newRef);
}
},
ErrorCallBack: function (oReq) {
alert(oReq.responseText); // выдача предупреждения об ошибке
},
Headers: InitArray([
{ Name: 'Content-Type', Value: 'text/xml; charset=utf-8' }
])
});
return retValue;
}
Вопросы?