Dynamics 365 WebResource:async/await处理查找字段Promise问题排查
异步过滤Dynamics 365查找字段失效问题
尝试通过async/await异步调用函数从关联实体获取记录,以过滤目标查找字段。调试时能正确获取所有值,但查找字段仍显示全部记录而非过滤结果;断点显示await addMasterContratLookupFilter(formContext);处Promise状态为pending,结果返回undefined。此前使用XrmServiceToolkit可正常工作,切换为XrmWebApi后出现该问题。
相关代码
过滤逻辑函数
async function addMasterContratLookupFilter(formContext) { 'use strict'; debugger; var mzk_subcontract = formContext.getAttribute("mzk_subcontract").getValue(); if (mzk_subcontract !== null) { var mzk_subcontractId = null; if (mzk_subcontract !== null && mzk_subcontract.length > 0) { mzk_subcontractId = mzk_subcontract[0].id; mzk_subcontractId = mzk_subcontractId.replace(/[{}]/g, ""); } var query = '<fetch>' + '<entity name="mzk_contractmanagement">' + '<attribute name="mzk_contractmanagementid" />' + '<attribute name="mzk_mastercontractagreement" />' + '<order attribute="mzk_subcontract" descending="false" />' + '<filter type="and">' + '<condition attribute="mzk_contractmanagementid" operator="eq" value="' + mzk_subcontractId + '" />' + '<condition attribute="statecode" operator="eq" value="0" />' + '<condition attribute="mzk_contracttypevalue" operator="eq" value="275380001" />' + '</filter>' + '</entity>' + '</fetch>'; query = "?fetchXml=" + encodeURIComponent(query); try { const results = await Xrm.WebApi.retrieveMultipleRecords("mzk_contractmanagement", query); if (results.entities.length > 0) { var values = ''; for (var i = 0; i < results.entities.length; i++) { values += "<value>" + results.entities[i]["_mzk_mastercontractagreement_value"] + "</value>"; } if (values !== '') { var fetchXml = '<filter type="and">' + '<condition attribute="mzk_contractmanagementid" operator="in">' + values + '</condition>' + '</filter>'; formContext.getControl("mzk_mastercontractagreement").addCustomFilter(fetchXml); } else { // 省略的逻辑 } } else { // 省略的逻辑 } } catch (error) { console.log(error.message); } } }
表单加载触发函数
async function PopulateMasterContractAgreement(executionContext) { 'use strict'; const formContext = executionContext.getFormContext(); if (formContext.getAttribute("mzk_subcontract") !== null && formContext.getAttribute("mzk_subcontract").getValue() !== null) { formContext.getControl("mzk_mastercontractagreement").addPreSearch(async function () { await addMasterContratLookupFilter(formContext); }); } }
问题原因与修复方案
核心问题
- PreSearch事件不支持异步回调:Dynamics 365的
addPreSearch方法仅支持同步执行,异步回调的Promise pending状态会导致过滤器尚未添加就已打开查找界面。 - 查询条件逻辑错误:原fetch查询中用
mzk_contractmanagementid匹配subcontractId,逻辑完全错误,应该匹配关联字段mzk_subcontract。 - 过滤器属性与实体未指定:添加自定义过滤器时,未指定查找字段关联的目标实体逻辑名称,且条件属性错误(用了当前实体ID而非目标实体ID)。
修复步骤
1. 重构PreSearch事件绑定
将异步逻辑改为Promise链式调用,确保过滤器添加完成后刷新查找控件:
function PopulateMasterContractAgreement(executionContext) { 'use strict'; const formContext = executionContext.getFormContext(); const masterControl = formContext.getControl("mzk_mastercontractagreement"); // 移除重复绑定的PreSearch事件 masterControl.removePreSearch(addMasterContratLookupFilterHandler); // 添加同步回调,内部处理异步逻辑 masterControl.addPreSearch(addMasterContratLookupFilterHandler); function addMasterContratLookupFilterHandler() { addMasterContratLookupFilter(formContext) .then(() => masterControl.refresh()) .catch(err => console.error(err)); } }
2. 修正查询与过滤器逻辑
修复fetch查询条件,同时指定过滤器关联的实体逻辑名称:
async function addMasterContratLookupFilter(formContext) { 'use strict'; const mzk_subcontract = formContext.getAttribute("mzk_subcontract").getValue(); const masterControl = formContext.getControl("mzk_mastercontractagreement"); // 清空旧过滤器 masterControl.removeCustomFilter(); if (!mzk_subcontract || mzk_subcontract.length === 0) { return Promise.resolve(); } const mzk_subcontractId = mzk_subcontract[0].id.replace(/[{}]/g, ""); // 修正查询条件:匹配关联字段mzk_subcontract而非当前实体ID var query = '<fetch>' + '<entity name="mzk_contractmanagement">' + '<attribute name="mzk_mastercontractagreement" />' + '<filter type="and">' + '<condition attribute="mzk_subcontract" operator="eq" value="' + mzk_subcontractId + '" />' + '<condition attribute="statecode" operator="eq" value="0" />' + '<condition attribute="mzk_contracttypevalue" operator="eq" value="275380001" />' + '</filter>' + '</entity>' + '</fetch>'; query = "?fetchXml=" + encodeURIComponent(query); try { const results = await Xrm.WebApi.retrieveMultipleRecords("mzk_contractmanagement", query); // 提取有效目标实体ID const masterIds = results.entities .map(entity => entity["_mzk_mastercontractagreement_value"]) .filter(id => id); if (masterIds.length > 0) { const values = masterIds.map(id => `<value>${id}</value>`).join(''); // 假设mzk_mastercontractagreement关联的实体逻辑名称为mzk_contract,主键为mzk_contractid const fetchXml = `<filter type="and"><condition attribute="mzk_contractid" operator="in">${values}</condition></filter>`; // 指定关联实体逻辑名称,确保过滤器生效 masterControl.addCustomFilter(fetchXml, "mzk_contract"); } return Promise.resolve(); } catch (error) { console.error(error.message); return Promise.reject(error); } }
3. 绑定字段变更事件
在mzk_subcontract字段的OnChange事件中调用PopulateMasterContractAgreement,确保字段值变化时重新触发过滤逻辑。
内容的提问来源于stack exchange,提问作者Syed Irfan Ali Shah
相关产品推荐
相关产品推荐

