模型驱动应用中阻止用户自选的XRM脚本失效问题排查
模型驱动应用中阻止Lookup字段选择自身的脚本失效问题排查与修复
问题概述
开发了客户端脚本,意图阻止用户在关联AAD User表的Lookup字段(digphil_peerreviewer)中选择自身,但脚本未生效,用户仍可选择自己。原代码如下:
function preventSelfSelection(executionContext) { var formContext = executionContext.getFormContext(); // Retrieve the current user ID without curly braces var userId = Xrm.Utility.getGlobalContext().userSettings.userId.replace("{", "").replace("}", ""); console.log("Current User ID: ", userId); // Retrieve AAD ObjectId of the current user via Web API Xrm.WebApi.retrieveRecord("systemuser", userId, "?$select=azureactivedirectoryobjectid").then( function success(result) { var currentAADObjectId = result.azureactivedirectoryobjectid; console.log("Current User AAD ObjectId: ", currentAADObjectId); // Get the AAD ObjectId from the "digphil_peerreviewer" field var peerreviewer = formContext.getAttribute("digphil_peerreviewer").getValue(); if (peerreviewer && peerreviewer.length > 0) { // Retrieve the selected user ID without curly braces var selectedUserId = peerreviewer[0].id.replace("{", "").replace("}", ""); console.log("Selected User ID: ", selectedUserId); // Get AAD ObjectId of the selected user Xrm.WebApi.retrieveRecord("systemuser", selectedUserId, "?$select=azureactivedirectoryobjectid").then( function success(peerreviewerResult) { var selectedAADObjectId = peerreviewerResult.azureactivedirectoryobjectid; console.log("Selected User AAD ObjectId: ", selectedAADObjectId); if (currentAADObjectId.toLowerCase() === selectedAADObjectId.toLowerCase()) { formContext.getControl("digphil_peerreviewer").setNotification("You cannot select yourself", "self_selection_error"); formContext.getAttribute("digphil_peerreviewer").setValue(null); console.log("User attempted to select themselves. Resetting field."); } else { formContext.getControl("digphil_peerreviewer").clearNotification("self_selection_error"); } }, function(error) { console.log("Error fetching selected user AAD ObjectId: ", error.message); // Handle error } ); } }, function(error) { console.log("Error fetching current user AAD ObjectId: ", error.message); // Handle error } ); };
问题原因分析
- 事件绑定错误:脚本大概率只绑定了表单
OnLoad事件,未绑定digphil_peerreviewer字段的OnChange事件。Lookup字段值变化时不会触发OnLoad,导致校验逻辑完全不执行。 - 冗余异步请求导致延迟:原代码通过两次
Xrm.WebApi.retrieveRecord获取AAD ObjectId做对比完全没必要——Lookup字段关联的是systemuser表,选中值的id就是当前环境的系统用户ID,直接对比即可。异步请求会导致校验不及时,甚至用户已经保存记录后才触发字段重置。 - 未处理字段清空场景:当用户清空
digphil_peerreviewer字段时,原代码不会清除已有的通知,导致提示残留。
修复后的代码
function preventSelfSelection(executionContext) { try { var formContext = executionContext.getFormContext(); if (!formContext) return; // 获取当前用户ID(保留大括号,与Lookup返回的ID格式一致) var currentUserId = Xrm.Utility.getGlobalContext().userSettings.userId; var peerReviewerAttr = formContext.getAttribute("digphil_peerreviewer"); var peerReviewerCtrl = formContext.getControl("digphil_peerreviewer"); // 先清除之前的通知,避免残留 peerReviewerCtrl.clearNotification("self_selection_error"); var selectedUser = peerReviewerAttr.getValue(); if (selectedUser && selectedUser.length > 0) { var selectedUserId = selectedUser[0].id; // 直接对比系统用户ID,无需绕路查AAD ObjectId if (selectedUserId.toLowerCase() === currentUserId.toLowerCase()) { peerReviewerCtrl.setNotification("不能选择自己", "self_selection_error"); peerReviewerAttr.setValue(null); console.log("用户尝试选择自己,已重置字段"); } } } catch (error) { console.log("校验逻辑执行出错:", error.message); } }
关键修复点说明
- 绑定正确事件:将脚本绑定到
digphil_peerreviewer字段的OnChange事件,确保字段值变化时立即触发校验。 - 移除冗余异步请求:直接对比当前用户ID与Lookup选中的用户ID,避免异步延迟,提升响应速度。
- 完善异常处理:增加
try-catch捕获执行错误,避免脚本崩溃影响其他表单逻辑。 - 处理字段清空场景:每次执行校验前先清除通知,避免提示残留。
额外优化建议
- 视图层面过滤:如果业务允许,可以修改
digphil_peerreviewer字段对应的Lookup视图,添加过滤条件systemuserid ne {当前用户ID},从源头阻止用户看到自己,减少前端校验的必要性。 - 统一ID格式:保留ID的大括号格式直接对比,避免字符串替换可能出现的格式错误。
内容的提问来源于stack exchange,提问作者LostMary
相关产品推荐
相关产品推荐

