问题描述
CRM365表单提供“ OnSave”事件,以便能够执行业务验证。 如果验证之一失败,我们可以使用“ executionContext.getEventArgs()。preventDefault()”来停止记录的创建。 最好验证当前表单的字段,但是,在某些情况下,验证还必须要求对实体记录执行查询。 例如,创建房间的预订必须检查是否有任何其他预先存在的预订,如果它们重叠则停止。 问题在于,REST API调用是异步的,需要时间来执行和返回结果。等到响应中的信息可用时,“ OnSave”功能就结束了,记录基本上没有验证就保存了。
我的问题如下:
-
“ executionContext.getEventArgs()。preventDefault()”是否相反?我们可以停止保存操作,但是可以说是“允许保存”吗? 我已经尝试过“ formContext.data.entity.save();”但是由于我处于“ OnSave”事件中,因此创建了一个无限循环。我几乎无法想象可以设置但不能重置此标志。
-
在REST API数据可用之前,停止Java脚本或使其“休眠”是否有效?一切都围绕着SetTimeout函数,但这是一个非阻塞函数,我的JavaScript当然就通过它运行。
我确定我不是唯一遇到这种情况的人,这必须是解决这些基于REST API的验证的模式。
我应该补充一点,就是我正在寻找基于客户端的解决方案;所有这些可能相对容易在插件或自定义工作流程中实现。
感谢您的时间和帮助。
解决方法
我找到了此链接,并在新的Dynamics Trial(2020年发布第二波)中对其进行了验证,并且XRM组件似乎在那里:
针对Save and Close
:https://dreamingincrm.com/2017/10/12/cancelling-save-event-based-on-the-result-of-async-operation/
编辑,以使其不是“仅链接”答案
-
使用
Clone
创建Xrm.Page.ui
和Xrm.Page.data.entity
的副本-这样,如果用户按下Save and Close
,这些对象仍然可用 -
创建使用
saveHandler
模拟异步验证过程的RetrieveMultiple
方法Xrm.Page.data.entity.addOnSave((((=)=> { let isSave = false; var uiClone = parent.jQuery.extend(true,{},Xrm.Page.ui); var entityClone = parent.jQuery.extend(true,{},Xrm.Page.data.entity);
var closeHandler = ()=>{ console.log('local. close blocked.'); }; var saveHandler = (ev)=>{ console.log('local. save blocked.'); Xrm.WebApi.retrieveMultipleRecords('systemuser','$select=fullname,jobtitle,homephone').then(x=>{ isSave = !x.entities.some(x=>x.homephone == '12345'); if(isSave){ Xrm.Page.data.entity.save = entityClone.save; Xrm.Page.ui.close = uiClone.close; if((typeof ev === 'string' && ev === 'saveandclose') || (ev.getEventArgs && ev.getEventArgs() && ev.getEventArgs().getSaveMode() === 2)){ console.log('saveandclose'); entityClone.save('saveandclose'); } else{ console.log('save'); entityClone.save(); } } else{ console.log('User with homephone 12345 exists. Save blocked.'); } }); }; return (e)=>{ var eventArgs = e.getEventArgs(); console.log(`DataXml OnSave: ${Xrm.Page.data.entity.getDataXml()}`); console.log(`Save Mode: ${eventArgs.getSaveMode()}`); if(isSave) { console.log('proceed to save'); Xrm.Page.data.entity.save = entityClone.save; Xrm.Page.ui.close = uiClone.close; return; } else{ Xrm.Page.data.entity.save = saveHandler; Xrm.Page.ui.close = closeHandler; if(eventArgs.getSaveMode() !== 2){ eventArgs.preventDefault(); } saveHandler(e); } }
})());
此代码示例的所有功劳归原始作者。