【发布时间】:2017-10-21 06:26:47
【问题描述】:
我的 TFS 集线器扩展(内部部署 2015.3)由于意外的扩展数据服务行为且未获得所需的首选项而无法正确加载。扩展用户存储 - 在首次启动/加载中心页面期间安装一次后 - 集合级别的扩展首选项,作为键值对(来自扩展数据服务 API 的 getValue/setValue),如果中心页面重新加载首选项已存储。这就像我的中心页面中的应用程序向导/首次启动对话框。
但是,当我在同一 TFS 的另一个集合上安装扩展程序并希望为该集合存储 (=setValue) 首选项时,它返回 OK(可以在 F12->Internet Explorer 的网络捕获中看到它),但不能刷新(=getValue on key)我的集线器时,找到这些先前输入/存储的键值对。它为键提供了一个空值,并且“首次启动”对话框再次出现,如果键有值,则不应该发生什么。已经调试过,它总是在该集合中返回空(空值)。服务没有错误,没有什么可捕获的,没有什么可调试的。
我可以检查其他地方(TFS 日志、事件查看器或数据库)以进行更深入的调试吗?
我还尝试手动使用 Powershell 和 restcalls,方法是在扩展数据服务的 Rest url 上放置和获取 json。在一个集合中它可以工作(手动和每个集线器扩展),但对于另一个集合,数据服务不起作用。
2015.3 扩展数据服务中是否存在已知问题?如果我无法将扩展的首选项存储在任何地方,我真的有问题 - 将其存储到默认的源代码控制路径将是一种替代方案,但我不想强制项目签入我的扩展的首选项...
编辑: 添加相关代码sn -p
function showSourceControlDialog(project: string/*TFS_Core_Contracts.TeamProjectReference*/) {
return Q.Promise(function (resolve, reject) {
//setTimeout(function () {
var thatProjectIDclean = project/*.id*/.replace(/-/g, "_");
var enterSourceControlPathDialog = VSS_Controls_Dialogs.show(VSS_Controls_Dialogs.ModalDialog, {
title: "Please now enter source control path for " + thisProjectName /*project.name*/,
content: $("<p/>").addClass("confirmation-text").html("<label><b>Source Control Path</b> to preferences file, e.g. '$/" + thisProjectName /*thisCollectionName + "/" + project.name*/ + "/.../...xml:</label><input id='enterSourceControlPathInput' size='40'/>" /*+ projectName + ".xml"*/),
useBowtieStyle: true,
buttons: {
"Cancel": function () {
enterSourceControlPathDialog.close();
enterSourceControlPathDialog.dispose();
reject("cancelled");
},
"OK": function () {
sourceControlPath = $("input#enterSourceControlPathInput").val();
if (sourceControlPath) {
setConfiguration(thatProjectIDclean, sourceControlPath).then(function (setToThisPath) {
console.log(setToThisPath);
enterSourceControlPathDialog.close();
enterSourceControlPathDialog.dispose();
$(".bss-button").show();
$(".bss-tvc").show();
resolve(sourceControlPath);
}).catch(function (error) {
reject(error);
})
}
}
}
});
//}, 10000);
});
}
function setConfiguration(key: string, value: string) {
return Q.Promise(function (resolve, reject) {
// Get data service
VSS.getService(VSS.ServiceIds.ExtensionData).then(function (dataService: IExtensionDataService) {
// Set value in collection scope
dataService.setValue(pssVersion + "_" + key, value/*, { scopeType: "Project Collection" }*/).then(function (setToThis: string) {
console.log(pssVersion + "_" + key + " is now " + setToThis );
resolve(setToThis);
}, function (error) {
reject(error);
console.log(error);
}, function (error) {
reject(error);
console.log(error);
});
});
}
function getConfiguration(key: string) {
return Q.Promise(function (resolve, reject) {
// Get data service
VSS.getService(VSS.ServiceIds.ExtensionData).then(function (dataService: IExtensionDataService) {
// Get value in collection scope
dataService.getValue(pssVersion + "_" + key/*, { scopeType: "Project Collection" }*/).then(function (gotThis: string) {
sourceControlPath = gotThis;
console.log(pssVersion + "_" + key + " is " + gotThis );
resolve(gotThis);
}, function (error) {
reject(error);
console.log(error);
});
}, function (error) {
reject(error);
console.log(error);
});
});
}
try {
console.log(thisProjectIDclean);
getConfiguration(thisProjectIDclean).then(function (resultPath: string) {
console.log(resultPath);
console.log(sourceControlPath);
if (!resultPath) {
//getProjects().then(function (resultProjects: TFS_Core_Contracts.TeamProjectReference[]) {
// resultProjects.forEach(function (resultProject: TFS_Core_Contracts.TeamProjectReference) {
showSourceControlDialog(thisProjectID/*resultProject*/).then(function () {
getXMLTree();
}, function (error) {
console.log(error);
});
// }, function (error) {
// console.log(error);
// });
//}, function (error) {
// console.log(error);
//});
} else {
getXMLTree();
}
});
} catch (error) {
console.log(error);
}
【问题讨论】:
-
您需要提供一些代码来演示问题。
-
详细代码是多少?可以在 OneDrive 上分享吗?另一方面,我认为您无法检查其他内容以进行更深入的调试。
标签: tfs tfs-2015 azure-devops-rest-api