javascript - CRM 365 - 在验证需要执行 FetchXMLQueries 时阻止“onSave”操作
问题描述
CRM365 表单提供“OnSave”事件以便能够执行业务验证。如果其中一项验证失败,我们可以使用“executionContext.getEventArgs().preventDefault()”来停止记录创建。验证当前表单的字段都很好,但是,在某些情况下,验证还必须要求对实体记录执行查询。例如,创建房间预订必须检查是否有任何其他预先存在的预订,如果它们重叠则停止。问题是 REST API 调用是异步的,需要时间来执行和返回结果。当信息在响应中可用时,“OnSave”功能已经结束,记录基本上没有验证就保存了。
我的问题如下:
是否与“executionContext.getEventArgs().preventDefault()”相反?我们可以停止保存操作,但有任何“允许保存”之类的说法吗?我试过“formContext.data.entity.save();” 但由于我在“OnSave”事件中,它创建了一个无限循环。我几乎无法想象这个标志可以设置但不能重置。
在 REST API 数据可用之前停止 Javascript 或使其“休眠”是否有效?一切都围绕 SetTimeout 函数,但这是一个非阻塞函数,我的 javascript 只是运行它,当然。
我确信我不是唯一遇到这种情况的人,它必须是解决这些基于 REST API 的验证的模式。
我可能应该补充一点,我正在寻找基于客户端的解决方案;所有这些都可以在插件或自定义工作流程中相对容易地实现。
感谢您的时间和帮助。
解决方案
我找到了这个链接,并在新的 Dynamics Trial(2020 版第 2 波)中对其进行了验证,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);
}
}
})());
此代码示例的所有功劳归原作者所有。
推荐阅读
- sql-server - 使用其他表中的值在表上创建主键
- unity3d - 在 Oculus 上突出显示触摸控制器按钮以进行教程
- mysql - MySQL 与 PostgreSQL 重复
- socket.io - Cloud Firestore - 两个播放器 - 检测断开连接 [Flutter]
- spring - 如何在多个假装客户端之一中禁用 hystrix
- java - 创建名为“userController”的 bean 时出错:通过字段“userService”表达的不满足的依赖关系
- python - 读取文件时的Python UnicodeEncodeError
- node.js - Websocket 431 错误:意外的服务器响应
- python - Pygame 参数 2 必须是 pygame.surface 而不是 str
- python - Python docker 容器使用 print()