CRM 365 - 在需要执行验证时阻止 "onSave" 操作 FetchXML 查询
CRM 365 - Blocking the "onSave" operation when validations require FetchXMLQueries be executed
CRM365 表单提供“OnSave”事件以执行业务验证。
如果其中一项验证失败,我们可以使用“executionContext.getEventArgs().preventDefault()”来停止记录创建。
验证当前表单的字段都很好,但是,在某些情况下,验证还必须要求对实体记录执行查询。
例如,创建一个房间的预订必须检查是否有任何其他预先存在的预订,如果它们重叠则停止。
问题是 REST API 调用是异步的,需要时间来执行和 return 结果。当信息在响应中变得可用时,“OnSave”功能结束并且记录基本上未经验证就保存了。
我的问题如下:
是否与“executionContext.getEventArgs().preventDefault()”相反?我们可以停止保存操作,但是是否有任何“允许保存”的说法?
我试过“formContext.data.entity.save();”但由于我在“OnSave”事件中,它创建了一个无限循环。我几乎无法想象这个标志可以设置但不能重置。
是否可以有效地停止 Javascript 或使其“休眠”直到 REST API 数据可用?一切都围绕着 SetTimeout 函数,但这是一个非阻塞函数,我的 javascript 当然只是运行它。
我确定我不是唯一遇到这种情况的 运行,解决这些基于 REST API 的验证必须是模式。
我应该补充一点,我正在寻找基于客户端的解决方案;所有这些都可以相对容易地在插件或自定义工作流中实现。
感谢您的宝贵时间和帮助。
我发现了这个 link 并在新的 Dynamics Trial(2020 版本第 2 波)中对其进行了验证,XRM 组件似乎在那里:
Save and Close
的补充评论:https://dreamingincrm.com/2017/10/12/cancelling-save-event-based-on-the-result-of-async-operation/
编辑,使其不是“link-only”答案
- 使用
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);
}
}
})());
此代码示例的所有功劳均归原作者所有。
CRM365 表单提供“OnSave”事件以执行业务验证。 如果其中一项验证失败,我们可以使用“executionContext.getEventArgs().preventDefault()”来停止记录创建。 验证当前表单的字段都很好,但是,在某些情况下,验证还必须要求对实体记录执行查询。 例如,创建一个房间的预订必须检查是否有任何其他预先存在的预订,如果它们重叠则停止。 问题是 REST API 调用是异步的,需要时间来执行和 return 结果。当信息在响应中变得可用时,“OnSave”功能结束并且记录基本上未经验证就保存了。
我的问题如下:
是否与“executionContext.getEventArgs().preventDefault()”相反?我们可以停止保存操作,但是是否有任何“允许保存”的说法? 我试过“formContext.data.entity.save();”但由于我在“OnSave”事件中,它创建了一个无限循环。我几乎无法想象这个标志可以设置但不能重置。
是否可以有效地停止 Javascript 或使其“休眠”直到 REST API 数据可用?一切都围绕着 SetTimeout 函数,但这是一个非阻塞函数,我的 javascript 当然只是运行它。
我确定我不是唯一遇到这种情况的 运行,解决这些基于 REST API 的验证必须是模式。
我应该补充一点,我正在寻找基于客户端的解决方案;所有这些都可以相对容易地在插件或自定义工作流中实现。
感谢您的宝贵时间和帮助。
我发现了这个 link 并在新的 Dynamics Trial(2020 版本第 2 波)中对其进行了验证,XRM 组件似乎在那里:
Save and Close
的补充评论:https://dreamingincrm.com/2017/10/12/cancelling-save-event-based-on-the-result-of-async-operation/
编辑,使其不是“link-only”答案
- 使用
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);
}
}
})());
此代码示例的所有功劳均归原作者所有。