json CRM 2011:使用 Javascript 获取实体
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7874562/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
CRM 2011: Getting entity with Javascript
提问by musefan
I am working on some CRM 2011 Online customisations and I need to get an entity using javascript.
我正在处理一些 CRM 2011 Online 定制,我需要使用 javascript 获取实体。
The entity I need will be based on the ID value of another field (a Contact entity) - this Contact ID I can get fine.
我需要的实体将基于另一个字段(联系人实体)的 ID 值 - 这个联系人 ID 我可以得到很好的。
The entity I want is a custom entity. There may be multiple matches based on the Contact ID so I just want to get the first one in the list (order not important)
我想要的实体是自定义实体。根据联系人 ID 可能有多个匹配项,所以我只想获取列表中的第一个(顺序不重要)
So far I have looked into a few ways to do this...
到目前为止,我已经研究了几种方法来做到这一点......
OData - I couldn't find enough examples on this as to what query expressions I can create, also I don't know if/how to make this work for custom entities
FetchXML - I can create a nice FetchXML query using the built-in "advanced find" too and would be happy to call this from javascript if anyone can help? I found one promising answer herebut I could not see how the "results" return data was being set (Service.Fetch function)
SOAP Request - First thing I tried is a similar method as I could have done in CRM 4 but this does not seem to work. Although the request executes, my result data just seems to be empty. This is all I have code for so if any one can spot a problem with the code below then that would be great.
OData - 关于我可以创建哪些查询表达式,我找不到足够多的示例,我也不知道是否/如何使其适用于自定义实体
FetchXML - 我也可以使用内置的“高级查找”创建一个很好的 FetchXML 查询,如果有人可以提供帮助,我很乐意从 javascript 调用它?我在这里找到了一个有希望的答案,但我看不到“结果”返回数据是如何设置的(Service.Fetch 函数)
SOAP 请求 - 我尝试的第一件事是一种与我在 CRM 4 中可以做的类似的方法,但这似乎不起作用。虽然请求执行了,但我的结果数据似乎是空的。这就是我所有的代码,所以如果有人能发现下面代码的问题,那就太好了。
EDIT: I have spotted some redundant query data (I had removed link opening tags but left closing tags) - since removing this I now get XML result data... however, the where clause does not seem to apply (just get list of all entities)
编辑:我发现了一些冗余的查询数据(我已经删除了链接的开始标签但留下了结束标签) - 因为删除了这个,我现在得到了 XML 结果数据......但是,where 子句似乎并不适用(只是获取所有列表实体)
var xml = "<?xml version='1.0' encoding='utf-8'?>" +
"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" +
GenerateAuthenticationHeader() +
"<soap:Body>" +
"<RetrieveMultiple xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\">" +
"<query xmlns:q1=\"http://schemas.microsoft.com/crm/2006/Query\" xsi:type=\"q1:QueryExpression\">" +
"<q1:EntityName>new_vehicle</q1:EntityName>" +
"<q1:ColumnSet xsi:type='q1:ColumnSet'>" +
"<q1:Attributes>" +
"<q1:Attribute>new_vehicleid</q1:Attribute>" +
"<q1:Attribute>new_primarydriver</q1:Attribute>" +
"<q1:Attribute>statuscode</q1:Attribute>" +
"<q1:Attribute>new_registration</q1:Attribute>" +
"</q1:Attributes>" +
"</q1:ColumnSet>" +
"<q1:Distinct>false</q1:Distinct>" +
"<q1:Conditions>" +
"<q1:Condition>" +
"<q1:AttributeName>new_primarydriver</q1:AttributeName>" +
"<q1:Operator>Equal</q1:Operator>" +
"<q1:Values>" +
"<q1:Value xmlns:q2='http://microsoft.com/wsdl/types/' xsi:type='q2:guid'>" +
customerID +
"</q1:Value></q1:Values></q1:Condition>" +
"</q1:Conditions>" +
"</query></RetrieveMultiple>" +
"</soap:Body></soap:Envelope>";
var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xmlHttpRequest.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/RetrieveMultiple");
xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
xmlHttpRequest.send(xml);
var result = xmlHttpRequest.responseXML.xml;
var doc = new ActiveXObject("MSXML2.DOMDocument");
doc.async = false;
doc.loadXML(result);
var id = doc.selectSingleNode("//new_vehicleid");
var registration = doc.selectSingleNode("//new_registration");
if(id == null)
return null;
var vehicle = new Array();
value[0] = new Object();
value[0].id = id;
value[0].name = registration;
value[0].entityType = "new_vehicle";
return vehicle;
Sorry about the big code post but hopefully somebody who has a better understanding can help
对大代码帖子感到抱歉,但希望有更好理解的人可以提供帮助
回答by musefan
Firstly, thanks to GlennFerrieLive for his answer post. The samples I found with the Dynamics CRM 2011 SDK(well just one in particular) really helped and the JSON parser included was perfect for the job!
首先,感谢 GlennFerrieLive 的回答帖子。我在Dynamics CRM 2011 SDK 中找到的示例(尤其是其中一个)确实很有帮助,并且包含的 JSON 解析器非常适合这项工作!
I am posting this answer to give a full example of how I did it with some important comments to pay attention to which may not be so obvious from the SDK examples.
我发布这个答案是为了给出一个完整的例子,说明我是如何做到的,并有一些重要的评论需要注意,从 SDK 示例中可能不那么明显。
Get selected ID value from lookup field
从查找字段中获取选定的 ID 值
The aim of my task was to use javascript to get set a lookup field, based on the selected data of another lookup entity. The entity to set is "new_vehicle" and the entity to query on is "customer".
我的任务的目的是使用 javascript 根据另一个查找实体的选定数据设置查找字段。要设置的实体是“new_vehicle”,要查询的实体是“customer”。
First job is to get the ID value of the contact lookup field...
第一项工作是获取联系人查找字段的 ID 值...
var customerItem = Xrm.Page.getAttribute("customerid").getValue();
var customerID = customerItem[0].id;
Querying an entity using an ID
使用 ID 查询实体
Next is the part where I used the customerID value to find the vehicle that is currently assigned to them (the entity I want to use to set a lookup field).
接下来是我使用 customerID 值查找当前分配给他们的车辆的部分(我想用来设置查找字段的实体)。
First problem I found was that when querying with OData, the ID value does not seem to work with curly brackets {} - so these need to be removed...
我发现的第一个问题是,当使用 OData 查询时,ID 值似乎不适用于大括号 {} - 所以这些需要被删除......
customerID = customerID.replace('{', '').replace('}', '');
Next we get the oDataPath...
接下来我们得到 oDataPath...
var oDataPath = Xrm.Page.context.getServerUrl() + "/xrmservices/2011/organizationdata.svc";
Then we can construct the OData query...
然后我们可以构造 OData 查询...
var filter = "/new_vehicleSet?" +
"$select=new_vehicleId,new_Registration" +
"&$filter=new_PrimaryDriver/Id eq (guid'" + customerID + "')" +
"&$orderby=new_LastAllocationDate desc" +
"&$top=1";
NOTE: There are a couple of important things to note here...
注意:这里有几件重要的事情需要注意......
- When using a guid value you must explicitly say it is a guid using
(guid'xxx') - When filtering by a lookup entity (e.g. new_PrimaryDriver) you must append the value to query (e.g. Id) - this results in new_PrimaryDriver/Id
- 使用 guid 值时,您必须明确说明它是使用的 guid
(guid'xxx') - 当通过查找实体(例如 new_PrimaryDriver)过滤时,您必须将值附加到查询(例如 Id) - 这会导致 new_PrimaryDriver/Id
Once we have the query setup we can request the data as follows...
完成查询设置后,我们可以按如下方式请求数据...
var retrieveRecordsReq = new XMLHttpRequest();
retrieveRecordsReq.open("GET", oDataPath + filter, true);
retrieveRecordsReq.setRequestHeader("Accept", "application/json");
retrieveRecordsReq.setRequestHeader("Content-Type", "application/json; charset=utf-8");
retrieveRecordsReq.onreadystatechange = function () {
if (this.readyState == 4) {
if (this.status == 200) {
var retrievedRecords = JSON.parse(retrieveRecordsReq.responseText).d;
if(retrievedRecords.results.length > 0)
{
var vehicle = retrievedRecords.results[0];
SetLookup("new_replacedvehicle", vehicle.new_vehicleId, vehicle.new_Registration, "new_vehicle");
}
}
}
};
retrieveRecordsReq.send();
Note that this is an asynchronous call and the onreadystatechange function will be processed upon completion, in this function we do a couple of checks to see if it was a success and the we parse the resulting JSON data - the JSON.Parse function has been included at the bottom of this post (but is available from the SDK)
请注意,这是一个异步调用,并且 onreadystatechange 函数将在完成后进行处理,在此函数中,我们进行了一些检查以查看它是否成功并解析生成的 JSON 数据 - 已包含 JSON.Parse 函数在这篇文章的底部(但可以从SDK 获得)
Setting a lookup field using the entity queried above
使用上面查询的实体设置查找字段
The other function to make note of here is SetLookup which is just a simple helper function I added to set a lookup field. This is as follows...
这里要注意的另一个函数是 SetLookup,它只是我添加的一个简单的辅助函数来设置查找字段。这是如下...
function SetLookup(fieldName, idValue, textValue, typeValue)
{
var value = new Array();
value[0] = new Object();
value[0].id = idValue;
value[0].name = textValue;
value[0].typename = typeValue;
Xrm.Page.getAttribute(fieldName).setValue(value);
}
JSON parse function
JSON 解析函数
This is the JSON helper function that was used in the above code (JSON.parse), pasted as it was found in the SDK...
这是上面代码 ( JSON.parse) 中使用的 JSON 辅助函数,粘贴时在 SDK 中找到...
if (!this.JSON) { this.JSON = {}; } (function () { function f(n) { return n < 10 ? '0' + n : n; } if (typeof Date.prototype.toJSON !== 'function') { Date.prototype.toJSON = function (key) { return isFinite(this.valueOf()) ? this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours()) + ':' + f(this.getUTCMinutes()) + ':' + f(this.getUTCSeconds()) + 'Z' : null; }; String.prototype.toJSON = Number.prototype.toJSON = Boolean.prototype.toJSON = function (key) { return this.valueOf(); }; } var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, escapable = /[\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, gap, indent, meta = { '\b': '\b', '\t': '\t', '\n': '\n', '\f': '\f', '\r': '\r', '"': '\"', '\': '\\' }, rep; function quote(string) { escapable.lastIndex = 0; return escapable.test(string) ? '"' + string.replace(escapable, function (a) { var c = meta[a]; return typeof c === 'string' ? c : '\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); }) + '"' : '"' + string + '"'; } function str(key, holder) { var i, k, v, length, mind = gap, partial, value = holder[key]; if (value && typeof value === 'object' && typeof value.toJSON === 'function') { value = value.toJSON(key); } if (typeof rep === 'function') { value = rep.call(holder, key, value); } switch (typeof value) { case 'string': return quote(value); case 'number': return isFinite(value) ? String(value) : 'null'; case 'boolean': case 'null': return String(value); case 'object': if (!value) { return 'null'; } gap += indent; partial = []; if (Object.prototype.toString.apply(value) === '[object Array]') { length = value.length; for (i = 0; i < length; i += 1) { partial[i] = str(i, value) || 'null'; } v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : '[' + partial.join(',') + ']'; gap = mind; return v; } if (rep && typeof rep === 'object') { length = rep.length; for (i = 0; i < length; i += 1) { k = rep[i]; if (typeof k === 'string') { v = str(k, value); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } } else { for (k in value) { if (Object.hasOwnProperty.call(value, k)) { v = str(k, value); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } } v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : '{' + partial.join(',') + '}'; gap = mind; return v; } } if (typeof JSON.stringify !== 'function') { JSON.stringify = function (value, replacer, space) { var i; gap = ''; indent = ''; if (typeof space === 'number') { for (i = 0; i < space; i += 1) { indent += ' '; } } else if (typeof space === 'string') { indent = space; } rep = replacer; if (replacer && typeof replacer !== 'function' && (typeof replacer !== 'object' || typeof replacer.length !== 'number')) { throw new Error('JSON.stringify'); } return str('', { '': value }); }; } if (typeof JSON.parse !== 'function') { JSON.parse = function (text, reviver) { var j; function walk(holder, key) { var k, v, value = holder[key]; if (value && typeof value === 'object') { for (k in value) { if (Object.hasOwnProperty.call(value, k)) { v = walk(value, k); if (v !== undefined) { value[k] = v; } else { delete value[k]; } } } } return reviver.call(holder, key, value); } text = String(text); cx.lastIndex = 0; if (cx.test(text)) { text = text.replace(cx, function (a) { return '\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); }); } if (/^[\],:{}\s]*$/.test(text.replace(/\(?:["\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').replace(/"[^"\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { j = eval('(' + text + ')'); return typeof reviver === 'function' ? walk({ '': j }, '') : j; } throw new SyntaxError('JSON.parse'); }; } } ());

