ALM Rangers

Использование объектной модели клиента Team Foundation Server

Брайен Блэкмен
Уилли-Питер Шауб

Продукты и технологии:

Visual Studio Team Foundation Server

В статье рассматриваются:

  • важность расширяемости;
  • настройка среды разработки;
  • рекомендации и правила;
  • сборки и пространства имен;
  • подключение к TFS-серверам.

Исходный код можно скачать по ссылке.

В этой статье мы представим объектную модель клиента Visual Studio Team Foundation Server (TFS) и начнем новую серию статей от Visual Studio ALM Rangers, где сосредоточимся на практических рекомендациях и распространенных сценариях кодирования с применением TFS.

Напомним: ALM Rangers — это группа экспертов, которая способствует кооперации группы продуктов Visual Studio, Microsoft Services и сообщества Microsoft Most Valuable Professional (MVP), занимаясь восполнением недостающей функциональности, снимая различные препятствия, мешающие внедрению тех или иных продуктов, и публикуя рекомендации и руководства, основанные на практическом опыте.

Суть Visual Studio TFS заключается в управлении жизненным циклом приложений (application lifecycle management, ALM). Этот продукт позволяет группам вести совместную работу, планировать, отслеживать, проектировать, разрабатывать, компилировать и хранить свои решения — эффективно и безопасно. Он также обеспечивает высокую продуктивность труда и делает доступным ALM профессиональным разработчикам ПО в организациях любых масштабов независимо от того, какой процесс они используют — формальный, динамичный или собственный, а также от того, работают они в виртуальных или тесно связанных группах. В этой статье мы исследуем базовые архитектурные концепции, которые вы должны понимать, чтобы работать с TFS и, что важнее, расширять его функциональность.

Суть Visual Studio TFS заключается в управлении жизненным циклом приложений (ALM).

Почему так важна расширяемость

TFS включает механизмы и точки подключения для расширения существующей функциональности и введения новой. Новая функциональность позволяет адаптировать ALM-решение для TFS под вашу среду и расширять TFS собственной функциональностью и поведениями, не встроенными в стандартный продукт.

TFS является многоуровневым решением, к которому можно обращаться программным способом, используя подходящие объектные модели. Как показано на рис. 1, существуют объектные модели клиента и сервера, которые можно использовать для расширения клиентского или прикладного уровня соответственно. В этой статье мы сосредоточимся на объектной модели клиента.

Архитектура Visual Studio Team Foundation Server
Рис. 1. Архитектура Visual Studio Team Foundation Server

Team Foundation Server Client Клиент Team Foundation Server
Team Foundation Server Team Foundation Server
Client Object Model Объектная модель клиента
Team Foundation Web Services Веб-сервисы Team Foundation
Server Object Model Объектная модель сервера

Хотя технически возможно напрямую обращаться к уровню веб-сервисов или данных, настоятельно рекомендуется делать это только через релевантные объектные модели, показанные на рис. 1.

Давайте сделаем небольшое отступление и рассмотрим идею объектной модели TFS и ее пространств имен, на которые мы будем ссылаться как в этой статье, так и в сопутствующем коде.

Объектная модель — это набор классов, логически распределенных по пространствам имен и физически распределенным по сборкам. Объектная модель TFS-клиента — обобщенный термин, который относится ко всем открытым классам, Доступным в сборках Microsoft.TeamFoundation.*.dll.

Пространства имен организуют TFS-классы и средства в аналогичные элементы, которые можно было бы сравнить с каталожным шкафом. Каждый ящик представляет объектную модель, каждая папка внутри каждого ящика — пространство имен, а содержимое каждой папки — классы. Как и каталожный шкаф, пространство имен позволяет вам разделять классы на категории и в последующем быстрее и легче находить релевантные классы.

Мы займемся созданием клиента, использующего объектную модель TFS для подключения к веб-сервисам TFS. TFS-сервисы поддерживают специфическую функциональность вроде контроля версий, отслеживания рабочих элементов и событий.

