1

Project Server の開発は初めてで、PSI を使用してリソースのカスタム フィールド値を設定できるかどうか疑問に思っていました。

これでは初心者向けの情報が見つからないようです。

現在、CustomFields と Resource Web サービスの Web 参照を設定していますが、特定のリソースにカスタム フィールドを設定する方法がわかりません。

どんな助けでも本当に感謝します!

ありがとう!

4

1 に答える 1

6

私はあなたの問題を知っています。Microsoft は、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;

これで、更新したいものを知っている 2 つの 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 関数は非常に悪い回避策ですが、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;
}
于 2012-02-28T13:25:41.750 に答える