Dynamics JavaScript Web Resource控制台日志跳转失效问题排查
控制台日志文件链接无法跳转的排查方案
针对你遇到的控制台日志文件链接无法跳转的问题,结合你提供的代码,我整理了几个常见原因和解决办法:
一、核心原因分析
1. 代码为内嵌脚本而非外部文件
如果这段JavaScript代码是直接内嵌在Dynamics 365表单的命令按钮脚本中(没有通过外部Web资源引用),控制台日志里的文件链接会指向平台动态生成的脚本容器(比如form.js或匿名脚本块),而非你的实际代码文件,自然无法跳转。
2. 缺少源映射(Source Map)
如果代码经过压缩/混淆后部署,且没有上传对应的.map源映射文件,控制台无法将压缩后的代码映射回原始文件,导致链接失效。
3. Dynamics 365脚本加载机制限制
Dynamics 365会将表单相关脚本打包加载,控制台日志中的文件路径可能是平台内部的临时路径,而非你实际开发的文件路径。
二、解决办法
1. 将代码迁移到外部Web资源
在Dynamics 365中创建一个新的JavaScript Web资源,把你的代码复制进去,然后修改按钮命令的配置,让它引用这个Web资源中的HandleSyncTask函数。这样控制台日志就会关联到这个Web资源文件,点击链接就能直接跳转。
2. 启用源映射(若代码压缩)
如果你的代码是压缩后上传的,确保同时生成并上传对应的.map文件作为Web资源,控制台会自动识别源映射,实现压缩代码到原始文件的跳转。
3. 检查脚本注册配置
确认按钮命令的“库”字段选择的是你上传的外部Web资源,而非直接在“函数”字段里写内嵌代码。
三、代码小问题提示
顺便提一下,你的代码里有两个潜在问题,建议修正:
openSyncTaskCompleteDialog函数里的拼写错误:concole.log应为console.log,否则报错时无法正常输出日志getOrgTasks函数里的变量错误:tokenReq.open之后的taskReq.setRequestHeader应该是tokenReq.setRequestHeader,否则会触发taskReq is not defined的报错
以下是你提供的完整代码(已格式化):
function HandleSyncTask(commandProperties, primaryControl) { console.log("HandleSyncTask running..."); openSyncTaskConfirmDialog(commandProperties, primaryControl); } function openSyncTaskConfirmDialog(commandProperties, primaryControl) { console.log("Opening confirm dialog..."); var confirmStrings = { cancelButtonLabel: "No", confirmButtonLabel: "Yes", title: "Preparing Tasks Sync", subtitle: "Are you sure you want to Sync Tasks?" }; var confirmOptions = { height: 200, width: 450 }; Xrm.Navigation.openConfirmDialog(confirmStrings, confirmOptions).then( success => { if (success.confirmed) { console.log("openSyncTaskConfirmDialog confirmed."); getOrgTasks(commandProperties, primaryControl); } else { console.log("openSyncTaskConfirmDialog closed."); } }, error => { console.log(error.message); }); } function openSyncTaskCompleteDialog() { var alertStrings = { confirmButtonLabel: "Okay", text: "Sync task complete" }; var alertOptions = { height: 120, width: 260 }; Xrm.Navigation.openAlertDialog(alertStrings, alertOptions).then( function success(result) { console.log("openSyncTaskCompleteDialog dialog closed"); }, function (error) { console.log(error.message); // 修正了拼写错误 } ); } function getOrgTasks(commandProperties, primaryControl) { console.log("In getOrgTasks"); var stsToken = ""; var tokenReq = new XMLHttpRequest(); var tokenReqParams = "grant_type=password&scope=OrgApi&username={REMOVED FOR STACKOVERFLOW}&password={REMOVED FOR STACKOVERFLOW}"; tokenReq.addEventListener("readystatechange", function () { if (this.readyState === 4) { if (this.status == 200) { console.log("SUCCESS sts/connect/token"); var tokenObject = JSON.parse(this.responseText); stsToken = tokenObject.access_token.toString(); } } }); tokenReq.open("POST", "https://orgdev.azurewebsites.net/sts/connect/token", true); tokenReq.setRequestHeader("Accept", "application/json"); // 修正了变量名错误 tokenReq.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); tokenReq.setRequestHeader("Authorization", "Basic {REMOVED FOR STACKOVERFLOW}"); tokenReq.setRequestHeader("Cache-Control", "no-cache"); console.log("About to SEND sts/connect/token"); tokenReq.send(tokenReqParams); var challengeTasks = []; var orgConfigurationEntityReference = primaryControl.getGrid().getRows().get(0).data.entity.getEntityReference(); var orgConfigurationEntityType = orgConfigurationEntityReference["entityType"].toString(); var orgConfigurationGuid = orgConfigurationEntityReference["id"].toString(); Xrm.WebApi.retrieveRecord(orgConfigurationEntityType, orgConfigurationGuid, "?$expand=org_org_orgconfiguration_org_orgchallenge_orgconfigurationid").then( function success(result) { console.log("SUCCESS retrieveRecord"); var taskReq = new XMLHttpRequest(); taskReq.withCredentials = true; taskReq.addEventListener("readystatechange", function () { if (this.readyState === 4) { if (this.status == 200) { challengeTasks = JSON.parse(this.responseText); } } }); taskReq.open("GET", `https://orgdev.azurewebsites.net/api/${result.org_org_orgconfiguration_org_orgchallenge_orgconfigurationid[0]["org_orgid"]}/tasks`, false); taskReq.setRequestHeader("Accept", "application/json"); taskReq.setRequestHeader("Authorization", "Bearer " + stsToken); taskReq.setRequestHeader("Content-Type", "application/json"); taskReq.setRequestHeader("Cache-Control", "no-cache"); taskReq.send(); var orgTrigger = { }; var orgEntityName = ""; Xrm.Utility.showProgressIndicator("Syncing Tasks..."); for (var i = 0; i < challengeTasks.length; i++) { orgEntityName = challengeTasks[i].primaryobjecttypecode[0].toUpperCase() + challengeTasks[i].primaryobjecttypecode.slice(1); orgTrigger = { "org_name": challengeTasks[i].name + " " + orgEntityName, "org_entityname": orgEntityName, "org_messagename": challengeTasks[i].name, // org_org_orgtask_org_orgtrigger // navigation property (1:N), DataModel/orgCrmSdkTypes, generated class using the CrmSvcUtil.exe "org_org_orgtrigger_org_orgtask_orgtriggerid": [ { "org_name": challengeTasks[i].Title, "org_orgtaskidreference": challengeTasks[i].TaskId, "org_enabled": true, "org_pointvalue": challengeTasks[i].EligiblePoints } ] }; Xrm.WebApi.createRecord("org_orgtrigger", orgTrigger).then( function success(result) { console.log("Created task and attached trigger to it, trigger is "); }); } Xrm.Utility.closeProgressIndicator(); openSyncTaskCompleteDialog(); }, function (error) { console.log(error.message); }); }
内容的提问来源于stack exchange,提问作者greg
相关产品推荐
相关产品推荐