Настройка среды разработки

Мы будем использовать язык C# и Visual Studio IDE. С объектной моделью можно работать и на других языках и в других средах, например Windows PowerShell.

Использование объектной модели TFS-клиента в настоящее время требует установки на компьютер разработчика SKU клиента, скажем, Team Explorer. В будущем объектная модель TFS-клиента станет доступной в виде отдельной клиентской подсистемы.

Team Explorer включается во все редакции Visual Studio, кроме Express. После установки Visual Studio и TFS запустите Visual Studio, подключитесь к TFS-серверу и подтвердите, что у вас есть разрешения на выполнение CRUD-операций (create, read, update and delete) с рабочими элементами и системой контроля версий исходного кода.

Для этой статьи и для большей части разработки мы использовали общедоступную виртуальную машину (VM), предоставляемую Брайеном Келлером (Brian Keller) из группы ALM Developer Evangelism Team в Microsoft (для Visual Studio 2010 можно скачать по ссылке bit.ly/VS2010RTMVHD, а для Visual Studio 2012 — по ссылке aka.ms/VS11ALMVM). Если вы скачаете ту же VM, то примеры кода должны просто работать. Если вы используете этот код применительно к своему серверу, то, возможно, потребуются некоторые изменения.

Пространства имен организуют TFS-классы и средства в аналогичные элементы, которые можно было бы сравнить с каталожным шкафом.

Чтобы работать с примерами кода в этой статье, вам понадобятся ссылки на сборки .NET Framework для TFS, которые будут перечислены позже. Вы получаете эти сборки при установке Team Explorer.

Рекомендации и правила

При разработке клиентских приложений с применением объектной модели TFS соблюдайте следующие правила.

Используйте TFS Client API, даже если API вызывает веб-сервисы Прямой доступ к интерфейсам веб-сервисов официально не поддерживается. Объектная модель TFS-клиента помогает с аутентификацией, совместимостью с различными версиями сервера, олицетворением (подменой идентификации), двухэтапной аутентификацией с применением клиентских удостоверений и многими другими вещами в дополнение к обеспечению четких высокоуровневых абстракций поверх интерфейсов веб-сервисов. Для некоторых клиентов (например, для приложения Ruby on Rails, выполняемого в *nix-среде) уровень веб-сервисов является лишь одним из возможных вариантов. Если ваше приложение подпадает под эту категорию, вам стоит проверить Java SDK (bit.ly/irHxgm).

По возможности выполняйте рекурсивные операции вместо перечисления каждого индивидуального элемента Например, удаляйте папку, а не каждый индивидуальный файл в ней. Это правило оформилось на основе того, чему мы в свое время научились у Дона Бокса (Don Box) на его секции на конференции TechEd в Новом Орлеане — тогда он еще носил очень длинные волосы и не работал на Microsoft: «Сетевой трафик — зло». Мы выступали на его секции с докладом по удаленным вызовам процедур. В те годы использовался язык C, но важность его заявления с тех пор ничуть не изменилась. Сетевой трафик — зло! Некоторые разработчики до сих пор не усвоили это либо они учатся этому на своем горьком опыте в общении с заказчиками и консультантами, жалуясь им на плохую производительность при использовании сети.

Общим шаблоном будет подключение к Team Foundation Configuration Server или какому-нибудь набору и перечисление зарегистрированных серверов или проектов.

Чтобы соблюсти мантру «сетевой трафик — зло», объединяйте нерекурсивные операции в пакет и запрашивайте URL-адреса для скачивания, только когда они действительно нужны. В некоторых примерах кода это правило будет игнорироваться в попытке продемонстрировать функциональность API.

При передаче пути в API используйте серверный путь вместо локального Так нужно делать потому, что последний транслируется в серверный путь. Эта трансляция требует идентификации рабочей области вызвавшего, загрузки сопоставления, определения корректного сопоставления и т. д.

