使用PSI设置自定义字段 - Microsoft Project Server

时间:2012-02-23 21:07:40

标签: custom-fields project-server psi ms-project-server-2010

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

我似乎无法在此找到初学者的任何信息。

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

任何帮助都会非常感激!

谢谢!

1 个答案:

答案 0 :(得分:6)

我知道你的问题。微软在MSDN上有很糟糕的例子。许多东西不起作用或刚从2007手册中复制过。我昨天开始使用Project Server 2010的Webservice进行开发。

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

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

准备解决方案

首先,我已将服务参考添加到:

  

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

Service Reference

之后,我编辑了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. 进行迭代
  4. 检查CustomField是否与我们的Guid匹配
  5. 更新值
  6. 将指标设置为更新
  7. //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);
    

    但现在我们刚刚更新了数据库。服务器仍然会向我们显示&#34; old&#34;价值而不是新的价值。这是因为我们还没有发布我们的项目:

    //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)很陌生,所以这段代码可能不是最好的例子。因此,有一些增强功能可以使解决方案更好:

    • 睡眠功能是一个非常糟糕的解决方法,但我找不到一个处理相同的事情(like here)和2010年QueueSystem的示例?!
    • 如果您不了解项目的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;
    }