Настройка пользовательских полей с помощью PSI - Microsoft Project Server
Я новичок в разработке Project Server и мне было интересно, если вы можете использовать PSI для установки значений настраиваемых полей ресурса.
Я не могу найти информацию для новичка в этом.
В настоящее время у меня есть веб-ссылки, настроенные для пользовательских полей и веб-службы ресурсов, но я не уверен, как установить настраиваемое поле для определенного ресурса.
Любая помощь могла бы быть полезна!
Спасибо!
1 ответ
Я знаю твою проблему. У Microsoft действительно плохие примеры на MSDN. Многие вещи не работают или только что скопированы из руководства 2007 года. Вчера я начал работать с Webservice для Project Server 2010.
Вот простое (возможно, не лучшее) решение для настройки пользовательских полей:
Полный исходный код: 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
Подключение и обновление
Теперь мы можем создать новый 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;
Теперь я объявил двух гидов, что мы знаем, что мы хотим обновить. Другие переменные используются позже и являются комментарием в коде:
//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 и обновить данные. Это действительно просто:
- загрузка ProjectDataSet
- итерация через CustomFieldsRow
- проверка соответствия CustomField нашему Guid
- обновление значения
- установка индикатора для обновления
//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;
}