Используйте для своих операций оптимистичный шаблон Как и в случае баз данных, исходите из того, что операция записи будет успешной и перехватывайте исключение. Например, в операциях, использующих сервис контроля версий, не тратьте время на проверку элемента перед операцией с ним, так как этот файл может быть удален, а значит, и здесь нужно обрабатывать исключения. Поэтому надейтесь на лучшее, но готовьтесь к худшему.

Еще один полезный инструмент для выявления того, где есть вредный сетевой трафик, — Microsoft Network Monitor. Не кодируйте и не отлаживайте сетевые операции без него. От этого инструмента не ускользнет ни один сетевой пакет, и правда обязательно вскроется. Microsoft Network Monitor можно скачать с сайта Microsoft (bit.ly/mMmieH).

Если вы попали в затруднительное положение и не знаете, почему, как или сколько времени работают те или иные вещи, включайте трассировку для веб-методов Трассировка покажет вам, какие веб-методы вызываются API. Она сообщает такие детали, как, например, что было вызвано, длительность вызова и SOAP-ответ. Трассировка включается модификацией файла .config приложения в разделе system.diagnostics, как показано на рис. 2. Пример вывода, который вы найдете в своем файле журнале, приведен на рис. 3. Однако, если вы хотите изучить полезные данные SOAP, вам потребуется такой инструмент, как Microsoft Network Monitor.

Рис. 2. Включение трассировки в вашем конфигурационном файле

<?xml version ="1.0"?>
  <configuration> 
    <system.diagnostics>
      <switches>
        <add name="TeamFoundationSoapProxy" value="4" />
        <add name="VersionControl" value="4" />
      </switches>
      <trace autoflush="true" indentsize="3">
        <listeners>
          <add name="rangerListener"    
            type="Microsoft.TeamFoundation.TeamFoundationTextWriterTraceListener,
            Microsoft.TeamFoundation.Common, Version=10.0.0.0, Culture=neutral,
            PublicKeyToken=b03f5f7f11d50a3a"
            initializeData="c:\almrangertracing.log" />
          <add name="performanceListener" 
            type="Microsoft.TeamFoundation.Client.PerfTraceListener,
            Microsoft.TeamFoundation.Client, Version=10.0.0.0, Culture=neutral,
            PublicKeyToken=b03f5f7f11d50a3a" />
        </listeners>
      </trace>
    </system.diagnostics>
  </configuration>

Рис. 3. Трассировка веб-метода с данными по производительности

