Настройка пользовательских полей с помощью PSI - Microsoft Project Server - PullRequest
1 голос
/ 24 февраля 2012

Я новичок в разработке Project Server, и мне было интересно, можно ли использовать PSI для установки значений настраиваемых полей ресурса.

Я не могу найти информацию для начинающего в этом.

В настоящее время у меня настроены веб-ссылки для пользовательских полей и веб-службы ресурсов, но я не уверен, как настроить настраиваемое поле для определенного ресурса.

Любая помощь будет очень признательна!

Спасибо!

1 Ответ

6 голосов
/ 28 февраля 2012

Я знаю вашу проблему.У Microsoft действительно плохие примеры на MSDN.Многие вещи не работают или только что скопированы из руководства 2007 года.Вчера я начал разрабатывать с Webservice для Project Server 2010.

Вот простое (возможно, не лучшее) решение для настройки пользовательских полей:

Полный исходный код:http://pastebin.com/tr7CGJsW

Подготовьте ваше решение

Сначала я добавил ссылку на сервис:

http: // имя_сервера / 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

Подключите иОбновление

Теперь мы можем создать новый SoapClient, который связывается с Project Server:

//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;

Теперь я объявил две Guids, которые мы знаем, что мы хотим обновить.Другие переменные используются позже и являются комментарием в коде:

//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 для 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;
}
...