Dynamics 365 WebAPI获取业务流程流阶段及preStageChange校验问题
问题根本原因
preStageChange 事件是同步执行的,事件触发后平台会立即判断是否有调用 preventDefault(),不会等待异步逻辑执行完成:
- 你在事件触发时才发起 WebAPI 异步请求,请求返回时事件生命周期已经结束,此时再调用
preventDefault()自然失效 - Dataverse 表单事件原生不支持 async/await 等待异步逻辑执行,加 async 关键字也不会等待 Promise 完成
最优解决方案(完全规避异步问题)
BPF 阶段ID在同一个解决方案的不同环境中是固定不变的,不需要动态查询,直接硬编码目标阶段ID即可,代码全程同步执行,preventDefault() 可正常生效。
先获取目标阶段ID:打开业务流程流编辑器,选中「Socioeconomic Status」阶段,右侧属性面板即可复制该阶段的GUID。
正确代码示例
function preStageOnChange(executionContext) { var formContext = executionContext.getFormContext(); var eventArgs = executionContext.getEventArgs(); // 处理阶段ID格式,去掉大括号、转小写,避免匹配出错 var activeStageId = formContext.data.process.getActiveStage().getId().replace(/[{}]/g, '').toLowerCase(); // 替换为你实际的Socioeconomic Status阶段ID,同样去掉大括号转小写 var targetStageId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx".toLowerCase(); // 不是目标阶段直接放行 if (activeStageId !== targetStageId) { return; } let hasError = false; // 收入校验 if ( formContext.getAttribute("ava_netincome").getValue() == null && formContext.getAttribute("ava_investmentincome").getValue() == null && formContext.getAttribute("ava_otherincome").getValue() == null ) { formContext.ui.setFormNotification("至少填写一项收入信息", "ERROR", "income_error"); hasError = true; } else { formContext.ui.clearFormNotification("income_error"); } // 支出校验 if ( formContext.getAttribute("ava_householdexpenses").getValue() == null && formContext.getAttribute("ava_otherexpenses").getValue() == null ) { formContext.ui.setFormNotification("至少填写一项支出信息", "ERROR", "expense_error"); hasError = true; } else { formContext.ui.clearFormNotification("expense_error"); } // 贷款校验 if ( formContext.getAttribute("ava_currentloan").getValue() != null && formContext.getAttribute("ava_loanexpenses").getValue() == null ) { formContext.ui.setFormNotification("请填写贷款支出信息", "ERROR", "loan_error"); hasError = true; } else { formContext.ui.clearFormNotification("loan_error"); } // 有错误则阻止阶段跳转 if (hasError) { eventArgs.preventDefault(); } }
替代方案(必须动态查询阶段的场景)
如果确实需要动态适配不同环境的阶段名称,不要在preStageChange事件触发时才查询,改为在表单OnLoad事件中提前查询所有阶段并缓存到全局变量,preStageChange触发时直接读取缓存的阶段数据,全程同步执行即可。
内容的提问来源于stack exchange,提问作者Flashcap
相关产品推荐
相关产品推荐