03/17/2012 12:10:14 (pid 2936, tid 4820, 11636 ms) Web method response: [http://servername/tfs/myCollection/VersionControl/v1.0/repository.asmx] QueryWorkspace[VersionControl] 3 ms
03/17/2012 12:10:14 (pid 2936, tid 4820, 11637 ms) CreateWebRequest() -- Uri: http://servername:8080/tfs/myCollection/VersionControl/v1.0/repository.asmx
03/17/2012 12:10:14 (pid 2936, tid 4820, 11637 ms) request.AutomaticDecompression: GZip
03/17/2012 12:10:14 (pid 2936, tid 4820, 11637 ms) Web method running:
http://servername:8080/tfs/myCollection/VersionControl/v1.0/repository.asmx] UpdateWorkspace[VersionControl]
03/17/2012 12:10:14 (pid 2936, tid 4820, 11658 ms) HTTP headers:
Content-Length: 896
Cache-Control: private, max-age=0
Content-Type: application/soap+xml; charset=utf-8
Date: Sat, 17 Mar 2012 16:10:12 GMT
Server: Microsoft-IIS/7.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET

Сборки и пространства имен

Объектная модель TFS предоставляет доступ ко множеству сборок и пространств имен. Не все сборки и пространства имен будут охвачены в этой серии статей — только самые важные и часто используемые. В дополнение к распространенным пространствам имен TFS, мы перечислим базовые пространства имен .NET, от которых зависит объектная модель TFS.

Общим шаблоном будет подключение к Team Foundation Configuration Server или какому-нибудь набору и перечисление зарегистрированных серверов или проектов. Эти распространенные задачи на клиенте требуют следующих ссылок:

// Необходимо для TfsConfigruationServer
using Microsoft.TeamFoundation.Client;
// Необходимо для Catalog Resources, например для типов
using Microsoft.TeamFoundation.Framework.Common;
// Необходимо для другие Catalog Resources, таких как узлы
using Microsoft.TeamFoundation.Framework.Client;
// Необходимо для использования Version Control Service
using Microsoft.TeamFoundation.VersionControl.Client;

Использование каждого из доступных сервисов потребует тех же ссылок, таких как Microsoft.TeamFoundation.VersionControl.Client для Version Control Service. Операции с рабочими элементами могут потребовать ссылок на:

  • Microsoft.TeamFoundation.WorkItemTracking.Client;
  • Microsoft.TeamFoundation.WorkItemTracking.Common;
  • Microsoft.TeamFoundation.WorkItemTracking.Proxy.

В табл. 1 показаны основные сборки, которые включены в TFS SDK и находятся в Program Files\Microsoft Visual Studio 10.0\Common7\IDE в папках ReferenceAssemblies\v2.0 и PrivateAssemblies для TFS 2010 (или в Program Files (X86)\... в 64-разрядных ОС).

Табл. 1. Сборки TFS SDK

Пространство имен

o = Microsoft.TeamFoundation

Описание
o.client Пространство имен и связанные сборки предоставляют интерфейсы для подключения к TFS и доступа к данным, относящимся к групповым проектам и наборам группового проекта
o.framework.client Пространство имен и связанные сборки предоставляют API для просмотра и управления содержимым реестра TFS, запланированным заданиям, хранилищу обобщенных свойств (generic property store), подпискам на события, пространствам имен защиты, сервисам, наборам группового проекта, каталогу и объектам Lab Management
o.framework.common Пространство имен и связанные сборки определяют общие объекты, такие как разрешения, исключения и константы

(Примечание: предоставленные нами примеры кода по умолчанию скомпилирован и протестирован с объектной моделью TFS 2010, при этом сборки извлекались из …\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ReferenceAssemblies\v2.0. Чтобы задействовать новую объектную модель из бета-версии TFS 11, просто удалите ссылки на сборки Microsoft.TeamFoundation.* и заново добавьте их из …Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\ReferenceAssemblies\v2.0, а затем повторно скомпилируйте приложения-примеры. Вы можете использовать любую из объектных моделей для подключения к серверам TFS 2010 и 2012 с помощью примеров по умолчанию.)

Если вас интересует законченное решение-пример и дополнительные образцы кода от Visual Studio ALM Rangers или если вы хотели бы сами внести вклад в примеры кода, пожалуйста, заходите к нам на сайт bit.ly/M0oyQt.

Наше первое приключение в программировании

Напомню, что для подключения к TFS-серверу вам потребуются следующие ссылки:

using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Common;
using Microsoft.TeamFoundation.Framework.Client;

У вас также может быть зависимость от пространства имен System.Net, если вы передаете сетевые удостоверения в какие-нибудь перегруженные методы, как показано в примере кода ниже:

NetworkCredential myNetCredentials =
  new NetworkCredential("Administrator", "P2ssw0rd");
ICredentials myCredentials = (ICredentials)myNetCredentials;

NetworkCredential полезны, если вы используете общедоступную TFS VM. После размещения ссылок вы можете подключиться к TFS-серверу несколькими способами. Можно использовать сервер конфигурации, где вы получаете список наборов, передаваемых в URI вашего сервера, и удостоверения:

Uri tfsUri = @"http://servername:8080/tfs";
TfsConfigurationServer configurationServer =
  new TfsConfigurationServer(tfsUri, myCredentials);

Более эффективный способ — запросить удостоверения у пользователя, передав UICredentialsProvider:

TfsConfigurationServer configurationServer =
  new TfsConfigurationServer(tfsUri, new UICredentialsProvider());

Второй подход: подключение к новому серверу конфигурации

Рассмотрим альтернативный подход, когда вы выполняете процесс под должными удостоверениями и хотите избежать подключения к новому серверу конфигурации:

TfsConfigurationServerFactory.GetConfigurationServer(tfsUri);
// Установив соединение, можно получить список наборов
// на сервере. Получаем каталог наборов группового проекта.
ReadOnlyCollection<CatalogNode> collectionNodes;
collectionNodes = configurationServer.CatalogNode.QueryChildren(
  new[] { CatalogResourceTypes.ProjectCollection },
  false, CatalogQueryOptions.None);
foreach (CatalogNode collectionNode in collectionNodes)
{
  // Добавляем каждый набор в поле со списком
  cbTPC.Items.Add(collectionNode.Resource.DisplayName);
}

В предыдущем примере от вас требуется ввести URI в поле ввода в диалоге. В следующем примере мы получим на клиенте список зарегистрированных серверов. Зарегистрированными считаются TFS-серверы, добавленные в Visual Studio через его диалоговое окно Connect to Team Foundation Server, как показано на рис. 4.

Диалоговое окно с зарегистрированными TFS-серверами
Рис. 4. Диалоговое окно с зарегистрированными TFS-серверами

Чтобы прочитать на клиенте список зарегистрированных серверов, вам понадобится ссылка на Microsoft.TeamFoundation.Client. В следующем коде клиент считывает зарегистрированные серверы и добавляет их в поле со списком (показано на рис. 5):

List<RegisteredProjectCollection> registeredTPCs;
// Получаем все зарегистрированные на этом компьютере наборы
registeredTPCs = new
  List<RegisteredProjectCollection>((
    RegisteredTfsConnections.GetProjectCollections()));
foreach (var projectCollection in registeredTPCs)
{
  // Добавляем каждый зарегистрированный набор
  // группового проекта в поле со списком
  cbRegColl.Items.Add(projectCollection.Uri);
}

Чтение зарегистрированных серверов
Рис. 5. Чтение зарегистрированных серверов

Третий подход: подключение по известному URI набора

Если вы знаете URI набора, то можете подключиться к нему напрямую. На рис. 6 показан этот третий подход.

Рис. 6. Подключение по известному URI набора

NetworkCredential myNetCredentials =
  new NetworkCredential("Administrator", "P2ssw0rd");
ICredentials myCredentials = (ICredentials)myNetCredentials;
// Подключаемся к tpc, на котором размещен
// репозитарий сервиса контроля версий
TfsTeamProjectCollection tpc =
  new TfsTeamProjectCollection(new Uri(cb.Text),
  myNetCredentials);
// Получаем сервис контроля версий
vcServer = tpc.GetService<VersionControlServer>();
var teamProjects =
  new List<TeamProject>(vcServer.GetAllTeamProjects(false));
// Перечисляем групповые проекты в наборе
// и добавляем в поле со списком
foreach (TeamProject projectNode in teamProjects)
{
  // Добавляем список или групповые проекты в окно списка
  lbProjects.Items.Add(projectNode.Name);
}

Следующий пример демонстрирует использование некоторых средств сервиса контроля версий. Когда у вас есть ссылки на сервер и ссылка на сервис контроля версий (рис. 6), вы можете использовать некоторые API, например для получения списка файлов на сервере или незавершенных изменений. В коде, приведенном ниже, ссылка на сервер контроля версий используется для запроса всех XAML-файлов на сервере, которые потом добавляются в окно списка:

// Перечисляем все XAML-файлы на сервере
ItemSet items = vcServer.GetItems("$/*.xaml", RecursionType.Full);
foreach (Item item in items.Items)
{
  // Добавляем каждый файл в окно списка
  lbAll.Items.Add(item.ToString());
}

Первый параметр метода GetItems — путь к папке. В примере кода этот путь является корнем, и будут возвращаться все XAML-файлы во всех папках. На рис. 7 видно, что при выборе одного из этих файлов показываются детальные сведения о выбранном файле.

Получаем все XAML-файлы и показываем детальные сведения о выбранном файле
Рис. 7. Получаем все XAML-файлы и показываем детальные сведения о выбранном файле

Если вы хотите увидеть список файлов с незавершенными изменениями и добавить их в окно списка, используйте код, как на рис. 8. В этом коде API-метод QueryPendingSets перегружен, и этот пример использует перегруженную версию метода, которая позволяет запрашивать файлы на основе ItemSpecs (это массив, представляющий то, что нужно запросить). В данном случае мы запрашиваем незавершенные изменения только для одной папки на сервере. Мы также фильтруем незавершенные изменения для конкретной рабочей области и конкретного пользователя. Последний параметр указывает API предоставить нам информацию в таком виде, чтобы мы могли получить файл. Если у вас нет планов использовать эту информацию, перечитайте мантру «сетевой трафик — зло» и передайте false.

Помимо подключения к серверу, если известен URI набора, можно подключиться к набору напрямую.

Рис. 8. Получение PendingChanges

ItemSpec[] itemSpecs = new ItemSpec[1];
// Можно фильтровать путь к проекту и папке, используя
// $/ProjectName/Folder...
ItemSpecs[0] =
  new ItemSpec(@"$/Tailspin Toys/Development/Iteration 2",
  RecursionType.Full);
// Ваши критерии фильтрации - Workspace Name,
// User Name и предыдущий путь в ItemSpec
String qryWSName = @"WIN-GS9GMUJITS8";
String queryUserName = @"administrator";
bool includeDownloadInfo = true;
PendingSet[] pendingSet = vcServer.QueryPendingSets(
  itemSpecs, qryWSName, qryUserName, includeDownloadInfo);
foreach (PendingSet ps in pendingSet)
{
  // Добавляем незавершенные изменения в окно списка
  lbPendingChanges.Items.Add(ps.ToString());
}

Сервис контроля версий обеспечивает намного больше возможностей, о которых мы ничего не сказали в этой статье. Мы лишь попытались вызвать у вас интерес и показали, как подключаться к серверу и использовать сервис контроля версий.

В будущих статьях мы продолжим изучение объектной модели TFS-клиента и ознакомим вас с другими сценариями программированиями, такими как операции над рабочими элементами, управление версиями, выполнение сборочных операций и более глубокая интеграция через объектную модель TFS-сервера в Visual Studio.


Брайен Блэкмен (Brian Blackman)ведущий консультант в группе Microsoft Services Partner ISV, уделяет основное внимание успешной работе ISV-партнеров в технологиях и на рынке. Обладатель MBA, CSM, CSP, MCSD (C++), MCTS и Visual Studio ALM Core Ranger. Занимается написанием кода, созданием и поставкой инструментальных пакетов, консалтингом и всеми вещами, относящимися к ALM.

Уилли-Питер Шауб (Willy-Peter Schaub)старший менеджер программ в Visual Studio ALM Rangers в Microsoft Canada Development Center. Еще с середины 80-х стремился к простоте использования и удобству сопровождения ПО. Читайте его блог blogs.msdn.com/b/willy-peter_schaub и следите за его заметками в twitter.com/wpschaub.

Выражаем благодарность за рецензирование статьи экспертам Джеффу Брэмвеллу (Jeff Bramwell), Биллу Эссери (Bill Essary), Майку Фури (Mike Fourie), Бижану Джавиди (Bijan Javidi), Джиму Лэму (Jim Lamb) и Патриции Вагнер (Patricia Wagner).