1

我是 Project Server 开发的新手,想知道是否可以使用 PSI 设置资源自定义字段值。

我似乎找不到任何适合初学者的信息。

我目前为 CustomFields 和 Resource Web 服务设置了 Web 引用,但不确定如何为特定资源设置自定义字段。

任何帮助将非常感激!

谢谢!

4

1 回答 1

6

我知道你的问题。微软在 MSDN 上有非常糟糕的例子。很多东西不起作用,或者只是从 2007 年手册中复制而来。我昨天开始使用 Project Server 2010 的 Web 服务进行开发。

这是设置自定义字段的简单(可能不是最佳)解决方案:

完整源代码: http: //pastebin.com/tr7CGJsW

准备您的解决方案

首先,我添加了一个服务参考:

http://servername/instance/_vti_bin/PSI/Project.asmx?wsdl

服务参考

之后,我编辑了 app.config,因为我必须使用特殊凭据才能登录到项目服务器(也许这不一定适合你):

...
  <security mode="TransportCredentialOnly">
    <transport clientCredentialType="Ntlm" proxyCredentialType="Ntlm" realm="" />
    <message clientCredentialType="UserName" algorithmSuite="Default" />
  </security>
    <!--<security mode="None">
        <transport clientCredentialType="None" proxyCredentialType="None"
            realm="" />
        <message clientCredentialType="UserName" algorithmSuite="Default" />
    </security>-->
</binding>

注释代码已由 Visual Studio 创建

连接和更新

现在我们可以创建一个与 Project Server 通信的新 SoapClient:

//Creating a new service client object
ProjectSoapClient projectSvc = new ProjectSoapClient();

//Just if you need to authenticate with another account!
projectSvc.ClientCredentials.Windows.ClientCredential = new NetworkCredential("test", "test", "demo");
projectSvc.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;

现在我已经宣布了两个 Guid,我们知道,我们想要更新什么。其他变量稍后使用,并在代码中注释:

//Guid of my project
Guid myProjectId = new Guid("{610c820f-dc74-476c-b797-1e61a77ed6c6}");

//Guid of the custom field
Guid myCustomFieldId = new Guid("{cd879634-b3ee-44eb-87f7-3063a3523f45}");

//creating a new sessionId and a new jobId
Guid sessionId = Guid.NewGuid(); //the sessionId stays for the whole updating process
Guid jobId = Guid.NewGuid(); //for each job, you give to the server, you need a new one

//indicator if you have to update the project
Boolean updatedata = false;

然后我们准备从服务器加载ProjectDataSet,找到 CustomField 并更新数据。这真的很简单:

  1. 加载 ProjectDataSet
  2. 遍历 CustomFieldsRow
  3. 检查 CustomField 是否与我们的 Guid 匹配
  4. 更新值
  5. 将指标设置为更新
//loading project data from server
//Every change on this dataset will be updated on the server!
ProjectDataSet project = projectSvc.ReadProject(myProjectId, DataStoreEnum.WorkingStore);

//To find your custom field, you have to search for it in the CustomFieldsRow
foreach (ProjectServerCSVImport.PSS.Project.ProjectDataSet.ProjectCustomFieldsRow row in project.ProjectCustomFields)
{
    //check if the GUID is the same
    if (row.MD_PROP_UID == myCustomFieldId)
    {
        //if yes, write it into the container
        row.NUM_VALUE = 12345;

        //and set the indicater
        updatedata = true;
    }
}

如果我们更改了一个值,我们现在必须将 ProjectDataSet 发送到 ProjectServer。它将更新 ProjectDataSet 中更改的值。为此,我们必须检查我们的项目,更新它并再次检查:

//update if you have changed anything
if (updatedata)
{
    //check out the project first
    projectSvc.CheckOutProject(myProjectId, sessionId, "custom field update checkout");

    //send the dataset to the server to update the database
    bool validateOnly = false;
    projectSvc.QueueUpdateProject(jobId, sessionId, project, validateOnly);

    //wait 4 seconds just to be sure the job has been done
    System.Threading.Thread.Sleep(4000);

    //create a new jobId to check in the project
    jobId = Guid.NewGuid();

    //CheckIn
    bool force = false;
    string sessionDescription = "updated custom fields";
    projectSvc.QueueCheckInProject(jobId, myProjectId, force, sessionId, sessionDescription);

    //wait again 4 seconds
    System.Threading.Thread.Sleep(4000);

但现在我们刚刚更新了数据库。服务器仍会向我们显示“旧”值而不是新值。这是因为我们还没有发布我们的项目:

//again a new jobId to publish the project
jobId = Guid.NewGuid();
bool fullPublish = true;
projectSvc.QueuePublish(jobId, myProjectId, fullPublish, null);

//maybe we should wait again ;)
System.Threading.Thread.Sleep(4000);

终于我们完成了,我们的项目也更新了!

增强功能

我对这个平台(Project Server 2010)很陌生,所以这段代码可能不是最好的例子。因此,有一些增强功能可以使解决方案变得更好:

  • Sleep 函数是一个非常糟糕的解决方法,但我找不到一个使用QueueSystem for 2010处理相同事情的示例(如这里) ?!
  • 如果您不知道项目的 Guid,但不知道名称,您可以通过以下函数解决它:
/// <summary>
/// Returns the GUID for a specified project
/// and sets the guid for this class
/// </summary>
/// <param name="client">soap service client</param>
/// <param name="projectname">name of the project</param>
/// <returns>Project GUID</returns>
public Guid GetGuidByProjectName(ProjectSoapClient client, string projectname)
{
    Guid pguid = new Guid();
    ProjectDataSet data = client.ReadProjectList();

    foreach (DataRow row in data.Tables[0].Rows)
    {
        if (row[1].ToString() == projectname) //compare - case sensitive!
        {
            pguid = new Guid(row[0].ToString());
        }
    }

    return pguid;
}
于 2012-02-28T13:25:41.750 回答