Dynamics 365 Web API:已保存查询无法获取关联实体全部列
解决Dynamics 365 Web API中通过SavedQuery获取关联实体属性的问题
我懂你遇到的痛点——明明在视图里已经加了Product实体的自定义字段(比如你说的Discount %),但用SavedQuery调用Web API检索OpportunityProduct时,只能拿到Product的名称,其他关联属性死活不返回。这其实是Dynamics 365 Web API的默认行为:使用savedQuery参数时,只会返回主实体(OpportunityProduct)的字段,关联实体的字段不会自动展开,哪怕视图里包含了它们。视图里显示关联字段只是UI层的渲染逻辑,API不会自动帮你完成关联查询。
下面给你两种可行的解决方案:
方法一:用$expand显式关联Product实体
直接在请求URL里添加$expand参数,指定要关联的Product实体,同时用$select明确列出需要获取的Product字段(包括你的自定义字段pub_discountpercentage)。这样API就会把关联Product的指定字段一并返回。
修改后的请求URL大概是这样:
const reqUrl = window.parent.Xrm.Page.context.getClientUrl() + "/api/data/v9.0/opportunityproducts?savedQuery=********-****-****-****-************" + "&$expand=productid($select=pub_discountpercentage,name,productnumber)";
然后在处理返回结果时,就可以直接从展开的productid对象里取自定义字段了:
var product = { "Number": results.value[i]["productnumber"], "Name": results.value[i]["_productid_value@OData.Community.Display.V1.FormattedValue"], "Unit": results.value[i]["_uomid_value@OData.Community.Display.V1.FormattedValue"], "PricePerUnit": results.value[i]["priceperunit@OData.Community.Display.V1.FormattedValue"], "Quantity": results.value[i]["quantity@OData.Community.Display.V1.FormattedValue"], "Discount": results.value[i]["manualdiscountamount@OData.Community.Display.V1.FormattedValue"], "Discount%": results.value[i]["productid"]["pub_discountpercentage"], // 如果需要格式化后的显示值,可启用下面这行(前提是保留了Prefer头的注释参数) // "Discount% Formatted": results.value[i]["productid/pub_discountpercentage@OData.Community.Display.V1.FormattedValue"], "ExtendedAmount": results.value[i]["extendedamount@OData.Community.Display.V1.FormattedValue"] };
方法二:通过SavedQuery的FetchXml来查询
如果你想严格遵循视图中配置的所有列来返回数据,可以先获取该SavedQuery对应的FetchXml,再用fetchXml参数发起查询,这样API会返回FetchXml里定义的所有字段(包括关联实体的字段)。
步骤如下:
- 先调用API获取目标SavedQuery的FetchXml:
const fetchReq = new XMLHttpRequest(); fetchReq.open("GET", window.parent.Xrm.Page.context.getClientUrl() + "/api/data/v9.0/savedqueries(********-****-****-****-************)?$select=fetchxml", true); fetchReq.setRequestHeader("OData-MaxVersion", "4.0"); fetchReq.setRequestHeader("OData-Version", "4.0"); fetchReq.setRequestHeader("Accept", "application/json"); fetchReq.onreadystatechange = function () { if (this.readyState === 4 && this.status === 200) { const savedQueryResult = JSON.parse(this.response); const rawFetchXml = savedQueryResult.fetchxml; // 对FetchXml进行URL编码 const encodedFetchXml = encodeURIComponent(rawFetchXml); // 发起最终的查询请求 const req = new XMLHttpRequest(); const reqUrl = window.parent.Xrm.Page.context.getClientUrl() + "/api/data/v9.0/opportunityproducts?fetchXml=" + encodedFetchXml; req.open("GET", reqUrl, true); // 这里复用你原来的请求头和回调逻辑即可 req.setRequestHeader("OData-MaxVersion", "4.0"); req.setRequestHeader("OData-Version", "4.0"); req.setRequestHeader("Accept", "application/json"); req.setRequestHeader("Prefer", "odata.include-annotations=\"*\""); req.onreadystatechange = function () { // 你的结果处理逻辑... }; req.send(); } }; fetchReq.send();
这样返回的结果就会包含视图中所有配置的字段,包括Product实体的自定义属性。
注意事项
- 确保你有访问Product实体对应字段的权限,否则API会返回权限错误或者忽略该字段。
- 如果使用
$expand,要注意Dynamics 365 Web API的关联深度限制,不过这里只是一级关联,完全没问题。
内容的提问来源于stack exchange,提问作者Zahir Firasta
相关产品推荐
相关产品推荐

